十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Matlab强化学习实战:从零训练一级倒立摆全流程指南

Matlab强化学习实战:从零训练一级倒立摆全流程指南 简介一个基于MATLAB的强化学习倒立摆仿真程序包面向自动化、人工智能方向的初学者与研究人员用于解决一级倒立摆的平衡控制问题。压缩包内共2个文件均为.m源代码整体大小4KB其中一份负责倒立摆动力学建模另一份实现强化学习训练与仿真流程适合在MATLAB中直接运行和二次开发。资源已有1569人学习代码精简无冗余依赖便于拆解状态空间、动作空间、奖励函数及策略更新等核心环节。通过学习该程序读者可掌握用Q学习等强化学习算法处理经典非线性控制问题的完整思路也可在此基础上修改奖励函数或换用DQN等深度强化学习方法是快速上手强化学习项目实践的不错示例。 如果你问我强化学习入门最值得复现的第一个项目是什么我肯定会说倒立摆。没有别的理由就因为它能用最短的时间让你跑通强化学习的完整链路——环境、智能体、训练、评估而且效果极其直观一根杆子立在小车上智能体从随机乱晃到慢慢稳住整个过程肉眼可见比对着公式空想有意思多了。这篇记录的是我在Matlab里用强化学习训练一级倒立摆的实操全过程覆盖方案选型、环境搭建、智能体配置、训练调参和问题排查。适合正在做课程设计或毕业设计的学生也适合刚接触强化学习、想在仿真环境里快速验证算法效果的工程师。我的做法是直接用Matlab的Reinforcement Learning Toolbox来搭环境和智能体整个流程尽量贴近真实项目里“从零到能跑、再调优到能用”的节奏每一个关键地方的原理和坑都会讲到你照着操作基本不会卡在半路。1. 整体思路与方案选型1.1 为什么选Matlab而不是Python现在一聊强化学习很多人第一反应就是Python加OpenAI Gym之类框架。这个路线确实主流但不代表它是所有场景的最优解。对于倒立摆这个具体问题Matlab的优势相当明显。首先是环境成本低。OpenAI Gym里倒立摆确实也有但你得先配Python环境、装gym、处理不同版本的接口差异运气不好光装环境就能折腾半天。Matlab这边一行命令拿到CartPole环境不用解决任何依赖问题。其次是可视化方便训练过程中可以直接看到小车的实时动画也能通过工具箱自带的绘图函数观察每个episode的奖励曲线这对理解算法行为、定位训练问题非常有帮助。再者是算法切换成本低。Matlab的强化学习工具箱把DQN、DDPG、PPO、TD3这些常见算法都封装成了统一的智能体接口换算法就是改几行配置。做课程设计或者算法对比实验的时候这个优势会被放大得很明显。如果项目后续要往硬件部署走Matlab还可以用Simulink生成C代码同一个控制策略直接落到嵌入式控制器上前后衔接非常顺。所以我觉得在倒立摆这类教学和验证场景里Matlab是比Python更省心的选择。1.2 算法选型离散动作用DQN连续动作用DDPG或TD3倒立摆控制的难点在于系统本身不稳定摆杆任何一点小偏角都会因为重力效应被放大如果不加控制杆子会在零点几秒内倒下去。传统做法里LQR和模糊控制是常见方案网上搜“一级倒立摆模糊控制”也能找到很多资料但这类方法依赖系统建模精度控制器设计也要花不少功夫。强化学习的思路是直接从交互数据里学策略不靠人工设计控制律这正好适合作为入门项目。在具体算法选择上我建议先看动作空间类型。如果小车受力只有“向左”和“向右”两个离散选项DQN是最合适的入门算法。DQN的原理可以理解成把“做每个动作值多少钱”这件事用神经网络拟合出来然后每次选择最值钱的动作执行。如果控制量是连续力比如小车受力范围在-10N到10N之间那就得用DDPG、TD3这类处理连续动作空间的算法。我自己第一次做的时候选的是DQN理由有三条实现简单、调参相对容易、训练过程稳定。连续动作版本的DDPG在控制效果上通常更细腻但需要调的地方也多比如探索噪声大小、Actor和Critic的学习率比例等。入门阶段建议先用DQN把整个流程跑通再回头换成连续控制算法做对比对理解算法差异会很有帮助。1.3 项目整体流程从环境到评估的闭环整个项目的推进路径我建议按下面这条线走每完成一步都有明确的产出不容易出现“不知道下一步做什么”的情况。环境准备安装Matlab R2019a及以上版本确认强化学习工具箱可用。环境搭建用rlPredefinedEnv创建CartPole环境或自己搭Simulink模型作为环境。智能体设计选择DQN设计神经网络结构和关键超参数。训练调试设置训练选项实时观察奖励曲线发现问题及时止损并调整。仿真验证把训练好的智能体放回环境里观察控制效果和稳定性。结果分析绘制摆杆角度、小车位置等状态变量的变化曲线量化评估控制性能。这个流程本质上覆盖了强化学习实验的完整闭环后面所有小节都是围绕这条线展开的。2. 倒立摆系统与强化学习关键细节2.1 倒立摆动力学模型与状态空间倒立摆的经典模型是一辆可以在水平轨道上移动的小车小车上方铰接一根摆杆。系统状态通常用四个变量描述小车位置x、小车速度dx/dt、摆杆角度θ、摆杆角速度dθ/dt。控制量是小车受到的水平作用力F。摆杆角度以竖直向上为0一旦超过一定范围比如正负12度就认为平衡失败当前回合结束。这组状态变量非常值得琢磨。它们正好覆盖了“位置”和“变化趋势”两个层面强化学习智能体依靠这四个数值来决定每一步该施加多大的力。数学模型上倒立摆是非线性系统运动方程里含有sinθ、cosθ这些项控制领域通常会在平衡点附近做线性化处理然后用状态空间方程表示。Matlab自带的CartPole-Discrete环境已经把这些动力学封装好了我们实际写代码时不需要手动推导运动方程但一定要理解状态维度和动作维度因为它们直接决定了神经网络输入层和输出层的设计。另外要注意的是量纲差异。四个状态变量中角度的量级通常在0.01到0.1弧度位置可能到几米如果数据范围差异过大会拖慢训练收敛。很多教程忽略了这一步但我实际做下来把状态归一化到相近的量级训练速度会有肉眼可见的提升。2.2 奖励函数设计决定训练成败的手艺活强化学习里算法只负责最大化累积奖励但“奖励怎么定义”才是真正体现水平的地方。同一个算法奖励函数设计不同最终学出来的策略可能天差地别。倒立摆的奖励设计常见有三种思路我都试过感受很深。第一种是稀疏奖励摆杆保持直立就每步给一个正奖励一旦倒下就结束当前回合。这种设计最接近Q-learning的原始设定实现最简单但学习速度很慢前期智能体完全是在随机探索很难收到正反馈。第二种是密集奖励用角度和位置误差构造连续奖励比如角度越小奖励越高、小车越靠近轨道中心奖励越高。收敛速度会明显加快但需要仔细调各分量的权重。第三种是在奖励里加动作惩罚项抑制频繁大幅度动作能让训练出来的策略更平滑控制过程不抖。我第一次做的时候只用了角度误差作为奖励结果训练完之后小车虽然能立住杆子但会反复左右横冲动作非常“神经质”。后来加了位置项和控制力惩罚项策略才明显变得平滑。我的建议是倒立摆这个场景直接上密集奖励直接用比较简单的公式奖励 -α·θ² - β·x² - γ·F²。α、β、γ分别代表角度、位置、控制力的权重根据实际效果调整。这个公式的直觉很简单偏离平衡越远、离中心越远、用力越猛奖励就越低。2.3 智能体网络结构与超参数设置以DQN为例智能体由两部分组成一个用于估计Q值的深度神经网络加上一套经验回放机制。网络输入是四个环境状态输出是两个动作分别对应的Q值。中间层用两层全连接每层24个神经元就能跑得很稳完全没必要一上来就堆大网络对倒立摆来说大网络反而更难收敛。超参数方面我最常用的配置整理成了一张表新手可以直接照抄等跑通了再根据自己的情况调整。参数推荐值设置理由经验回放池大小10000足够覆盖多样历史经验又不会让训练初期的无效数据占太大比例小批量大小64训练稳定性和更新频率的平衡点目标网络更新频率每4步太频繁会让Q值估计不稳定太慢则学习速度下降初始探索率0.9前期尽可能多探索动作空间探索率衰减每步乘以0.995随着训练进行逐步减少随机动作比重折扣因子0.99倒立摆是长期平衡任务需要看重未来收益这里有一个容易被忽略的细节经验回放。DQN里的经验回放就像整理错题本智能体把每一步的状态、动作、奖励、下一状态存起来训练时从中随机抽一小批来学习。这样做有两个好处一是打破前后经验之间的相关性让网络训练更稳定二是提高数据利用率一条经验可以反复学习。刚开始接触强化学习的人经常以为智能体是“边学边忘”的理解了经验回放机制就能明白数据复用的重要性了。3. 实操从零构建DQN倒立摆程序3.1 创建环境一行代码拿到CartPoleMatlab的强化学习工具箱直接提供了CartPole环境创建代码非常简短env rlPredefinedEnv(CartPole-Discrete);就这么一行环境就创建好了。接下来可以查看环境的观测信息和动作信息确认维度是否符合预期obsInfo getObservationInfo(env); actInfo getActionInfo(env); disp(obsInfo); disp(actInfo);观测信息里会看到四个状态变量的维度和范围动作信息会看到两个离散动作。这个环境默认算一步是0.02秒也就是说智能体每20毫秒要做一次控制决策。如果后续想模拟更真实或者更复杂的场景可以基于Simulink自建环境但入门阶段强烈建议先用现成环境把精力集中在理解强化学习本身的流程上。3.2 搭建神经网络与DQN智能体网络结构用Matlab的深度学习网络设计方式搭建输入层对应四维状态输出层是两个动作的Q值。代码可以这样写statePath [ featureInputLayer(4, Normalization, none, Name, state) fullyConnectedLayer(24, Name, fc1) reluLayer(Name, relu1) fullyConnectedLayer(24, Name, fc2) reluLayer(Name, relu2) fullyConnectedLayer(2, Name, output)]; qNetwork dlnetwork(statePath); agentOptions rlDQNAgentOptions(... ExperienceBufferLength, 10000, ... MiniBatchSize, 64, ... TargetUpdateFrequency, 4, ... ResetExperienceBufferBeforeTraining, false); agent rlDQNAgent(obsInfo, actInfo, qNetwork, agentOptions);这段代码里有两个细节值得说明。第一网络输出层是2个神经元对应两个离散动作这一点和动作空间严格对应不能随意改。第二rlDQNAgent的输入是观测信息obsInfo和动作信息actInfo智能体会自动识别状态维度和动作维度所以前面getObservationInfo那一步不是多余的。如果你用的是R2020a之前的老版本可能不支持dlnetwork直接传给rlDQNAgent需要改成rlQValueRepresentation的写法本质功能是一样的。3.3 训练配置与过程监控智能体创建好之后设置训练选项。这一步很关键因为训练选项直接影响训练时长和判断收敛的标准。trainOpts rlTrainingOptions(... MaxEpisodes, 1000, ... MaxStepsPerEpisode, 500, ... StopTrainingCriteria, AverageReward, ... StopTrainingValue, 480, ... ScoreAveragingWindowLength, 20, ... Plots, training-progress); trainingStats train(agent, env, trainOpts);解释一下这几个参数的逻辑。MaxEpisodes设置为1000是给训练留足空间实际通常用不了那么多轮。MaxStepsPerEpisode设置为500意思是一个回合最多跑500步就强制结束这样既能保证智能体有足够的平衡时间又不会让训练无限拖下去。StopTrainingValue设置为480是因为每回合上限500步如果平均奖励接近480说明绝大多数回合都坚持到了最后基本可以认定控制策略已经稳定。ScoreAveragingWindowLength设为20表示看最近20个回合的平均奖励避免偶发性表现引起误判。训练过程中Matlab会弹出一个实时进度窗口画出两条曲线一个是每个回合的奖励一个是滑动平均奖励。我正常训练下来大概在200到500个回合之间会出现拐点平均奖励从几十迅速爬升到400以上。如果训练到600个回合奖励还在低位徘徊通常不是训练步数不够而是超参数或者奖励设计出了问题需要停下来排查。3.4 仿真验证把学到的策略放到环境中检验训练结束并不代表工作完成关键一步是让训练好的智能体重新在环境里跑一遍看它是不是真的学会了维持平衡。仿真代码也非常简单simOpts rlSimulationOptions(MaxSteps, 500); experience sim(env, agent, simOpts);跑完之后experience里记录了一整个回合的观测、动作、奖励数据。我会把摆杆角度数据画出来看它是否始终在零度附近波动theta experience.Observation.theta.Data; plot(theta); xlabel(步数); ylabel(摆杆角度(rad));画出来的曲线应该是在0附近小幅震荡的波形说明智能体在持续修正摆杆姿态。如果曲线发散或者止步于某一步说明策略还不够稳定。另外也可以试试把MaxSteps调得更大比如1000步看智能体能不能长期保持平衡。我之前有一次训练出来的智能体在500步内表现完美但拉到1000步就会在某个时刻突然失控后来发现是训练回合上限恰好限制住了智能体的“耐力”适当调大MaxStepsPerEpisode再训练一轮才解决。3.5 可选的扩展把离散动作换成连续控制如果基础版本已经跑通我强烈建议尝试换成连续动作控制这是对理解强化学习算法非常有帮助的一步。你需要自己搭建一个连续力控制的CartPole环境动作范围比如[-10, 10]牛顿算法换成DDPG或TD3。代码框架也很简洁大致是agent rlTD3Agent(obsInfo, actInfo, ... actor, critic, agentOptions);其中actor和critic需要分别定义网络结构actor输出连续动作值critic输出状态动作对的价值。这个过程中你会真正理解离散动作和连续动作在策略表示上的本质差异而不是停留在概念层面。4. 常见问题与调参避坑实录4.1 训练不收敛四个排查方向训练不收敛是倒立摆项目里最常见的问题我见过不少同学卡在这一步然后放弃了。这里把我用过的排查顺序写出来按优先级从高到低排。第一检查奖励函数。如果奖励特别稀疏比如只有倒下才给惩罚那前期探索基本是在碰运气。先改用密集奖励让每一步都能提供梯度训练难度会立刻下降一个档次。第二检查状态归一化。四个状态的量级差异太大会让神经网络很难学把状态缩放到相近区间收敛速度会明显提升。第三检查探索率。如果epsilon衰减太快智能体还没有充分探索动作空间就过早进入“利用”阶段很容易陷入局部最优。我一般把epsilon从0.9开始每步乘0.995确保前期有足够的随机探索。第四检查学习率。工具箱默认的1e-3对倒立摆是合理的但如果你手动改过可以尝试调低到1e-4学习率过大是网络震荡发散的常见原因。如果这四个方向都排查过了还是不行那就重置环境并固定随机种子重新训练。强化学习本身随机性很大同样的参数多次训练结果可能不一样多跑几次有时候自然就收敛了。4.2 训练收敛但控制效果差奖励缺陷与网络问题另一种让人头疼的情况是训练曲线看着很漂亮平均奖励冲到上限但实际仿真时控制效果却很差小车在轨道上剧烈来回冲撞摆杆角度震荡得厉害。这种情况往往不是算法问题而是目标没有设计好。我在第一次做到这个现象时奖励函数里只设置了角度误差惩罚智能体发现只要摆杆勉强不倒位置再偏也无所谓于是学会了“疯狂摆动加猛冲”的极端策略。解决办法就是我前面提到的在奖励里加位置项和控制力惩罚项让策略必须兼顾稳定性、位置居中和平滑性。如果你用的奖励里已经包含了位置项但还是抖动严重可以适当增大控制力惩罚的权重。另外网络结构太浅也可能导致学出来的Q值估计不够平滑可以试着把隐层神经元从24增加到64但注意不要过度网络太大会造成训练不稳定。还有一种情况是目标网络更新太频繁导致Q值估计持续震荡。把TargetUpdateFrequency调低比如从1改为4或者8通常能改善稳定性。这个参数的作用是让目标Q值更新得慢一点给网络学习留出缓冲可以类比成“不要每次考试完都立刻改教材而是积累一段时间再更新”。4.3 工具箱版本与安装常见坑最后聊一个容易被忽视的环境问题。强化学习工具箱是R2019a引入的如果你的Matlab版本太老会出现找不到rlPredefinedEnv这类函数的情况。我建议直接用R2021b以上版本一方面函数接口稳定另一方面dlnetwork的支持也更完善。如果确认版本没问题但工具箱仍然不可用可以检查一下安装列表里Reinforcement Learning Toolbox是否勾选。Matlab在安装时默认不会装全部工具箱需要在MATLAB的“主页-附加功能-管理附加功能”里补装。学校或者公司通常都有正版授权直接在附加功能里搜索安装就行。另外不同版本之间rlDQNAgentOptions和rlTrainingOptions的具体字段偶尔会有小改动如果某段代码在你的版本上报错优先查对应版本的文档中心比随便改代码可靠得多。5. 一点经验与后续扩展方向把这个项目跑通之后我自己又沿着三条线做了扩展每一条都刷新了对强化学习的理解。第一条是把环境从一级倒立摆换成二级倒立摆难度立刻上了一个台阶DQN基本学不动了得换PPO这类更稳的算法才能处理。第二条是研究奖励塑形对训练速度的影响对比不同权重的奖励公式在相同训练步数下的表现差距收获很大。第三条是关注离线强化学习的思路把之前在线训练产生的经验数据保存下来然后重新喂给智能体研究数据复用对样本效率的影响这也是当前强化学习研究里的热门方向之一。如果你现在也跑通了倒立摆我的建议是先别急着换模型、换算法把奖励函数反复改几遍每次训练都盯着那条奖励曲线看变化搞清楚“为什么改了这个权重曲线就变平稳了”。这种体感是任何教程都替代不了的。倒立摆虽然是个入门级环境但它把强化学习里最核心的“试错-评估-改进”逻辑完整演了一遍把这条线吃透后面遇到机器臂控制、运动控制、智能决策这些复杂场景你都会有个清晰的知识坐标。本文还有配套的精品资源点击获取
返回列表