资讯动态

DDPG强化学习与滑模控制参数自动整定方法解析

发布时间:2026/10/17 3:01:11 来源:尧图企业网站定制
1. 为什么要把DDPG用在滑模控制调参上1.1 滑模控制参数难调的本质做控制的人对滑模控制SMC应该都不陌生。它的思路说白了就是先设计一个滑动面把系统状态引导到这个面上然后通过不连续的控制律把状态摁在这个面上滑向平衡点。好处是结构简单、鲁棒性强尤其对付参数摄动和外部扰动很有一套这在电机驱动、机器人关节、飞行器姿态控制这类场景里特别吃香。但真上手调参的人都知道SMC的调参体验并不友好。核心要调的参数其实就三大类滑模面参数、趋近律参数、切换项增益。滑模面参数决定了系统的收敛速度和动态品质趋近律参数影响状态到达滑模面的快慢切换项增益则直接硬扛扰动和不确定性。问题在于这三个参数是耦合的把滑模面斜率调大系统响应快但抖振也跟着变大执行器受不了把切换增益调小抖振是小了可抗扰动能力又掉了。传统做法一般是先按经验定一组初值然后仿真试错跑一组波形改一个参数再跑一组反复折腾。碰上强非线性或者工况变化频繁的对象一组固定参数根本不够用整个过程非常消耗时间而且极度依赖经验。我在某实验室做过一个带参数摄动和负载扰动的电机位置伺服仿真当时试过把切换增益调高去压扰动结果仿真波形看着挺干净一加噪声和模型不确定性控制量高频摆动得非常明显。后面把增益降下来扰动抑制效果又退步了。那段时间大量的时间都花在调一个参数、跑一轮仿真、截图对比这种循环里效率低到让人头疼。这也是后来我把强化学习引入来做这件事的直接原因与其人肉试错不如让算法根据系统的实时状态自动把参数调出来。1.2 DDPG相比于其他强化学习算法的优势既然要自动调参那选哪个强化学习算法就得有个说法。滑模控制的参数调节本质上是连续动作空间问题参数不是离散的几个档位而是连续变化的数值比如切换增益可能是3.2、3.5、3.8这种连续取值。DQN那类基于值函数的算法天然只擅长离散动作你非要把连续动作空间强行离散化要么精度不够要么动作维度爆炸很难落地。DDPG是深度确定性策略梯度算法它是Actor-Critic架构策略网络直接输出确定性动作天然匹配连续控制场景。你给它一个状态输入它输出的就是一个连续的控制参数组合比如滑模面参数c和切换增益ε一步到位连先离散再选动作这种别扭环节都省了。而且在训练稳定性上DDPG用了经验回放和目标网络软更新这两招对解决强化学习训练中常见的样本相关性和目标不稳定问题很有效实战中比直接硬训PPO更容易收敛出稳定可用的策略。我当时也考虑过PPO。PPO在采样效率和稳定性上确实不错但它属于on-policy算法每次更新都需要新采样的数据在Simulink这种仿真速度本身就不快的环境里训练时长会非常可观一轮500个episode跑下来时间成本高得让人怀疑人生。DDPG是off-policy旧的样本能反复利用数据效率更高配合Simulink里一个step一个step地推进仿真实际训练体验会从容很多。2. 整体思路与方案设计2.1 控制框架与学习回路怎么搭把DDPG和SMC放在一起并不是说用强化学习去替代滑模控制而是让强化学习充当一个参数决策器给SMC控制器实时提供一组更合适的参数。整个框架分两层底层是SMC控制器和被控对象组成一个常规闭环。滑模控制器每个控制周期根据当前的误差e和误差导数de/dt计算出控制量驱动被控对象跟踪期望轨迹这个闭环是实时的、确定性的控制律本身不变。上层是DDPG智能体它不直接参与每个周期的控制计算而是作为一个参数调节器存在。智能体观察系统状态比如跟踪误差、误差变化率、控制量大小、当前工况信息经过策略网络计算输出一组SMC参数的调整量或直接输出参数值然后再由SMC控制器使用这套参数执行控制。DDPG智能体的学习信号来自奖励函数每个episode结束之后根据被控对象的表现——跟踪精度、超调量、控制能量的消耗——给智能体打分通过不断试错让策略网络学会在什么状态下给出什么参数能让整体表现最好。这个设计的关键在于SMC的稳定性由控制律本身保证DDPG只是调整增益和滑模面相当于在一个已经被证明稳定的控制结构内部做参数调度。这么做的好处是安全即使DDPG在一开始训练时输出了很离谱的参数最坏的结果是仿真性能变差而不会因为控制律结构被破坏导致系统完全失控。我见过有人把神经网络直接替换掉整个SMC控制器让智能体输出控制量那种做法对训练的要求苛刻得多一旦奖励函数设计不合理训练过程发散到根本看不出任何规律排查起来也特别困难。参数调优式的做法要稳得多也更适合工程落地。2.2 状态空间、动作空间与奖励函数的设计这个方案能不能收敛、收敛出来的策略好不好用三个关键设计直接决定成败状态怎么定义、动作怎么定义、奖励怎么设计。状态空间方面我的建议是要让智能体看得到系统当前处于什么处境。最基础也最好用的是这几项跟踪误差e、误差变化率de/dt、最近一段时间误差的积分或累积项、当前的控制量u以及SMC当前的滑模面值s。如果被控对象存在明显的工况变化比如负载突变最好把负载力矩或者它的估计值也放进状态里。这样智能体看到负载变大就能知道要增大切换增益去对抗扰动而不是在负载已经变大之后被动响应。我实测过只给误差和误差导数两个状态的情况训练也能收敛但最终策略的泛化性明显差换个扰动幅值性能就下滑加上负载信息之后好很多。动作空间的定义有两种常见做法。第一种是直接输出参数值比如智能体输出一个值映射到切换增益ε的实际范围[1, 10]上。第二种是输出参数的增量智能体输出Δc和Δε当前参数等于上一时刻参数加增量。两种我都试过直接输出参数值训练更简单直接收敛速度也快一些增量输出更平滑能天然限制参数变化幅度不容易出现参数剧烈跳变但训练难度大一点因为智能体需要学会记忆当前的参数基础值而DDPG没有内置的记忆机制纯粹靠观测状态来推断参数基准增加了一层隐式的学习负担。对于大多数SMC调参场景直接输出参数值并限制到合理区间已经能取得不错的效果。奖励函数是整件事的灵魂。我踩过的坑是只把跟踪误差放进奖励比如奖励等于负的误差平方智能体很快会发现一个作弊的办法——把切换增益无限调大让控制量变得非常大这样跟踪误差确实很小但抖振和控制能量爆炸系统在实际中根本无法接受。后来我把奖励拆成三块跟踪误差项、控制量惩罚项、抖振惩罚项。具体来说每一步的奖励可以设计为r -w1 * e^2 - w2 * u^2 - w3 * |u(k) - u(k-1)|其中w1、w2、w3是权重系数。误差项保证跟踪精度控制量平方项抑制过大的控制能量控制量的变化量绝对值项直接惩罚抖振。这个奖励结构一换上去智能体训练出来的策略明显“懂事”很多不会为了误差漂亮而疯狂加大控制量。权重系数怎么定我的建议是先只开误差项训练一个粗糙策略看控制量大概在什么量级再根据控制量的典型大小去设定w2和w3确保三项在初始策略下的数值贡献大致相当这个经验比对着文献硬抄权重靠谱得多。3. 核心细节解析DDPG调参的各个环节3.1 滑模面参数与趋近律参数的作用范围要把参数调节做对首先得明确到底在调什么。一个典型的滑模控制器滑模面可以设计为s c * e de/dt当s收敛到0跟踪误差e就按指数规律收敛收敛速率由滑模面参数c决定。c越大误差衰减越快但c太大会放大噪声因为de/dt对测量噪声非常敏感。这一项直接决定系统的响应速度与稳态精度是DDPG需要调节的第一个维度。趋近律方面指数趋近律是最常用的ds/dt -ε * sign(s) - k * s其中ε是等速趋近项增益决定系统在滑动面附近抵抗扰动的能力也是抖振的主要来源k是指数趋近项增益决定状态快速逼近滑动面的速度。这两个参数配合起来既要保证快速到达滑模面又要限制到达滑模面之后的高频切换幅度。在很多实现里还会把符号函数sign(s)替换成饱和函数sat(s)或者tanh(s)用边界层厚度来换取抖振抑制这个边界层厚度参数同样可以纳入DDPG的动作输出。我实际训练时动作空间设置成三个输出滑模面参数c、等速趋近增益ε、边界层厚度δ。k一般固定在某个经验值因为k对抖振的影响不如ε那么直接而且增加一个输出维度就会增加训练难度。Simulink的Reinforcement Learning Toolbox里创建自定义智能体时动作空间的维度设成3再配好每维上下限用tanh输出层配合缩放层把动作映射到设定区间非常方便。3.2 Actor-Critic网络结构与超参数选择DDPG的网络结构看起来简单一个Actor网络负责输出动作一个Critic网络负责评估状态-动作值但细节上的讲究一点也不少。我踩过的核心坑是网络层数堆得太深。一开始我图省事Actor和Critic都用了四个隐藏层每层256个节点觉得参数越多表达力越强结果训练起来既慢又容易发散。后来把结构改成Actor两层隐藏层128节点Critic也类似但Critic的输入侧多了一条动作输入分支训练稳定性和收敛速度都明显改善。DDPG的Critic输入要同时包含状态和动作这里有个结构设计上的细节。最常见的做法是把观测输入和动作输入分成两个分支各自过一层全连接层然后拼接在一起再送进后续的隐藏层。而不是简单粗暴地把状态和动作拼成一个向量直接灌进去。分开处理的好处是两个来源的信息可以先分别抽取特征再融合实测中比直接拼接的拟合效果更好这个结构细节在Matlab的rlCustomAgent建模时可以直接参考。超参数方面值得重点关注的几个软更新系数τ一般取0.001到0.005之间。τ太大目标网络更新过快训练容易震荡太小更新过慢智能体学得磨叽。Actor的学习率推荐1e-4到1e-3Critic的学习率可以稍微高一点比如1e-3但要注意两者间不要差距过大。经验回放缓冲区容量Simulink仿真里我推荐至少5万条样本起步如果电脑内存够10万更好。太小了样本多样性不足容易产生偏差。批量大小64或者128都适用需要根据仿真速度权衡批量太大单次更新慢太小更新噪声大。折扣因子γ这个场景取0.95到0.99之间。γ太大会让智能体过度关注远期收益导致训练变慢太小会让智能体目光短浅只看当前几步的控制效果。奖励缩放因子也是一个容易被忽视的点。整体奖励数值如果长期处于很大的量级网络权重更新容易过冲。我习惯在奖励函数里把误差项除以一个参考值让奖励量级尽量控制在正负几的范围内这样训练过程稳定得多。3.3 探索噪声与训练稳定性DDPG是确定性策略如果训练时不加探索噪声智能体输出的动作永远是确定的完全没有随机性它就只能在一个固定策略下收集数据永远发现不了更好的参数组合。标配做法是给动作加上Ornstein-Uhlenbeck噪声这种噪声的好处是它在时间上是相关的相邻时刻的噪声值不会完全独立更适合连续控制这类需要平滑动作的场景。我最初图省事用的是高斯白噪声效果也能训但训练后期收敛出来的策略抖振偏大因为白噪声让每个时间步的动作都随机跳动相当于在参数调节过程中引入了持续的高频抖动。换成OU噪声之后噪声在时间上平滑很多更符合参数应该缓慢调整这个物理直觉训练稳定性和最终策略质量都有提升。噪声的幅度也要精心设计初始阶段保持较大噪声让智能体充分探索参数空间随着训练进行噪声标准差应该逐步衰减否则到了后期智能体已经学到不错的策略大噪声反而会把参数拉离最优区域。有一个细节特别值得注意训练过程中偶尔会遇到数值异常。我遇到过几次某个episode直接出现控制量NaN的情况原因通常是参数组合过于极端比如c取得太大误差导数又被噪声污染导致控制量计算溢出。应对办法是在SMC控制律外面加一个输出饱和保护限制控制量在合理范围内的最大值并在检测到NaN时强制跳过本episode。这种工程保护不会影响正常训练但能避免整体训练过程因为一次数值爆炸而彻底崩溃。4. Simulink仿真实现与实战步骤4.1 被控对象模型搭建我用Simulink搭过一个电机位置伺服系统的仿真来跑这套算法被控对象模型就用常见的二阶级联形式一个电流环加一个机械运动方程J * d²θ/dt² B * dθ/dt Kt * i Td其中J是转动惯量B是粘滞摩擦系数Kt是力矩常数Td是负载扰动。实际建模时把对象封装成一个子模块输入是控制量u输出是位置θ再对θ求导得到角速度用于反馈回路。为了测试算法的鲁棒性我把J设置成可以在仿真中途发生突变通过一个Signal Builder在5秒的时刻突然把J放大30%模拟负载突变场景。这个设计后面验证DDPG调参策略的实时自适应能力非常方便。Simulink里的采样时间设置也得注意。控制周期如果设成固定步长1e-3秒滑模控制的高频切换特性就能比较真实地反映出来。我建议对被控对象用变步长求解器比如ode45但控制器部分要用固定步长否则滑模切换在变步长下会产生严重的数值抖振仿真结果会失真。在Simulink里做法是把整个闭环模型放到一个触发子系统中使用固定采样时间定时触发执行。4.2 SMC控制器与DDPG agent的接口设计这是整个工程实现的枢纽环节。SMC控制器封装成一个MATLAB Function模块输入是参考信号θ_ref、实际位置θ、速度以及当前时刻DDPG输出的参数c、ε、δ输出是控制量u。函数内部实现滑模控制律e theta_ref - theta de dtheta_ref - dtheta s c * e de u -epsilon * tanh(s / delta) - k * s 等效控制项注意这里我用的是tanh(s / delta)而不是sign(s)目的是用边界层思想抑制抖振。等效控制项根据被控对象的标称模型计算比如可以写成惯量乘以期望角加速度的形式。DDPG agent通过Simulink的Reinforcement Learning Toolbox接口接入。具体做法是创建一个rlObservationSpec和rlActionSpec观测向量是当前状态里的几个量动作向量就是c、ε、δ这三个参数然后通过rlDDPGAgent创建智能体再用rlTrainingOptions配置训练参数。在模型环路里观测信号通过State端口进入agentagent输出的动作经过一个外包层处理映射到设定的参数范围传给MATLAB Function模块。接口设计中一个容易出问题的点是观测数据的尺度差异。跟踪误差e可能在0.01这个量级而控制量u可能在几十这个量级直接一起灌进神经网络数值大的特征会主导网络更新导致小数值的特征信息被淹没。处理方法是对每个观测维度做归一化把量纲不同、尺度差异巨大的信号统一映射到接近0的范围内这一步几乎决定训练能否成功重要性怎么强调都不过分。4.3 训练流程与代码配置训练流程用Matlab脚本来驱动会灵活得多。基本流程是这样的初始化环境模型和DDPG agent的参数。如果是从头开始训练Actor网络和Critic网络都用随机初始化如果是续训用agent.load来加载之前的模型权重。设置rlTrainingOptions包括maxEpisodes、maxStepsPerEpisode、scoreAveragingWindowLength这些关键参数。我常用的是maxEpisodes设1000到1500maxStepsPerEpisode按仿真时长和控制周期换算比如仿真5秒、步长1e-3就是5000步。每个episode开始前把被控对象的初始状态随机化。这个细节很重要如果每次都从同一个初始状态开始训练智能体学到的策略会过拟合到这个固定的启动工况上。我会随机化初始位置、初始速度以及负载扰动的大小。训练循环中Simulink模型每步执行一次回归返回观测和奖励agent内部更新网络参数。每若干个episode保存一次checkpoint防止跑了一整天训练中途崩溃模型全部白费。这里给一段简化的训练配置示例obsInfo rlNumericSpec([5 1], ... LowerLimit, -inf*ones(5,1), UpperLimit, inf*ones(5,1)); actInfo rlNumericSpec([3 1], ... LowerLimit, [0.1; 0.1; 0.01], UpperLimit, [50; 50; 1]); agent rlDDPGAgent(obsInfo, actInfo); agent.AgentOptions.TargetUpdateSmoothFactor 0.001; agent.AgentOptions.ExperienceBufferLength 100000; trainOpts rlTrainingOptions(... MaxEpisodes, 1200, ... MaxStepsPerEpisode, 5000, ... StopTrainingCriteria, AverageReward, ... StopTrainingValue, -5, ... SaveAgentCriteria, EpisodeReward, ... SaveAgentValue, 100); trainResults train(agent, env, trainOpts);训练过程中可以实时查看每个episode的累计奖励曲线。我观察到一个规律前一两百个episode奖励曲线基本在低位徘徊甚至更差因为智能体还在乱探索当曲线开始出现稳定上升趋势时说明Actor网络开始学到有效参数的模式后面会出现几个阶段性的平台期平台期之后突然又跳升一级——这通常对应智能体发现了某种更优的参数配合比如把边界层厚度δ调到一个既能抑振又不牺牲精度的甜点值。训练到后期看到奖励曲线在高位平稳、不再有大起大落再跑几个验证episode确认腔内性能就可以停了不用干等满所有episode数。5. 常见问题与排查技巧实录5.1 训练不收敛奖励曲线大幅震荡这是最让新手崩溃的场景之一明明照着论文配置抄了一遍训练曲线却像心电图一样乱跳。排查顺序我建议从三个方面来先看观测和奖励的数值范围是不是失控。加一个Display模块或者直接在训练回调里打印每个episode的奖励明细如果某一个episode的奖励突然出现巨大的负值比如-5000这种回头看是哪个环节爆炸的——控制量太大还是状态值漂移到离谱区间这一步能快速定位是数值问题还是算法问题。然后检查Actor网络输出的动作是否长期贴在上限或下限附近。如果训练过程里参数一直顶到上边界说明动作空间的上下限设得不够合理或者奖励函数对参数过大的惩罚还不够强智能体发现了边界外还有更优解但被边界挡住训练就会一直在边界附近纠结表现为奖励波动剧烈。最后看噪声标准差是否合适。如果探索噪声太大后期策略已经不错了但噪声一直在把参数往坏的方向拉奖励曲线自然稳不下来。OU噪声的标准差初始值我一般设成动作范围宽度的十分之一左右训练进程过半后线性衰减到初始值的一半以下。5.2 Simulink仿真速度慢一个episode要跑几分钟做强化学习训练仿真速度几乎永远是瓶颈。一个5000步的episode实际物理时间只有5秒但如果Simulink支持性和实时性跟不上跑完一个episode可能耗时10秒以上1000个episode就是三小时起步全参数扫描根本不现实。最有效的提速手段是使用Simulink的快速加速模式Rapid Accelerator实测可以提速数倍。其次是减少不必要的scope显示和信号日志记录训练过程中其实不需要每次保存全部响应波形只需要在每个episode结束时由脚本提取几个关键性能指标即可这个改动对长训练的影响非常大。此外把仿真步长从1e-3放宽到1e-2前提是保证控制性能没有明显变化也能显著提速但滑模控制切换频率高步长太大会引入严重的数值抖振做这个调整前要仔细对比验证。如果实在提速有限另一个思路是降低maxStepsPerEpisode。把仿真时长缩短到2到3秒奖励改成只看稳态段的误差平方和控制量也能训出可用的策略。缩短单episode时长本质上是换了个角度解决训练速度问题——牺牲一部分覆盖工况的episode内时长换取单位时间内更多的训练轮次让训练策略更快更新。5.3 参数跳变导致系统不稳定训练好的DDPG智能体在推理阶段部署时最怕遇到参数输出突变。比如上一时刻c输出的是15下一时刻突然跳到40控制系统瞬间就进入一个完全不同的动态特性即使名义上稳定实际响应也会出现明显的冲击。这个问题要从两个层面去堵。第一个层面是在动作输出后处理时做速率限制限制每个控制周期参数变化的最大幅度就好比给参数调节加了速率饱和器。第二个层面是训练阶段就要防——在奖励函数里加入对参数变化量的惩罚也就是前面提到的控制量变化惩罚项这会让智能体学习到参数应平滑变化的行为模式属于从根本上解决问题。我遇到过一种特殊情况智能体在工况切换的边缘地带输出策略不稳定同一组观测值下偶尔给出一高一低两种参数。究其原因是训练数据里工况切换附近的样本太少网络没有拟合出确定性的映射关系。解决办法是在训练时增加开关事件的随机概率让负载突变出现在episode的不同时刻而不是固定在5秒。这样智能体能在各种切换时机下都见过足够的样本边缘地带的不确定性也会大为缓解。5.4 训练结束测试性能很好但换一个工况就不行这是典型的泛化性问题。一个常见的误解是训练时观察了负载扰动智能体就算见过各种工况了。但实际上智能体见过的是训练分布内的工况如果测试时扰动幅度显著超出训练范围策略性能可能断崖式下滑。提升泛化能力的做法有几个方向。第一扩大训练时的随机化范围——扰动幅度从训练的均值上下30%扩展到上下50%初始状态的随机范围也相应扩大。第二在状态空间中显式加入扰动估计值或负载信息让智能体在推理阶段能看到当前工况的强度从而调整参数。第三如果目标工况范围确实很宽可以考虑训练多个专用策略通过工况识别切换比试图用一个万能策略覆盖全部工况更简单可靠。我后来还在奖励函数里加了一个参数合理性约束项对明显超出工程经验的参数组合给予额外惩罚比如切换增益过大导致频繁饱和或效率极低的情况。这么做进一步压缩了策略的搜索空间让训练出来的参数基本都落在工程可用的范围内也间接提升了泛化性。最后的一点实操心得这套DDPG加SMC的自适应调参方案前前后后我跑了至少有几百个小时的仿真。回头复盘最大的体会是强化学习在这里起的作用不是创造控制规律而是在已有的、可靠的控制器框架内做参数优化。这个定位非常重要它决定了整个系统可控性的底线——不管智能体怎么折腾系统都不会完全失控。对工程应用来说这个底线比训练出多漂亮的性能指标都更值钱。另外想单独提一个细节训练好的模型最好导出成C代码或者封装成独立的函数方便脱离Matlab环境做后续部署。在推理阶段DDPG的策略网络其实就是一个多层感知机前向传播计算量很小在控制周期1ms的场合完全跑得动。真正在工程里应用时可以把训练好的网络参数固化下来省掉每次推理时加载模型的额外开销。如果你也想在这套方案上做扩展建议往多智能体协同调参或者基于数字孪生的在线再训练方向走。多智能体可以让每个智能体分别负责不同工况段或者不同控制目标的参数调整数字孪生则可以在实际对象模型漂移时用最新数据对策略做持续微调。这两条路线在当前工业界对智能控制需求越来越大的背景下落地价值都很明显。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑