ARTICLE DETAIL

资讯详情

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

强化学习算法地图:DQN与PPO实战调参指南

强化学习算法地图:DQN与PPO实战调参指南 如果让我给刚接触强化学习的同学提一条建议我不会推荐先去啃砖头教材里的公式推导而是建议先建立一张属于自己的算法地图。因为强化学习这个方向最劝退的地方不是某个算法有多难而是算法太多了DQN、PPO、SAC、TD3、IQL、MADDPG、MAPPO……每个都号称SOTA每个都有一堆变体翻两天资料下来大部分人连该用哪个算法解决我的问题都判断不了。这份笔记是我在实际项目里反复调参、踩坑之后整理出来的把强化学习的数学框架、DQN和PPO两个主干算法的来龙去脉、训练曲线的正确分析方式、机械臂从仿真到真机过程中和摩擦力有关的那些坑以及离线强化学习和多智能体算法的选型逻辑串在一起。适合已经知道强化学习大概是什么、但还在算法选择和训练调参阶段挣扎的朋友。1. 强化学习先要建立一张算法地图MDP、贝尔曼方程与三个判断维度1.1 从MDP开始理解智能体与环境的对话强化学习问题本质上是一个马尔可夫决策过程MDP由五元组组成状态集合 S、动作集合 A、状态转移概率 P、奖励函数 R、折扣因子 γ。智能体在每个时间步观察状态 s_t根据策略选择动作 a_t环境返回下一个状态 s_{t1} 和奖励 r_t目标是最大化期望累积折扣回报 G_t Σ γ^k r_{tk}。很多初学者把注意力全放在神经网络结构上忽略了MDP本身。实际上你面对的实际问题能不能用强化学习解决第一步就是能不能把它抽象成标准的MDP。我见过不少项目连状态定义都没想清楚就急着套PPO最后训练出来的策略看起来在涨换到新场景就崩。状态设计至少要满足马尔可夫性即当前状态已经包含了决策所需的全部信息否则后续所有计算都会失真。折扣因子 γ 的选择也常被忽视。γ 越接近1智能体越有远见但价值函数的方差会变大训练更不稳定γ 太小智能体只关心眼前收益容易短视。机器人控制类任务我一般从 0.99 起步简单栅栏世界 0.9 就够用。这个参数会让同样的算法跑出完全不同的曲线值得每次实验都记入配置。1.2 价值函数、策略与贝尔曼方程的关系理解了MDP之后第二个绕不开的概念是价值函数。状态价值 V(s) 表示从状态 s 出发按当前策略行动能够获得的期望回报动作价值 Q(s,a) 表示在状态 s 执行动作 a 之后再按当前策略行动获得的期望回报。两者满足贝尔曼方程V(s) Σ_a π(a|s) [R(s,a) γ Σ_{s} P(s|s,a) V(s)]Q(s,a) 的贝尔曼方程也是同理。这个方程最核心的思想是当前价值可以用下一步价值来表示正是这个自举bootstrapping结构让强化学习算法可以逐步逼近真实价值函数而不是等到轨迹结束才开始学习。我个人的理解习惯是把贝尔曼方程当成动态规划的一种泛化如果环境模型已知可以直接用值迭代求解模型未知就通过采样来估计。DQN系列本质上是用神经网络代替 Q(s,a) 表 用经验回放近似贝尔曼更新而策略梯度系列则是直接优化策略本身来判断哪些动作值得增加概率。理解到这一层后面看任何算法都不会迷路。1.3 把算法分成三类基于值、基于策略、Actor-Critic我在笔记里通常把强化学习算法分成三类分类维度不是新旧而是优化对象类别代表算法优化对象适应场景基于值Q-Learning、DQN、Double DQN、Dueling DQNQ(s,a) 逼近最优动作价值离散动作、状态空间较大基于策略REINFORCE、TRPO、PPO直接优化策略 π(as)Actor-CriticA2C/A3C、SAC、TD3、PPO同时优化策略与价值连续控制、大规模问题PPO 同时被归到策略类与 Actor-Critic 类是因为它有一个 Critic 网络用来估计优势函数但核心优化目标仍然是策略网络。理解 Actor-Critic 的关键在于两个网络各司其职Actor 决定怎么动Critic 判断动得好不好。1.4 如何选择动作空间、采样成本与数据来源拿到实际问题我建议按三个维度做选型判断比看论文里的 benchmark 表格有用得多。第一个维度是动作空间。如果是离散动作比如控制一个开关、选择一份调度方案DQN 及其变体简单够用。如果是连续动作比如机械臂关节力矩、车辆转向DQN 基本不可行必须直接上连续控制算法主流是 PPO、SAC、TD3。第二个维度是采样成本。仿真环境里可以并行采样百万步直接用 PPO 完全没问题真实机器人上每步都要耗费时间且可能损坏硬件需要优先考虑样本效率更高的算法SAC 通常比 PPO 更省样本但超参数更敏感。第三个维度是数据来源。如果只能使用收集好的历史数据不能与环境在线交互那就属于离线强化学习范畴要选 IQL、CQL 这类专门处理分布外动作的算法。很多工业场景恰恰是这种因为生产线上不允许你随便试验新策略。2. DQN及其变体为什么经验回放和目标网络缺一不可2.1 从Q表到深度Q网络的跨越经典 Q-Learning 的更新公式是 Q(s,a) ← Q(s,a) α [r γ max_{a} Q(s,a) - Q(s,a)]。这里用一张表格记录每个状态动作对的价值。状态稍微复杂一点比如一张 84×84 的 Atari 游戏画面表格直接爆炸。DQN 的核心贡献是用神经网络 Q(s,a;θ) 来逼近 Q 函数。网络输入是状态输出是每个离散动作的 Q 值。训练过程看似简单采样一条经验计算目标 y r γ max_{a} Q(s,a;θ⁻)做一次梯度下降。但如果真这么训练你会发现 loss 反复震荡甚至发散原因有两个相邻样本高度相关破坏了独立同分布假设目标值也在不断变化等于自己追着一个移动的靶子跑。2.2 经验回放与目标网络DQN 引入的第一个机制是经验回放池。把与环境交互得到的四元组 (s, a, r, s) 存进一个循环队列训练时从中随机均匀采样一个 batch。这样一来相邻样本的相关性被打散数据利用率也提高了。实现时值得注意的一点回放池不要做得太大我踩过容量设成 1e6 后老样本长期采不到、策略反而学不动的坑Atari 级任务常用 1e5 或 3e5如果你的状态维度不高1e5 起步就够了。第二个机制是目标网络用一套参数延迟更新的网络 θ⁻ 计算 Q 目标而不是直接用在线网络。每隔 C 步把 θ 硬拷贝给 θ⁻或者采用软更新 θ⁻ ← τ θ (1-τ) θ⁻τ 通常取 0.005 或 0.001。目标网络降低了目标值频繁移动造成的发散风险这是 DQN 能稳定训练的命根子。目标网络更新频率我建议记入实验记录。太高等于没有目标网络太低则目标长期不更新价值函数会滞后。我调试机械臂环境时发现硬更新每 1000 步一次往往比每 100 步稳定得多。2.3 Double DQN与Dueling DQN到底改了什么DQN 还有两个高频变体被论文大量使用。Double DQN 解决的是 Q 值过高估计问题。原版 DQN 在计算目标时直接取 max_{a} Q(s,a;θ⁻)噪声会让最大值被系统性高估。Double DQN 的做法是用在线网络选动作用目标网络评估该动作的价值a* argmax_{a} Q(s,a;θ)y r γ Q(s,a*;θ⁻)。这个简单的动作选择和价值评估解耦在不少任务里显著改善了策略质量几乎零成本我建议直接作为默认配置。Dueling DQN 则把 Q 值拆成状态价值 V(s) 和优势 A(s,a) 的和Q(s,a) V(s) A(s,a)。好处是在某些状态下无论选择哪个动作都一样关键时网络不需要为每个动作都维护一套独立的 Q 值更新更高效。它的实现要点是最后做了优势中心化避免优势函数在状态上飘移。实际项目里我通常 Double Dueling 优先经验回放 组合着用但优先经验回放会引入额外的超参数 α 和 β如果团队没有太多调参耐心别一上来就加。2.4 实操中常见的收敛漂移问题DQN 家族训练时最典型的现象是Q 值飞涨但策略表现却没有变好。这时候先不要急着调网络结构按顺序排查四件事奖励是否被裁剪到合理范围我通常把即时奖励 clip 到 [-1, 1]不然累积奖励尺度差异大目标值大幅波动。学习率是否过大DQN 常见稳定学习率是 2.5e-4哪怕 1e-3 也会在部分环境直接失败。回放池大小是否合适池太小样本相关性高池太大旧策略数据过多。目标网络更新频率是否合理结合你的训练步数通常每 500 到 2000 步硬更新一次。额外提醒一个容易被忽略的坑epsilon-greedy 的退火速度。如果 epsilon 从 1.0 掉到 0.1 只用了几千步智能体可能在探索不充分的情况下就锁定了次优策略。建议设计一个简单的指数退火函数让 epsilon 在训练中期才降到 0.1 附近。3. PPO与策略梯度从重要性采样到裁剪目标的工程智慧3.1 策略梯度为什么方差大策略梯度方法直接优化策略网络的参数 θ目标是最大化 J(θ) E[Σ_t γ^t r_t]。推导出的梯度是 ∇J(θ) E[∇ log π(a|s) A(s,a)]其中 A(s,a) 是优势函数表示当前动作相比平均水平好多少。为什么要减去 baseline直接用累积回报 G_t 作为权重梯度方差会非常大。比如某个状态无论选什么动作回报都比较高策略梯度会因为回报绝对值大而大幅改变概率但这些变化与动作好坏无关。减去状态价值估计 V(s) 后只剩这个动作比平均水平好多少的部分方差显著下降。这是所有 Actor-Critic 方法的理论基石。即便有 baseline策略梯度的方差依然比 Q 学习大得多所以 PPO 才需要 GAE广义优势估计进一步平滑。GAE 用 λ 参数在偏差和方差之间做权衡λ0 时等价于一步 TD 误差方差小但偏差大λ1 时退化为蒙特卡洛回报偏差小但方差大。我的默认值是 λ0.95适合大多数连续控制任务。3.2 PPO的核心重要性采样与裁剪目标PPO 解决了策略梯度一个老大难问题在线性策略梯度REINFORCE中每一轮采样出的数据用完就扔样本利用效率非常低。理论上可以用重要性采样把旧策略采到的数据复用到新策略上把目标改写成 J(θ) E[ (πθ(a|s) / πθ_old(a|s)) A(s,a) ]但如果不加约束新旧策略差异一大重要性比 r_t(θ) 会巨大训练直接崩。PPO 的工程智慧在于对目标函数做裁剪clip。它限制重要性比在 [1-ε, 1ε] 范围内当新旧策略差异超过阈值时梯度不再继续奖励偏离只保留安全方向的更新。标准的 PPO 目标是L_CLIP(θ) E[ min( r_t(θ) A_t, clip(r_t(θ), 1-ε, 1ε) A_t ) ]其中 ε 通常取 0.2。这个裁剪看起来简单实际效果极好既保留了稳定性又允许比 TRPO 更简单的实现。TRPO 需要求解带约束的优化问题PPO 只需要做普通梯度上升。3.3 训练流程与几个容易踩坑的超参PPO 的训练流程可以用伪代码概括for iteration in range(total_iterations): # 1. 在环境中收集一批轨迹 # 2. 用当前价值网络计算 GAE 优势估计 # 3. 将数据打乱并切分成 mini-batch # 4. 对每批数据做多个 epoch 的梯度更新 # 更新 Actor: 最小化 -L_CLIP coef * entropy_bonus # 更新 Critic: 最小化 MSE(当前回报 - V(s)) # 5. 清空当前批次数据核心超参数按经验排序重要性从高到低分别是学习率。PPO 对学习率很敏感3e-4 附近是连续控制任务的常见起点调大很容易出现策略崩坏我一般只在 5e-5 到 5e-4 之间搜索。mini-batch 大小与每批训练 epoch 数。epoch 过多会让策略在旧数据上过拟合导致策略分布和采样分布差距过大。默认 3 到 10 个 epoch数据少时取小值。GAE 的 λ 与折扣 γ。λ 影响优势估计平滑度γ 影响远见程度两者尽量在任务确定后就固定不要频繁改动。熵系数。策略的熵 bonus 能鼓励探索通常会随训练衰减设得太大策略永远随机太小容易过早收敛。默认 0.01 起步。一个我经常在别人代码里看到的问题对 advantage 做了归一化但把 normalization 的均值和标准差往整个训练历史累积。这样早期和后期尺度不一致优势估计会失真。正确的做法是在每个训练 batch 内做 norm或者用一个滑动统计窗口。3.4 训练曲线怎么看均值、单次回报与置信区间很多新手只看最终平均回报曲线一路绿就以为训练成功了。我试过好几次平均回报看似收敛实际单个 episode 的回报剧烈震荡机械臂末端已经撞到限位好几次。正确做法是同时看三样东西单次 episode 返回值的原始曲线观察方差。actor 的熵曲线判断策略是否过早确定性。critic 的 loss 或价值估计曲线判断价值网络有没有跟上策略变化。更严谨的评估方式是跑多个随机种子画出置信区间曲线。单一 seed 的结果几乎不能说明算法好坏我之前排过两个算法第一个算法单次实验比第二个高 30%换三个 seed 之后两者几乎重叠甚至第二个更稳。所以论文中的曲线基本都是多条 seed 取均值和方差。用 Origin 画置信区间曲线时我通常是这么操作的每个算法跑至少 5 个 seed记录每个训练步的 reward。由于不同 seed 的训练步长可能不一致先插值统一到公共 x 轴。计算每个 x 点上的均值与标准差95% 置信区间可用 1.96*std/sqrt(N) 估算。在 Origin 工作表里准备好四列step、mean、upper、lower。先画 mean 曲线再选中 upper/lower 列添加误差棒Plot: Error Bar或者在 Origin 的 Plot 里选择 Area 再叠加 Line。如果嫌 Origin 麻烦Python 里直接用 matplotlib 的 fill_between(x, lower, upper, alpha0.3) 一行搞定。有一点要强调如果两个算法的置信区间有大量重叠说明差异不显著不要强行解读成某个算法更好。这个严格的统计意识在工科项目里非常加分。4. 从仿真到真实机械臂摩擦、延迟和reward设计的实战教训4.1 为什么机械臂强化学习这么难我最早做机械臂项目时天真地以为在仿真里用 PPO 训练到 90% 成功率搬到真机就能直接跑。结果真机第一次尝试末端直接高速撞向目标附近的工作台把我吓出一身冷汗。机械臂强化学习难难在四件事叠加动作空间是高维连续的通常是 6 到 7 个关节力矩或速度。采样成本极高真实机械臂一小时可能才跑几百个 episode。仿真模型和真实系统始终存在差异尤其是摩擦力、间隙、柔性。安全约束严格训练期间一次失败动作就可能损坏硬件。因此机械臂项目几乎不能走纯在线学习路线。主流方案是先在 MuJoCo、Isaac Gym 这类仿真器里大规模训练再用 domain randomization 或少量真机微调迁移。4.2 摩擦机器人强化学习最容易忽略的物理量在仿真环境里默认参数往往没有摩擦力或只有一个极小的线性阻尼。真实的减速器、电机、关节处存在明显的静摩擦stiction和库仑摩擦方向切换时还有不连续的摩擦跳变。这个差异在运动方向频繁切换的任务里会被无限放大。强化学习策略在仿真里学到的往往是用微小速度试探、随时反向修正的控制方式。到真机上由于静摩擦的存在微小速度指令可能根本驱动不了关节而一旦突破静摩擦关节又突然窜动。我在项目里观察到策略在零速附近反复震荡表现为高频抖动和异常发热。解决办法有两步。第一步是在仿真里建立更真实的摩擦模型通常用库仑-粘性摩擦近似τ_friction f_c * sign(velocity) f_v * velocity仿真中可以加入静摩擦项但数值求解会变慢许多引擎需要用支持弹性-塑性摩擦或自定义摩擦项的求解器。第二步是 domain randomization在每次训练 episode 开始时从分布中随机采样摩擦系数。例如库仑摩擦系数 f_c 在 [0.1, 0.4] 之间随机粘性系数 f_v 在 [0.01, 0.05] 之间随机。仿真里不精确但随机比精确但不随机迁移效果更好。另外真机调试前可以做一次简单的摩擦辨识让机械臂空载以不同速度匀速运动记录所需力矩再拟合力矩-速度关系曲线。这个数据能帮你把仿真摩擦区间校准到真实范围内而不是瞎猜。4.3 reward 设计的两个原则reward design 是机械臂强化学习里最容易被忽视的课题。我总结出两个必须遵守的原则第一个原则是势能函数塑形。用距离差 r_t d_{t-1} - d_t 作为奖励比用距离绝对值要稳定得多。只给 -distance 奖励时智能体发现离得越远惩罚越大在 Epic 场景里反而可能学习绕远路来降低瞬时惩罚的方差而势能塑形在理论上不改变最优策略实际训练也稳定得多。第二个原则是明确惩罚每一次危险交互。末端速度过大、关节力矩超过额定范围、末端离目标过快这些都要有对应的惩罚项。很多失败项目只给到达目标的正奖励稀疏奖励让智能体很难学到安全动作。我在任务里常用r α1 * (d_{t-1} - d_t) α2 * (-|τ| - τ_max 的越限惩罚) α3 * (-末端速度的平方) terminal_bonusα1 到 α3 要按任务手动调比例。我通常先只保留距离奖励跑通再把安全和平滑项逐步加进来避免一次引入太多项后不知道是哪里把训练带崩。4.4 从仿真到真机的迁移策略仿真到真机sim-to-real有两条路线零样本迁移和真机微调。零样本迁移靠的是 domain randomization 和随机化视觉/物理参数让策略见过足够多变的动态环境真机微调则是带着安全限制在真实系统上训练少量步数继续优化。实际项目中我推荐组合使用仿真里加入摩擦、质量、延迟、观测噪声的随机化训练一个鲁棒策略真机上先用 PID 或位置控制确保基本安全再逐步切换强化学习策略输出增加力矩限幅。真机微调的学习率一定要比仿真小一个数量级因为真机采到的数据数据量少且噪声大学习率一大直接破坏已有策略。还有一个训练技巧值得记下动作重复action repeat。策略每决策一次底层控制器把动作重复执行 K 次K 通常取 5 到 10。这相当于以更低频率做决策降低了动作延迟带来的非平稳性也给底层硬件更多响应时间。真机的关节速度控制器频率一般是 100Hz 以上策略决策频率 10Hz重复 K 次正好匹配。4.5 安全限位与状态设定建议最后无论是仿真还是真机机械臂强化学习都要有硬限位保护。在仿真里把关节角度、角速度、力矩全部加上约束超限的 episode 直接终止并给予大惩罚。真机端必须设置独立的紧急停止系统和关节软限位优先级高于策略输出和训练算法完全解耦。状态设计我建议至少包含关节角度、关节角速度、末端位置、末端速度、目标位置与末端的相对坐标、上一时刻动作。把上一时刻动作放进观测能有效缓解实际控制中的延迟问题因为策略可以从上一次自己做了什么推断当前系统的响应阶段。这个经验在几篇机器人强化学习论文里也见过亲测效果明显。5. 离线强化学习与多智能体IQL、MADDPG、MAPPO的选择逻辑5.1 离线强化学习的核心问题分布外动作很多工业场景不允许智能体在线试错只能从一个固定数据集中学习这就是离线强化学习。离线强化学习的首要障碍是分布外动作的高估当数据集中没有某些动作的样本时学习的 Q 网络会对这些未见过的动作给出极高却不真实的 Q 值策略一旦选中它们价值函数就崩了。早期直接把 DQN/PPO 用在离线数据上是行不通的因为标准 Q 学习更新里的 max_{a} 会不断访问分布外动作的价值。离线强化学习算法要做的事情就是约束价值估计对未知动作的过度乐观。5.2 IQL的解决思路不做最大化用期望分位取代IQLImplicit Q-Learning是一个我比较推崇的离线算法它实现简单、计算开销小在不少基准上表现和复杂算法打平。IQL 的核心思路是不再计算 max_{a} Q(s,a)而是只利用数据集中真实出现的动作来更新价值函数。具体做法是先学一个 Critic V(s)然后用 expectile regression分位回归的一种拟合 Q 值和 V 之间的关系。直观理解是V(s) 取的是数据集里所有动作价值的分位数而非最大值。这样策略在训练时只提升数据中出现过的、高价值动作的概率避免了 OOD 动作的高估。使用 IQL 时要注意它的超参数 expectile ττ 越接近 1优化越激进但也越容易高估默认值 0.7 或 0.8 是常见选择。如果你的离线数据集质量参差不齐先做数据清洗和奖励裁剪再训练 IQL效果好很多。5.3 MADDPG多智能体环境下的集中训练分散执行多智能体强化学习比单智能体难在环境同时受多个策略影响每个智能体看到的奖励和状态都在变化标准单智能体算法在非平稳环境下会学到崩溃。MADDPG 是目前最经典的多智能体算法之一结构上是 DDPG 加上集中训练、分散执行CTDE框架。训练时每个智能体的 Critic 输入全部智能体的观测和动作从而知道整个环境的联合状态执行时Actor 只依赖自身观测不依赖其他智能体信息。这解决了每个智能体把其他智能体当作环境一部分造成的非平稳问题。如果你要控制多个机械臂协作且智能体是同构的MADDPG 可以归为一类基线。但它在异构任务里收敛速度偏慢动作空间维度翻倍会让 Critic 的输入维度过大训练样本需求成倍上涨。5.4 MAPPOPPO的多智能体改造相比于 MADDPGMAPPO 在近年更受欢迎尤其在星际争霸、足球、多机器人协作等任务上。它的核心思路非常简单把 PPO 直接用到CTDE 框架下每个智能体训练一个策略但 Critic 接收全局信息且多个智能体共享策略参数。MAPPO 能成功的关键不是加了一个全局 Critic而是几个工程细节共享参数但不同智能体身份用 one-hot embedding 区分对每个智能体的 advantage 做归一化训练时把多智能体数据混合成一个 batch价值函数基于全局状态给出更稳定的估计。如果不用这些技巧MAPPO 在很多任务里和普通 PPO 没太大差别。选型上我的建议是智能体之间同构、共享观测结构优先试 MAPPO它调参简单、稳定异构明显或需要个体差异化行为的任务再考虑 MADDPG 这类独立 Actor 的方法。5.5 离线、多智能体与新的方向TRL和基于模型的强化学习顺着离线强化学习的思路还有一个融合多智能体与离线的方向值得关注离线多智能体强化学习直接在多智能体收集的离线数据上训练逻辑就是上面两者的叠加难度更大但很有工业价值。再往前沿看TRLTransformer Reinforcement Learning这个概念是强化学习和语言模型结合的具体库方案把大模型当成策略网络把 text 生成序列当成动作训练目标是用强化学习反馈微调模型对齐人类偏好。虽然和我做的机械臂项目完全属于两个领域但它的算法核心仍然是 PPO只是把状态换成了 token 序列把动作换成了下一步 token。理解 PPO对理解这类工具会有很大帮助。基于模型的强化学习则是另一个分支用一个世界模型来模拟环境动态智能体大多时候不跟真实环境交互只跟世界模型交互大幅降低采样成本。如果预算紧张、真机训练昂贵我会优先考虑先用世界模型预训练一份策略再用少量真机样本校正这也是仿真到真机自然的延伸方向。最后说一个我自己的体会。搞强化学习最怕的不是数学看不懂而是代码能跑、曲线在涨但你看不懂它在学什么。我踩过很多次这样的坑单次实验表现好换 seed 就翻车平均回报收敛但单 episode 还在剧烈震荡仿真顺利真机直接爆炸。所以后来我做任何强化学习实验都会强制自己做好三件事多 seed 取置信区间同时观察 reward、entropy、critic loss任何改动只动一个变量。这套笔记里的很多东西其实都是我一遍遍调参、一遍遍记录曲线得出来的教训。希望它能让你少走一些弯路。
返回列表