1. 从LQR到深度强化学习为什么这三讲值得反复啃如果你正在啃深度强化学习大概率绕不开一个经典课程体系其中连续三讲专门讲基于模型的强化学习与控制理论。很多人第一次看的时候会有一个共同的困惑前面几讲还在讲策略梯度、Actor-Critic这些无模型方法怎么突然画风一转开始讲LQR、iLQR、DDP这些控制论里的东西了我当初也是这个反应甚至一度想跳过这几讲直接去看后面的离线强化学习。后来踩了坑才发现这几讲恰恰是从“会调包”到“真正理解强化学习在做什么”的分水岭。这三讲的核心内容说白了就是回答一个问题当我们知道环境模型或者能学出一个模型的时候怎么用它来做出更好的决策这跟无模型方法是两条腿走路。无模型方法直接从数据里学策略样本效率低但通用性强基于模型的方法先学一个动力学模型然后在模型里做规划或者优化样本效率高但对模型精度敏感。而LQR线性二次调节器就是基于模型控制里最基础、最优雅的那块基石。这篇文章适合谁看如果你已经学过强化学习的基础概念知道MDP、值函数、策略梯度大概是怎么回事但一看到LQR、Riccati方程、iLQR这些词就头大那这篇就是写给你的。我会从LQR的基础知识讲起把这三讲里涉及的核心技术点拆开揉碎补充课程里一带而过但实际很重要的细节再结合我自己的实操经验把容易踩的坑和排查思路都整理出来。整篇内容会围绕“基于模型的强化学习”这条主线展开不会跑偏到其他方向。先说结论这三讲的价值不在于让你背下LQR的推导而在于建立一种“用模型做决策”的思维方式。这种思维方式在后面学MBPO、PETS、Dreamer这些算法的时候会反复用到。而且LQR本身在工程里应用极广从无人机姿态控制到机械臂轨迹跟踪底层都是这套东西。所以花时间啃透绝对不亏。2. 基于模型强化学习的整体设计思路拆解2.1 无模型与基于模型两条路线的本质差异要理解这三讲为什么重要得先搞清楚基于模型的方法到底解决什么问题。无模型方法比如PPO、SAC的流程是采样一批轨迹用这批数据更新策略然后再采样再更新。问题在于每一步更新都需要大量真实交互在真实机器人或者复杂仿真环境里这个代价非常高。而基于模型的方法换了个思路先用数据学一个环境模型然后在模型里“想象”大量轨迹用这些想象出来的数据来训练策略或者做规划。这个思路的优势很明显——样本效率高。你只需要少量真实交互就能学出一个还不错的模型然后在模型里反复利用。但劣势也很明显模型误差会累积。如果模型在某一步预测偏了后面基于这个错误状态做的规划就全歪了。所以基于模型的方法核心难点在于怎么在模型不完美的情况下依然做出鲁棒的决策。这三讲的内容安排其实很有讲究。先讲LQR因为它是线性系统加二次代价这个特殊设定下的精确解有闭式解能让你看清楚“最优控制”长什么样。然后讲iLQR和DDP把线性二次的框架扩展到非线性系统通过局部线性化来迭代求解。最后讲基于模型的强化学习怎么跟神经网络结合用学出来的模型做规划。整个逻辑是从特殊到一般从精确到近似层层递进。2.2 为什么先啃LQR基础中的基础LQR看起来简单但它包含了最优控制的几个核心要素状态、动作、动力学约束、代价函数、最优性原理。它的解——线性状态反馈——形式极其简洁但背后的推导涉及动态规划、Riccati方程、矩阵求逆等一堆线性代数操作。很多人学LQR的时候只记住了“解一个Riccati方程得到反馈增益K”但不知道为什么是这个形式也不知道K的物理意义是什么。我当初学的时候就是这个问题公式推了一遍就过了结果后面看iLQR的时候完全跟不上。后来回头重新啃了一遍LQR把动态规划的推导自己手推了三遍才真正理解为什么最优策略是状态的线性函数。这个理解在后面做轨迹优化的时候非常关键因为iLQR本质上就是在每个时间步做局部LQR如果你不理解LQR的解为什么长那样iLQR的迭代公式你只能死记硬背。所以我的建议是LQR部分不要跳过不要只记结论一定要自己推一遍。推完之后你会发现后面iLQR和DDP的推导其实就是把LQR的结论套到非线性系统的局部线性化上逻辑是连贯的。2.3 三讲之间的逻辑衔接与知识依赖这三讲的内容不是孤立的它们之间有明确的依赖关系。LQR是基础提供了最优控制的精确解和动态规划的思路。iLQR和DDP是在LQR基础上扩展出来的用于处理非线性系统。而基于模型的强化学习则是把iLQR/DDP的思路跟神经网络模型结合起来用于更一般的场景。具体来说LQR要求动力学是线性的、代价是二次的。但现实中的系统几乎都是非线性的怎么办iLQR的思路是在当前轨迹附近对动力学做一阶泰勒展开对代价做二阶泰勒展开这样就把非线性问题转化成了局部线性二次问题然后用LQR求解。解完之后更新轨迹再在新轨迹附近重新线性化反复迭代直到收敛。DDP跟iLQR的区别在于DDP在展开的时候保留了更多的二阶项精度更高但计算量也更大。而基于模型的强化学习比如PETS或者MBPO则是用神经网络学一个动力学模型然后用这个模型做规划或者生成虚拟数据。这里的规划部分很多时候就是用iLQR或者随机打靶法random shooting来实现的。所以你看这三讲的内容是环环相扣的前面没搞懂后面就接不上。3. LQR核心细节解析与实操要点3.1 LQR的问题设定与动态规划推导LQR的问题设定很干净系统动力学是线性的( x_{t1} A_t x_t B_t u_t )代价函数是二次的( c(x_t, u_t) x_t^T Q_t x_t u_t^T R_t u_t )。目标是找到一串控制序列 ( u_0, u_1, ..., u_{T-1} ) 使得总代价最小。这里Q和R是半正定和正定矩阵分别惩罚状态偏差和控制量大小。这个问题的解可以用动态规划来推。定义值函数 ( V_t(x_t) ) 为从t时刻状态x_t出发的最小剩余代价。根据贝尔曼最优性原理( V_t(x_t) \min_{u_t} [x_t^T Q_t x_t u_t^T R_t u_t V_{t1}(A_t x_t B_t u_t)] )。假设值函数是二次形式 ( V_t(x_t) x_t^T P_t x_t )代入后对u_t求导令其为零就能解出最优控制 ( u_t^* -K_t x_t )其中 ( K_t (R_t B_t^T P_{t1} B_t)^{-1} B_t^T P_{t1} A_t )。而P_t满足Riccati方程( P_t Q_t A_t^T P_{t1} A_t - A_t^T P_{t1} B_t (R_t B_t^T P_{t1} B_t)^{-1} B_t^T P_{t1} A_t )。这个推导的关键假设是值函数是二次的。为什么可以这样假设因为代价是二次的、动力学是线性的二次函数经过线性变换和最小化之后仍然是二次的。这个性质叫“二次不变性”是LQR有闭式解的根本原因。理解这一点很重要因为后面iLQR能work也是因为局部线性二次近似之后值函数在局部可以近似为二次。3.2 Riccati方程的求解与反馈增益的物理意义Riccati方程是LQR的核心它是一个矩阵差分方程从终端时刻T往前递推。终端条件通常是 ( P_T Q_T )终端代价。递推过程是已知 ( P_{t1} )计算 ( K_t ) 和 ( P_t )然后往前推。这个过程是确定性的不需要迭代所以LQR的求解非常高效。反馈增益 ( K_t ) 的物理意义值得多说两句。它表示“状态偏差每增加一个单位控制量应该增加多少来纠正”。如果K很大说明系统对状态偏差很敏感控制力度大如果K很小说明控制比较温和。K的大小取决于Q和R的相对大小Q越大说明你越在意状态偏差K就越大R越大说明你越在意控制代价K就越小。这个权衡在调参的时候非常直观。我实际做实验的时候发现很多人调LQR的时候只调Q和R的对角线元素忽略了非对角线元素。其实非对角线元素可以表达状态之间的耦合关系比如你希望位置和速度的偏差不要同时很大就可以在Q的非对角线上加负值。这个技巧在轨迹跟踪任务里很有用但课程里一般不会讲。3.3 有限时域与无限时域LQR的区别LQR分有限时域和无限时域两种。有限时域就是上面说的从T往前递推到0每个时刻的K_t都不一样。无限时域则是T趋于无穷这时候P_t会收敛到一个稳态值PK也会收敛到常数K。无限时域LQR的解可以通过求解代数Riccati方程ARE得到不需要递推。两者的区别在于有限时域LQR的最优策略是时变的因为终端代价会影响前面的决策无限时域LQR的最优策略是时不变的因为系统已经进入稳态。在实际应用中如果你的任务有明确的终止状态比如机械臂要到达某个目标点那用有限时域更合适如果任务是持续调节比如保持无人机悬停那用无限时域更合适。这里有个容易踩的坑无限时域LQR要求系统是可稳定的stabilizable和可检测的detectable否则ARE可能没有正定解。我当初做实验的时候遇到过一次系统矩阵A有特征值在单位圆外但B矩阵不能控制这些模态结果ARE解出来P不是正定的K也不稳定。后来检查了半天才发现是系统本身不可稳定跟LQR算法没关系。所以用LQR之前先检查一下系统的可控性和可观测性能省很多调试时间。4. 从LQR到iLQR/DDP的扩展实操4.1 非线性系统的局部线性化策略现实中的系统几乎都是非线性的比如倒立摆、四旋翼、机械臂动力学里都有三角函数或者乘积项。iLQR的思路是在当前轨迹附近对动力学做一阶泰勒展开( f(x_t, u_t) \approx f(\hat{x}_t, \hat{u}_t) \frac{\partial f}{\partial x}(x_t - \hat{x}_t) \frac{\partial f}{\partial u}(u_t - \hat{u}_t) )其中 ( \hat{x}_t, \hat{u}_t ) 是当前轨迹上的状态和动作。这样就把非线性系统转化成了局部线性系统A_t和B_t就是雅可比矩阵。代价函数也做二阶展开( c(x_t, u_t) \approx c(\hat{x}_t, \hat{u}_t) \nabla c^T \delta \frac{1}{2} \delta^T \nabla^2 c \delta )。展开之后问题就变成了关于偏差 ( \delta x, \delta u ) 的LQR问题可以用上一节的方法求解。解完之后得到新的控制序列更新轨迹再在新轨迹附近重新展开反复迭代。这个过程的收敛性依赖于初始轨迹的质量。如果初始轨迹离最优解很远线性化误差会很大迭代可能不收敛。我实际用的时候一般先用一个简单的控制器比如PID跑一条还不错的轨迹作为初始解然后再用iLQR优化。这样收敛快很多也不容易发散。4.2 iLQR的迭代流程与收敛判断iLQR的完整迭代流程可以拆成这几步前向传播用当前控制序列 ( {u_t} ) 在真实动力学上 rollout得到轨迹 ( {x_t} )。反向传播从终端时刻往前递推计算每个时刻的Q函数展开系数然后解出最优控制偏差 ( \delta u_t^* ) 和反馈增益 ( K_t )。前向更新用新的控制序列 ( u_t \alpha \delta u_t^* K_t \delta x_t ) 重新 rollout其中 ( \alpha ) 是步长。收敛判断如果代价下降小于阈值或者迭代次数超过上限就停止。这里的关键是步长 ( \alpha ) 的选择。如果 ( \alpha 1 )就是完全信任LQR的解但线性化误差可能导致代价反而上升。所以实际实现里一般用线搜索从 ( \alpha 1 ) 开始如果新轨迹代价更低就接受否则减半再试直到找到能降低代价的步长。这个技巧叫“回溯线搜索”是保证iLQR收敛的关键。我当初实现iLQR的时候一开始没加线搜索结果迭代几次之后代价就爆炸了。后来加上线搜索收敛就稳定多了。所以如果你自己写iLQR线搜索一定要加这是血泪教训。4.3 DDP与iLQR的差异及选择依据DDP和iLQR的主要区别在于对动力学的展开阶数。iLQR只做一阶展开DDP做二阶展开保留了 ( \frac{\partial^2 f}{\partial x^2} ) 这些项。二阶展开的精度更高但计算量也更大因为要算张量。在实际应用中iLQR通常已经够用了DDP主要在需要高精度控制的场景下使用比如航天器轨迹优化。选择哪个取决于你的任务对精度的要求和计算资源的限制。如果动力学非线性很强一阶展开误差大那DDP可能更合适如果动力学比较平滑或者计算资源有限iLQR就足够了。我个人的经验是先试iLQR如果收敛不好或者精度不够再考虑DDP。大部分机器人控制任务iLQR都能搞定。5. 基于模型的强化学习实操与问题排查5.1 用神经网络学动力学模型的注意事项基于模型的强化学习里动力学模型通常用神经网络来学。输入是当前状态和动作输出是下一状态或者状态差分。训练数据是从真实环境里采样的轨迹。这里有几个坑要注意第一数据归一化。状态和动作的尺度可能差很多比如位置是米级速度是米每秒如果不归一化神经网络很难学好。我一般会把所有输入输出都归一化到零均值单位方差训练完再反归一化。第二模型不确定性。神经网络学出来的模型在训练数据分布内可能很准但在分布外可能错得离谱。所以做规划的时候如果规划出来的轨迹跑到了数据稀疏的区域模型预测就不可信了。解决办法是用集成模型ensemble来估计不确定性或者加一个惩罚项让规划尽量待在数据分布内。第三模型误差累积。如果规划步长很长模型误差会逐步累积导致规划出来的轨迹在真实环境里完全不能用。解决办法是缩短规划步长或者用MPC模型预测控制的思路只执行规划轨迹的前几步然后重新规划。5.2 规划与控制中的常见问题速查下面这张表整理了我实际做基于模型强化学习时遇到的一些典型问题以及对应的排查思路和解决方法问题现象可能原因排查方法解决方法规划轨迹在真实环境里跑偏模型误差累积对比模型预测和真实 rollout 的偏差缩短规划步长用MPC训练时代价不下降学习率太大或线搜索没加打印每次迭代的代价减小学习率加回溯线搜索模型预测在分布外完全错误数据覆盖不足检查规划轨迹是否超出训练数据范围加不确定性惩罚用集成模型iLQR迭代发散初始轨迹太差检查初始轨迹的代价用PID或随机打靶法找更好的初始解Riccati方程解不出正定P系统不可稳定检查A、B矩阵的可控性重新设计系统或换控制方法这张表里的每一条都是我实际踩过的坑。比如“规划轨迹跑偏”这个问题我当初做PETS的时候规划步长设了20步结果模型误差累积到后面完全不能用。后来改成只规划5步执行前2步然后重新规划效果就好多了。这就是MPC的思路虽然简单但非常有效。5.3 实操心得与避坑技巧最后分享几个我在做基于模型强化学习时总结的小技巧技巧一先用LQR验证你的规划器。如果你实现了一个iLQR或者打靶法规划器先在一个线性系统上测试跟LQR的解对比。如果结果一致说明你的规划器实现没问题如果不一致那肯定是哪里写错了。这个验证步骤能帮你排除很多低级bug。技巧二模型训练时用多步预测损失。如果只用单步预测损失训练模型模型在长程预测上可能很差。我一般会用多步展开的损失比如预测未来5步的状态然后跟真实轨迹对比。这样学出来的模型在规划时更可靠。技巧三规划时加动作平滑惩罚。如果规划出来的动作序列抖动很厉害可以在代价里加一项惩罚动作的变化量( |u_{t1} - u_t|^2 )。这样规划出来的轨迹更平滑在真实系统上也更容易执行。技巧四用随机打靶法做快速原型。如果你不想实现iLQR那么复杂的规划器可以先用随机打靶法随机采样一堆动作序列在模型里 rollout选代价最低的那个。虽然简单但在很多任务上效果已经不错了。我一般用随机打靶法做快速验证确认思路可行之后再换成iLQR做精细优化。技巧五注意数值稳定性。LQR和iLQR涉及大量矩阵求逆数值稳定性很重要。如果Riccati方程递推的时候P矩阵变得不正定可以加一个小正则项 ( \epsilon I ) 到求逆的矩阵里。这个技巧在实现的时候很实用能避免很多数值问题。这三讲的内容我前前后后啃了大概一个月中间反复看了好几遍视频推了好几遍公式又自己写代码实现了一遍iLQR和基于模型的规划器。现在回头看这段时间花得非常值。因为后面学任何基于模型的强化学习算法底层都是这套东西。而且LQR本身在工程里应用极广学会了之后遇到控制相关的问题第一反应就是“能不能用LQR的思路来解”这个思维方式的转变才是最大的收获。
阅读完成 · 觉得有帮助?