简介本资源是一份面向计算机、电子信息工程及数学等专业本科生的分层强化学习HRL算法实践材料聚焦课程设计、期末大作业与毕业设计场景提供可直接运行的Matlab实现方案。压缩包共4个文件2个核心m脚本、1张算法效果示意图png、1份说明文档md总大小仅28KB轻量易部署其中HRL_4rooms.m与flatRL_4rooms.m分别实现分层与扁平化强化学习在四房间任务中的对比验证代码采用参数化设计关键超参清晰标注、逻辑模块分明、注释详尽便于理解算法架构与调优思路。目前已有104人学习下载读者可快速复现经典HRL实验流程掌握状态抽象、子目标设定、选项策略训练等核心环节并通过README.md明确项目结构与运行指引显著降低入门门槛与调试成本。1. 分层强化学习不是“把算法叠高”而是让Matlab跑出可解释、可中断、可复用的决策结构你手头有个控制任务机械臂要从杂乱桌面抓取目标物体但直接用DQN或PPO训练策略网络总在“要不要抬腕”和“该不该旋转基座”之间反复震荡训练曲线抖得像心电图收敛慢、泛化差、调试时连哪一层出错都难定位。这时候“分层强化学习”不是锦上添花的炫技而是工程落地的刚需——它把一个复杂任务拆成高层策略比如“先清障→再定位→最后抓取”和底层控制器比如“关节角速度PID调节”让高层决定“做什么”底层专注“怎么做”。Matlab实现的关键不在代码行数而在如何用其内置的强化学习工具箱Reinforcement Learning Toolbox原生支持的分层架构Hierarchical RL、状态抽象机制State Abstraction和子任务终止条件Subtask Termination来构建可验证的层级关系。本文面向已掌握Matlab基础强化学习如SAC、TD3但卡在多级任务建模的工程师不讲论文推导只讲怎么在R2023b及以上版本中用rlAgent、rlLayeredAgent和自定义rlFunctionEnvironment三者配合把“高层选选项、底层执行动作”的闭环跑通、调稳、查得清。2. 用rlLayeredAgent构建双层结构高层选宏动作底层执行原始动作分层强化学习在Matlab中并非靠手动拼接两个独立agent而是依赖rlLayeredAgent这一原生类型它强制定义了“高层agent输出选项option底层agent接收该选项并生成实际控制信号”的数据流。这种设计避免了传统手动切换agent带来的状态同步漏洞和奖励泄漏问题。2.1 高层agent用选项策略Option Policy替代离散动作空间高层不直接输出电机电压而是输出一组预定义的宏动作macro-action例如{move_to_bin_A, move_to_bin_B, grasp_object}。每个宏动作对应一个子任务目标其完成条件由终止函数Termination Function判定。Matlab中需用rlOptionPolicy封装高层策略% 定义高层状态空间仅包含任务相关抽象特征如目标物相对位置、障碍物分布编码 highLevelObsInfo rlNumericSpec([3 1],LowerLimit,[-1;-1;0],UpperLimit,[1;1;1]); % 高层动作空间3个宏动作索引1/2/3 highLevelActInfo rlFiniteSetSpec({move_to_bin_A,move_to_bin_B,grasp_object}); % 使用SAC算法训练高层因宏动作间存在强时序依赖SAC的熵正则化更稳定 highLevelAgentOpts rlSACAgentOptions(... DiscountFactor,0.99,... ExperienceHorizon,1000,... NumStepsToLookAhead,3); % 提前看3步适应宏动作持续时间不确定性 highLevelAgent rlSACAgent(... rlRepresentation(rlNetworkGenerator(actor-critic,Observation,highLevelObsInfo,Action,highLevelActInfo)),... highLevelObsInfo,highLevelActInfo,highLevelAgentOpts);提示高层状态必须做抽象——不能传入原始图像像素或全部关节角度。常见做法是用rlFeatureExtractor提取目标距离、夹爪开合度、碰撞标志等35维语义特征。若传入100维原始状态高层会学成“记忆回放器”失去分层意义。2.2 底层agent为每个宏动作绑定专属控制器底层agent不是单一网络而是按宏动作动态切换的控制器集合。Matlab通过rlLayeredAgent的SubAgent字段实现每个子agent对应一个宏动作其输入是原始环境状态高层指令输出是具体执行动作如6轴电机PWM值。% 为宏动作move_to_bin_A定义底层agent使用TD3因连续控制更稳定 lowLevelObsInfo rlNumericSpec([12 1]); % 原始状态6关节角6角速度 lowLevelActInfo rlNumericSpec([6 1],LowerLimit,-1,UpperLimit,1); % 6维扭矩输出 % 构建子agent每个子agent独立训练共享底层网络结构但权重不同 subAgents rlAgentVector(3); % 对应3个宏动作 for i 1:3 subAgents(i) rlTD3Agent(... rlRepresentation(rlNetworkGenerator(actor-critic,Observation,lowLevelObsInfo,Action,lowLevelActInfo)),... lowLevelObsInfo,lowLevelActInfo,... rlTD3AgentOptions(DiscountFactor,0.995)); end % 绑定子agent到rlLayeredAgent layeredAgent rlLayeredAgent(highLevelAgent, subAgents);2.2.1 关键参数SubTaskTermination决定何时交还控制权底层agent不能无限执行。当宏动作完成如机械臂到达bin_A上方±2cm内必须触发终止并返回高层。Matlab要求显式定义终止函数% 为move_to_bin_A宏动作定义终止条件末端执行器与bin_A中心距离0.02m terminationFcn (obs) norm(obs(1:3) - binA_position) 0.02; subTaskTerm rlSubTaskTermination(terminationFcn); layeredAgent.SubTaskTermination{1} subTaskTerm; % 绑定到第1个子agent注意终止函数必须基于当前观测obs不可依赖内部计时器。Matlab在每步仿真后自动调用该函数返回true即切换回高层。若误用step_count 100类逻辑会导致跨episode状态污染。2.3 环境接口用rlFunctionEnvironment实现状态分流标准rlSimulinkEnv或rlMATLABFunctionEnv无法天然支持“高层看抽象状态、底层看原始状态”。必须自定义环境函数在reset和step中按需裁剪观测function [nextObs, reward, isDone, nextInfo] hierarchicalEnvStep(obs, action, info) % obs是完整原始状态12维 % action来自高层1×1整数宏动作索引或来自底层6×1连续向量 if info.IsHighLevelAction % 标记当前动作来源 % 高层动作仅更新任务状态不执行物理动作 nextObs abstractState(obs); % 提取3维抽象特征 reward 0; % 宏动作本身无即时奖励 isDone false; else % 底层动作执行物理控制更新真实状态 nextObs physicsStep(obs, action); % 调用动力学模型 reward computeReward(nextObs); % 基于原始状态计算奖励 isDone checkTaskDone(nextObs); % 如目标被抓取且稳定 end end3. 训练流程分阶段初始化联合微调避免高层被底层噪声淹没直接端到端训练rlLayeredAgent极易失败——高层策略在底层尚未学会基本运动时会因持续收到零奖励而崩溃。必须采用三阶段训练法每阶段保存检查点确保可回溯。3.1 阶段一单独训练所有底层agent冻结高层先关闭高层学习仅训练3个子agent使其能可靠完成各自子任务% 冻结高层策略不更新其网络权重 highLevelAgent.Options.LearnRate 0; % 创建专用训练环境固定高层指令只让底层执行 trainEnv rlFunctionEnvironment(hierarchicalEnvReset, hierarchicalEnvStep); trainEnv.Specification.HighLevelAction 1; % 强制执行move_to_bin_A % 训练子agent1对应宏动作1 trainOpts rlTrainingOptions(... MaxEpisodes, 500,... StopTrainingCriteria, AverageReward,... StopTrainingValue, 950,... % 子任务成功奖励设为1000 ScoreAveragingWindowLength, 20); trainAgent(subAgents(1), trainEnv, trainOpts);3.1.1 验证底层稳定性用rlSimulation注入扰动训练后必须验证底层抗干扰能力而非仅看收敛曲线% 在bin_A任务中人为添加关节摩擦突变 simEnv rlFunctionEnvironment(hierarchicalEnvReset, hierarchicalEnvStep); simEnv.Specification.HighLevelAction 1; simEnv.Specification.AddFrictionDisturbance true; % 自定义扰动开关 sim rlSimulation(simEnv, subAgents(1)); simResult sim.run(EpisodeCount, 10); % 检查每集成功率末端位置误差2cm的帧数占比 successRate mean(cellfun((x) sum(x.PositionError 0.02)/length(x.PositionError), simResult)); assert(successRate 0.92, 底层agent抗扰动不足需重训);3.2 阶段二冻结底层训练高层策略此时所有子agent已具备基础能力高层可开始学习任务编排% 解冻高层冻结所有子agent highLevelAgent.Options.LearnRate 1e-4; for i 1:3 subAgents(i).Options.LearnRate 0; end % 全任务环境高层自由选择宏动作 fullEnv rlFunctionEnvironment(hierarchicalEnvReset, hierarchicalEnvStep); % 高层奖励设计关键必须包含稀疏任务奖励稠密子任务完成奖励 % 否则高层会陷入“永远选择简单宏动作”的局部最优 trainOpts.HighLevelRewardFcn (obs,act,nextObs) ... (taskSuccess(nextObs) * 1000) ... % 全局成功奖励 (subTaskDone(nextObs,act) * 200); % 子任务即时奖励鼓励推进 trainAgent(layeredAgent, fullEnv, trainOpts);3.2.1 高层奖励陷阱避免“奖励劫持”若仅给全局成功奖励如抓取后1000高层会倾向于选择低风险但无效的宏动作如反复执行move_to_bin_A。必须加入子任务完成奖励但需满足不可重复领取同一宏动作完成一次后后续执行不再给分衰减设计子任务延迟完成时奖励线性衰减如max(0, 200 - 5*steps)负向惩罚宏动作超时未完成扣分如-10 per step。Matlab中通过info结构体传递子任务状态确保奖励计算有据可依。3.3 阶段三联合微调Learning Rate Decay策略解冻全部网络但大幅降低学习率防止底层已学策略被破坏% 高层学习率降为1e-5底层降为1e-6 highLevelAgent.Options.LearnRate 1e-5; for i 1:3 subAgents(i).Options.LearnRate 1e-6; end % 微调训练轮次严格限制通常≤100集 fineTuneOpts rlTrainingOptions(... MaxEpisodes, 80,... Verbose, false); trainAgent(layeredAgent, fullEnv, fineTuneOpts);4. 调试与可视化用rlDataStore解析层级决策流定位“卡在中间层”的根因训练完成后90%的问题不出在算法而出在状态抽象失准或终止条件过松。Matlab的rlDataStore可导出每步的完整决策链这是排查分层失效的核心工具。4.1 导出分层轨迹数据捕获高层选择、底层执行、终止触发全链路% 创建带日志功能的仿真环境 logEnv rlFunctionEnvironment(hierarchicalEnvReset, hierarchicalEnvStep); logEnv.Specification.EnableLogging true; % 开启详细日志 sim rlSimulation(logEnv, layeredAgent); simResult sim.run(EpisodeCount, 1); % 提取分层决策日志 trajectory rlDataStore(simResult.Data); % 关键字段 % trajectory.HighLevelAction —— 每步高层选择的宏动作索引 % trajectory.LowLevelAction —— 对应底层输出的实际动作向量 % trajectory.SubTaskTerminated —— 是否触发子任务终止1/0 % trajectory.Reward —— 该步获得的奖励值4.1.1 诊断“高层死循环”统计宏动作切换频率若高层长期卡在同一个宏动作如连续50步选move_to_bin_A说明终止条件未触发或底层执行失败% 统计宏动作序列 hlSeq trajectory.HighLevelAction; switchPoints find(diff(hlSeq) ~ 0); % 找到切换点 if isempty(switchPoints) || mean(diff(switchPoints)) 30 warning(高层宏动作切换间隔过长检查子任务终止函数); % 可视化底层执行效果 plot(trajectory.Time, trajectory.LowLevelAction(:,1)); title(底层关节1扭矩输出 —— 若持续为0说明底层未响应); end4.2 可视化层级状态转移用状态空间投影发现抽象失效高层状态空间应呈现清晰聚类——同类宏动作对应的状态点应聚集。若move_to_bin_A和grasp_object的状态向量混杂说明抽象特征提取失败% 提取高层观测抽象状态和对应宏动作标签 highObs trajectory.HighLevelObservation; % 3×N矩阵 labels trajectory.HighLevelAction; % 1×N向量 % PCA降维可视化 pcaModel pca(highObs); reduced highObs * pcaModel(:,1:2); % 投影到前2主成分 gscatter(reduced(:,1), reduced(:,2), labels, rgb, o, 10, filled); legend(move_to_bin_A,move_to_bin_B,grasp_object); xlabel(PC1); ylabel(PC2); title(高层状态空间PCA投影 —— 理想情况三簇分离); % 若簇间重叠严重需重构抽象特征如增加目标物置信度维度4.2.1 实时监控技巧用rlPlotEpisode叠加层级事件标记在训练过程中实时观察高层决策与底层执行的对齐度% 自定义绘图函数在reward曲线中标记宏动作切换点 figure; rlPlotEpisode(simResult, Reward); hold on; switchIdx find(diff(trajectory.HighLevelAction) ~ 0); yline(max(simResult.Reward)*0.8, --r, 宏动作切换); plot(trajectory.Time(switchIdx), simResult.Reward(switchIdx), rx, MarkerSize, 12); xlabel(Time (s)); ylabel(Reward); legend(Episode Reward,Macro-action Switch,Location,northwest);5. 工程部署优化将训练好的分层agent导出为独立函数脱离工具箱依赖训练完成的rlLayeredAgent对象体积大、依赖Reinforcement Learning Toolbox无法直接部署到嵌入式设备。必须将其转化为纯函数调用仅依赖基础Matlab Runtime。5.1 提取核心推理逻辑用generatePolicyFunction生成无工具箱代码Matlab提供generatePolicyFunction将agent网络导出为.m文件但rlLayeredAgent需分两步处理% 步骤1导出高层策略函数 generatePolicyFunction(highLevelAgent, highLevelPolicy, ... OutputFolder, ./deploy/, ... IncludeSupportFiles, false); % 步骤2为每个子agent导出底层策略 for i 1:3 generatePolicyFunction(subAgents(i), [lowLevelPolicy_,num2str(i)], ... OutputFolder, ./deploy/, ... IncludeSupportFiles, false); end生成的highLevelPolicy.m包含predict函数输入抽象状态输出宏动作索引lowLevelPolicy_1.m等同理。这些函数仅调用feval和基础矩阵运算无需任何工具箱。5.2 构建轻量级推理引擎用结构体封装状态机逻辑最终部署代码需模拟rlLayeredAgent的运行时状态管理% 部署结构体存储当前宏动作、子任务计时器、状态缓存 deployState struct(... CurrentOption, 1,... SubTaskStepCount, 0,... LastHighLevelObs, zeros(3,1),... TerminationThreshold, 0.02); function [action, deployState] hierarchicalInference(rawObs, deployState) % 1. 提取抽象状态 highObs abstractState(rawObs); % 2. 高层决策仅当上一宏动作完成或超时 if deployState.SubTaskStepCount 0 || ... (deployState.SubTaskStepCount 200 rand 0.1) % 超时随机重选 deployState.CurrentOption highLevelPolicy(highObs); deployState.SubTaskStepCount 1; deployState.LastHighLevelObs highObs; else deployState.SubTaskStepCount deployState.SubTaskStepCount 1; end % 3. 底层执行调用对应子agent switch deployState.CurrentOption case 1 action lowLevelPolicy_1([rawObs; highObs]); % 原始抽象状态拼接 case 2 action lowLevelPolicy_2([rawObs; highObs]); case 3 action lowLevelPolicy_3([rawObs; highObs]); end % 4. 检查终止此处用简化版欧氏距离实际部署用C函数加速 if norm(rawObs(1:3) - binPosition(deployState.CurrentOption)) deployState.TerminationThreshold deployState.SubTaskStepCount 0; % 重置计时器 end end提示abstractState函数必须与训练时完全一致如归一化参数硬编码否则部署效果归零。建议将归一化常数写入结构体字段而非全局变量。5.3 性能压测用profile定位Matlab部署瓶颈在目标硬件如Intel Core i5嵌入式PC上实测单步推理耗时% 预热 for i 1:100, hierarchicalInference(rand(12,1), deployState); end % 正式压测 tic; for i 1:1000 obs rand(12,1); [act, deployState] hierarchicalInference(obs, deployState); end latency toc / 1000 * 1000; % ms fprintf(平均单步延迟: %.2f ms\n, latency); % 若10ms用profile分析热点 profile on; for i 1:100, hierarchicalInference(rand(12,1), deployState); end profile viewer; % 重点关注abstractState和网络预测函数——这两处最可能成为瓶颈将abstractState中耗时的图像处理替换为查表法或把神经网络预测用codegen转为C MEX可将延迟压至3ms内。本文还有配套的精品资源点击获取