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

资讯详情

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

橡皮鸭走迷宫玩出强化学习:从奖励设计到PPO实战全拆解

橡皮鸭走迷宫玩出强化学习:从奖励设计到PPO实战全拆解 这个转发很有意思。很多人第一眼看到是一只橡皮鸭在走迷宫、找食物、躲障碍以为就是动画片或者娱乐视频实际上它是把强化学习里的核心机制用一只能看能动的“鸭子”完整演了一遍。我在几个平台都刷到过这个视频评论区讨论最多的其实是这只鸭子到底是怎么学会走路的它拿到奖励之后为什么能记住如果我换成机械臂、无人机或者一个游戏机器人是不是也按这个逻辑来做刷了几遍之后我自己的判断是这个视频适合两类人看。第一类是刚接触强化学习、还没弄懂状态、动作、奖励、策略之间关系的人这类人看完能建立起直觉第二类是已经跑过强化学习代码、但训练时经常不收敛、奖励一直跳、模型卡在局部最优的开发者这类人看完会发现很多训练问题都能在“鸭子演示”里找到对应关系。所以这篇文章不打算只讲视频本身我会把视频里那只鸭子的行为翻译成强化学习里最常用到的训练流程然后结合真实项目里跑强化学习会遇到的环境搭建、参数设置、奖励设计、离线训练这些问题一起拆开讲。文章后面会给出一个可以参考的最小示例还有我在实际训练时踩过的一些坑。1. 用一只鸭子把强化学习四个要素讲清楚了1.1 状态、动作、奖励、策略其实都能在鸭子的日常里找到对应视频里的鸭子如果是在模拟环境里移动那只鸭子的位置、方向、嘴巴朝向、当前食物距离这些都属于“状态”。一次行走、一次转头、一次张嘴咬住食物都是“动作”。吃到食物就是一个正奖励撞到障碍或者一直原地打转就是一个负奖励或低奖励。而它下一步怎么做是往左还是往右是继续走还是停下来这个选择规则就是“策略”。强化学习里最常用的数学描述是马尔可夫决策过程也就是当前这一步的决策只依赖当前状态不需要追溯到很久以前。鸭子站在岔路口它只需要知道“我现在在哪、前面有没有食物”不需要把出生以来每一步都重新回忆一遍。这个“只看当前”的设定很多新手会觉得太简单了但实际训练中几乎所有的算法都是基于这个假设来更新的。用鸭子来类比的好处是它把抽象的奖励函数变成了特别直观的行为现象。比如鸭子本来往左走结果踩到一滩水被扣分下一次训练里它会增加往右走的倾向。这就是策略更新。如果它连续十次往右走都拿到食物那个通向食物的动作路径就会被保存下来。如果环境里还有一只猫在追它那状态还要包含猫的位置这就是动态环境下的强化学习任务。1.2 从鸭子演示到实际项目最先要抓住的是“奖励给了什么”视频弹幕和评论区经常出现一句玩笑话如果奖励设计得不好鸭子就学会了原地转圈刷分。这句话很真实是我在项目里反复遇到的场景。奖励是强化学习的指挥棒。如果设计者告诉鸭子“碰到食物加 1 分”鸭子会慢慢学会朝食物移动。但如果你还加了“不停下来再加 0.1 分”那它可能会找到一条捷径在食物旁边来回走而不是把食物吃掉。这在实际训练里很常见比如机械臂抓取任务里如果奖励只给“接近目标”机械臂可能会停在目标上方来回抖动因为那样也能拿到接近奖励但抓取动作永远不会完成。所以视频里那只鸭子看起来动作自然背后通常要经过很多次奖励调整。它身上每一处“看起来合理的走位”都意味着奖励函数在平衡“做对了”和“持续探索”这两件事。这也是我在后面会专门展开的部分因为很多强化学习实例跑不出理想效果问题不在算法代码而是奖励给偏了。2. 从鸭子演示到第一个可跑实例先把环境跑起来2.1 为什么建议从自带环境开始而不是一上来就自己搭场景看完视频如果手痒最简单的上手方式不是立刻去做一个 3D 鸭子而是先找一个已经有强化学习接口的环境跑一个最小样例。视频里那只鸭子的动作虽然看起来简单背后其实涉及物理模拟、碰撞检测、图像渲染或坐标状态处理这些从零搭会消耗大量时间。以 Python 生态为例最常用的入门组合是gymnasium加stable-baselines3。gymnasium负责提供环境和交互接口stable-baselines3负责提供现成算法比如 PPO、DQN、SAC。新手不用先自己写策略更新公式而是先观察环境是怎么交互的等理解之后再改算法。环境选型建议按难度分三级难度环境示例适合练习点入门级CartPole小车上杆状态少动作少第一次跑通算法进阶级简单的二维寻路或抓取场景开始设计奖励、处理稀疏奖励应用级机械臂、无人机、机器人仿真需要处理连续动作、多任务目标第一次跑的时候重点不是看算法多么厉害而是确认四件事环境能启动、动作能执行、奖励能返回、状态能更新。只要这四步通顺后面调参才有意义。2.2 一个最小示例安装依赖、初始化环境、跑一个随机策略我先给出一个偏演示的轻量示例。它不能直接运行在你这台机器上因为具体环境名称和版本可能不一样但整条链路是一致的你可以根据自己实际环境改名字。# 安装依赖的参考命令具体版本以你所在环境为准 # pip install gymnasium # pip install stable-baselines3 import gymnasium as gym # 选择一个环境 env gym.make(CartPole-v1) # 重置环境拿到初始状态 state, info env.reset() for step in range(100): # 用一个随机动作作为示例 action env.action_space.sample() # 执行动作返回状态、奖励、是否结束、是否截断和其他信息 next_state, reward, terminated, truncated, info env.step(action) if terminated or truncated: break这段代码看起来简单但它把强化学习项目的骨架暴露出来了初始化环境、根据当前状态选动作、执行动作、拿奖励、判断任务是否结束。所有强化学习训练流程都是在这个循环里加策略网络、加经验存储、加损失更新。跑这段代码之前我一般会先看一眼env.action_space和env.observation_space。这一步很多人跳过但后面一旦报错基本都是这个信息没确认好。动作空间是离散的整数还是一组连续浮点数直接影响算法选择。观察空间是几个字段还是一张图片也直接影响神经网络输入层怎么设计。2.3 从随机策略换成 PPO只需要改调用代码如果随机策略已经能跑通就可以把算法换成 PPO。PPO 是现在最稳妥的入门算法之一它不像 DQN 那样对奖励数值特别敏感也比一些早期策略梯度算法更好调参。对于第一次训练来说选 PPO 踩坑最少。from stable_baselines3 import PPO model PPO( MlpPolicy, env, verbose1, learning_rate3e-4, n_steps2048, batch_size64, n_epochs10, gamma0.99, gae_lambda0.95, clip_range0.2, ) # 先训练一个很短的时间确认日志正常 model.learn(total_timesteps10000)这里有几个参数在新手阶段先关注四个learning_rate学习率太大容易震荡太小训练太慢。n_steps每次更新前收集多少步经验大一点训练更稳定但内存占用高。batch_size每次梯度更新用的样本量。gamma折扣因子表示未来奖励在当下决策里占多大权重。不要急着把total_timesteps设成几千万。第一次训练可以把时间步设小一点观察日志里的ep_len_mean和ep_rew_mean。如果平均奖励在持续上升说明方向基本正确。3. 鸭子能不能学会关键看动作空间和奖励边界3.1 离散动作和连续动作训练难度完全不一样视频里的鸭子如果只是在二维网格里移动那方向可以抽象成“上、下、左、右”四个离散动作这是最简单的强化学习任务。但如果换成视频形式鸭子要平滑转向、控制速度、调整身体倾斜角度那动作就变成了连续空间。机械臂、无人机、自动驾驶基本都是连续控制问题。离散动作适合用 DQN 这类基于价值的方法连续动作更适合用 PPO、SAC、TD3 这类基于策略的方法。选错算法不一定完全跑不出来但训练效率会差很多。问题类型动作示例常用算法方向难度点离散动作上、下、左、右、跳跃DQN、Double DQN动作数量变了输出层要改连续动作速度、角度、力矩PPO、SAC、TD3要处理探索与稳定的平衡如果你的任务里有“连续控制”需求尽量不要把连续动作强行离散化。比如机械臂的关节角度如果你只允许 0 度、30 度、60 度三挡机械臂很可能实现不了精细抓取。这类问题里用 PPO 或者 SAC 会更合理。3.2 稀疏奖励和密集奖励怎么取舍强化学习里有一个常见难题一些任务根本给不出密集奖励。比如鸭子走到迷宫出口才算成功中间所有位置都没有积分奖励这就是稀疏奖励。稀疏奖励会让训练非常难因为算法不知道中间哪些动作是对的只能靠大量随机探索碰运气。遇到稀疏奖励我一般按这个顺序做调整先看能不能在环境中加入过程性奖励比如离目标近了就加小分。如果加过程奖励后训练还是不稳定就考虑用奖励塑形把最终目标拆成子目标。如果子目标也难定义可以尝试逆强化学习或课程学习但这两类方法不适合纯新手先不用碰。过程性奖励要小心“太密”。如果每一步都给出非常大的奖励模型可能会选择原地不动因为它发现不动也能拿稳定分数。奖励不是越密越好而是要让每一步行动的收益都能体现出“和目标的相对关系”。3.3 奖励遇到错误信号时训练会变成什么样热搜里有一个词叫“强化学习遇到错误奖励”这精确描述了一个非常隐蔽的坑。很多强化学习项目跑起来日志看起来在涨但策略输出的行为在业务上完全不合理这通常就是奖励函数和真实目标不一致。我自己遇到过的最典型情况是设计任务时给“接近目标”加了一个大奖励给“到达目标”只加了一个小奖励。结果模型学到的是“来回接近目标但永远不到达目标”因为那样刷分更快。表面上看奖励曲线在涨实际任务完成率是零。这种问题的排查方法并不难但不是看训练日志就能发现。你需要单独设计一个评估环节让模型执行完之后人工检查实际效果。如果只看训练平均奖励会被假象骗很久。视频里如果鸭子看起来是在走迷宫但它的运动轨迹没有真正靠近终点那奖励就很可能给错了。我建议每个强化学习项目都做一个“行为观测”步骤训练完一个阶段后把模型跑成视频或轨迹文件人眼过一遍。不要只保存模型权重不保存行为轨迹。很多问题看一眼轨迹就知道是奖励给错了还是动作空间设小了。4. 训练不稳定、不收敛和离线强化学习的取舍4.1 强化学习项目失败先按这个链路排查无论你是跑鸭子演示还是跑一个真实的机械臂或无人机任务训练失败时的排查路径很固定。我自己的习惯是按以下顺序一层层排除不要一上来就改算法。第一步先看环境交互是否正常。环境能不能重置动作执行后状态有没有更新终止条件会不会永远触发或永不触发如果环境本身就有 bug训练再久也没有意义。第二步看奖励的数值分布。记录每一步的即时奖励输出奖励最大值、最小值、平均值。如果奖励数值跨度太大比如几百到几千之间乱跳算法的损失也会跟着乱跳。这种情况下要检查奖励缩放。第三步看策略能不能做最简单的单步动作。先不看长任务只在环境里让模型完成一个非常简单的动作比如移动到正前方的一个固定点。如果连这个都学不会说明算法或环境还有问题而不是模型能力不够。第四步看状态输入有没有被标准化。强化学习对状态尺度非常敏感。一个状态是 0 到 1 的小数另一个状态是 0 到 1000 的坐标值如果直接拼在一起输入网络训练稳定性会非常差。可以先做归一化处理。第五步看日志里的平均步长趋势。平均步长变长了通常说明模型学会了让任务持续更久平均步长总是很短说明模型总在早期就失败这时优先查终止条件再看奖励引导。现象优先排查方向训练一开始奖励就很大随后崩掉奖励范围、学习率奖励一直很小几乎不变环境探索范围、状态标准化、奖励密度训练出现 NaN学习率、梯度裁剪、输入特征训练到某个阶段后不再提升探索率衰减、局部最优、奖励边界日志正常但业务效果差奖励函数与目标不一致4.2 在线训练成本太高离线强化学习成了务实选择热搜里出现一句话叫“IQL 离线强化学习”。IQL 的全称是 Implicit Q-Learning它是离线强化学习里比较常用的一类算法。离线强化学习和在线强化学习的核心区别在于在线强化学习需要不断和环境交互一个回合跑完数据立刻用来更新策略然后继续探索离线强化学习只用一份已经收集好的数据不和环境交互只靠历史数据训练出一个策略。为什么这个方向会火因为很多真实项目里在线训练花的钱和精力太高。机器人如果每一次动作失败都要在真实机台上试一遍成本很难接受无人机在室内仿真里能飞但换到室外环境就很难反复试错。而离线强化学习相当于从已有的失败和成功经验里学习。但是离线强化学习有一个很明显的坑它只能学到“数据集覆盖范围内的策略”。如果历史数据里从来没有出现过某个动作模型不会凭空学会这个动作。用一句白话讲离线强化学习是一个“比葫芦画瓢”的过程数据集里没有的瓢它画不出来。IQL 这类方法在处理离线数据时会比朴素 Q-learning 更稳定。朴素 Q-learning 在离线数据上容易过高估计没见过动作的价值IQL 通过限制价值估计的范围缓解这个问题。但离线强化学习依然要吃数据分布。如果只是入门实践我建议不要一上来就做离线强化学习。先跑通在线训练理解奖励、环境、状态这些基础概念再去看离线数据里的数据分布问题会顺利很多。4.3 基于模型的强化学习和无模型强化学习怎么选热搜里还有“基于模型强化学习”这个词。这个方向和无模型强化学习是两条不同的技术路线。无模型强化学习是让算法直接根据环境返回的奖励来调整策略它不关心环境内部怎么变化。PPO、DQN、SAC 都是无模型方法。鸭子视频里如果只是根据“吃到食物”来判断好坏就是无模型强化的思路。基于模型强化学习则先让模型学习“环境的动态变化”。比如鸭子往前走一步可能遇到石头、可能遇到斜坡模型会尝试学习“当前状态 动作 → 下一个状态”这个转换关系。学会这个转换关系后可以少做很多真实环境交互因为算法可以在自己学到的环境模型里提前做规划。两种方法各有适用场景方法类型优点缺点适合场景无模型不依赖环境建模通用性强样本效率低需要较多交互仿真中训练游戏角色、机械臂基于模型样本利用率高能提前规划环境模型不准确时误差会累积真实环境成本高、交互次数有限很多人认为基于模型一定比无模型强这个想法不一定对。环境模型如果学不准后面的规划反而可能把模型带偏。实际项目中如果仿真速度足够快在线交互成本低无模型往往是更容易落地的方式。4.4 逆运动学和强化学习结合是机械臂方向最常见的组合热搜里“mujoco 机械臂 ppo 强化学习逆向运动学ik”这条说明很多人开始把强化学习和机器人运动学结合起来。这里简单解释一下。机械臂抓取一个目标通常先通过逆运动学解算出关节角度然后让机械臂走到那个角度。但真实环境里目标会移动、会有障碍物纯靠逆运动学实时求解不总是稳定。强化学习的加入方式一般是用逆运动学先生成一些可行轨迹或参考动作再把强化学习放在上层根据当前目标动态调整关节角度。PPO 在 Mujoco 这类物理仿真里跑机械臂任务算是比较常见的选择。但要注意机械臂这类任务动作空间往往是多关节连续力矩或角度状态空间也包括机械臂每个关节的角度、角速度、目标位置维度高了之后训练变慢是很正常的。低配环境里可以先降低控制频率减少每一步的复杂度而不是把状态维度全部塞进去。这类项目最容易出问题的地方是第一轮训练就期望机械臂直接学会完整抓取。更稳的做法是把任务拆成子任务先学“接近目标”再学“对准目标”最后学“夹取”。每一步单独训练和评估最后再拼成一个完整流程。这个思路和鸭子走迷宫一样如果鸭子连“走到食物旁边”都不会那“把食物叼起来”就更加无从谈起。5. 训练过程中的日志、可视化与常见坑5.1 TensorBoard 或 wandb至少选一个强化学习的训练日志非常关键因为它的训练过程不像普通深度学习那样迅速下降一个稳定损失而是充满波动和跳变。如果你只看终端输出的模糊数字很难判断模型是不是真的在进步。我个人的建议是第一次训练就用 TensorBoard或者直接连 wandb。至少记录每个时间步的奖励均值、回合长度、损失函数值、学习率变化。训练一段时间后用图表看趋势比看枯燥数字更直观。实际记录时有一个字段建议额外保存每个回合中“首次获得正奖励的时间步”。这个字段能反映探索效率。如果很长时间都没有出现正奖励说明奖励太稀疏或探索范围太小要优先处理而不是继续训练。5.2 可视化环境时注意仿真速度瓶颈可视化会消耗不少计算资源。视频里那种让鸭子视觉化移动的场景如果你边训练边渲染训练速度会明显下降。新手第一次跑的时候可以先关掉渲染只输出日志。需要观察行为时可以单独加载一个已训练模型把环境设置成可以渲染的模式跑几次看轨迹。不要一边训练一边开渲染否则很多低配机器会直接卡成幻灯片。如果是跑机械臂或无人机仿真还要注意 CPU 和 GPU 资源分配。物理仿真通常吃 CPU神经网络训练吃 GPU两者如果争抢资源训练就会来回抖动。5.3 遇到训练时间过长先降条件再降需求很多强化学习项目最终不是死在算法上而是死在“等不起”。比如你想训练一个高分辨率图像输入的智能体每一步都要处理一大张图数据收集的速度会明显变慢。这种情况下的第一个优化方向不是换更强的 GPU而是降图像分辨率。如果降分辨率之后任务难度变高、无法收敛可以考虑用状态特征代替图像输入。比如机械臂任务里不一定非要输入一整幅图像可以直接给目标的三维坐标和机械臂关节角度很多任务用这种低维状态就能训练得很好。图像输入只有在需要语义理解的场景里才是必须的比如识别不同颜色或形状的物体。训练时间也可以从n_steps入手。这个值越大每次更新前收集的数据越多稳定性更高但单次更新时间更长。如果发现训练速度太慢可以适当调小如果发现训练震荡可以适当调大。这个值没有一个万能答案需要根据你的任务和环境一步步试。6. 从鸭子科普到生产项目还需要补哪些能力6.1 单条任务能跑只是第一小步视频里鸭子在同一个地图里来回走如果换了一张新地图它还走得好吗这就涉及强化学习里的泛化能力问题。很多模型在一个固定环境下训练得很漂亮换一个初始位置或障碍物布局表现就明显下降。要解决这个问题最直接的办法是在训练时引入随机化。环境初始化时随机生成起点、目标位置、障碍物位置甚至随机改变一些物理参数。这样训练出来的模型才有机会适应更多场景。这在实际生产项目里非常重要尤其是机械臂和无人机因为真实环境不可能每次都是同一个起始位置。我自己见过最多的失败案例是模型在仿真环境里跑得不错一到真实环境就失灵。这种情况通常不是仿真不真实而是训练时没有加入足够的随机性模型把仿真里的固定初始条件当成了规律。6.2 模型训练完了还要考虑部署和接口如果是从零入门跑通训练就够满足了。但如果你的目标是落地训练完之后还要考虑模型输出怎么接入业务系统。强化学习模型部署和普通深度学习模型部署不太一样。普通模型往往是输入一个样本输出一个结果流程固定。强化学习模型需要在环境里持续交互每一步输出一个动作后要接收新的状态再输出下一个动作。所以部署时需要一个循环控制逻辑还需要处理超时、异常状态、安全边界。比如一个机械臂强化学习模型部署时不会让它直接控制真实机械臂而是先在仿真环境里做大量测试。测试内容包括目标移动到边界位置时动作是否仍然稳定。连续运行多个回合之后会不会出现累加误差。模型输出的动作幅度是否超出机械臂物理限制。遇到异常状态时有没有保护机制比如急停、回退、重置。这些内容在科普视频里不会出现但真实项目里每一项都比训练本身更花时间。6.3 如果只是学习优先把基础算法吃透不少读者看完鸭子演示后直接想跳到最复杂的算法比如离线强化学习、多智能体强化学习、模型预测控制。但这个顺序通常不太好。我建议的学习路径是用有现成环境实现一个随机策略理解环境交互链路。用 DQN 跑通一个离散动作小游戏理解价值函数。用 PPO 跑通一个连续控制任务理解策略更新和优势估计。再探索奖励塑形、稀疏奖励、课程学习。最后接触离线强化学习、多智能体强化学习等进阶方向。每一步都尽量做一遍“调参数”的动作而不只是“跑通”。跑通用的是默认参数调参数才是理解算法的过程。比如训练一个鸭子走迷宫的理想过程应该这样拆第一轮随机策略观察它怎么失败。第二轮加入密集奖励让鸭子能朝食物移动。第三轮减小奖励密度让鸭子学会更接近目标的路径。第四轮增加障碍物随机位置测试泛化能力。每一轮都记录下来。训练日志、奖励曲线、行为轨迹都要留档。等回看的时候你会发现很多问题和坑都有规律。7. 关于那只鸭子最后想说的经验这个视频看起来轻松但它确实把强化学习里最难讲清楚的“奖励驱动行为”讲出来了。很多人学强化学习时把精力放在公式和推导上忽略了对“行为”的直观理解。其实很多训练问题回到“这只鸭子为什么这么做”的层面答案反而更清晰。如果鸭子撞了墙你不会怪墙而是会想它为什么没避开墙。对应到项目里模型输出不合理行为时不要只怪模型要看一下它是在优化哪个奖励信号。如果鸭子原地转圈很可能不是它笨而是奖励设计让它觉得转圈比走路收益更高。我建议你把这个视频当作一个起点但不只是停留在“看懂了”。看懂之后去跑一个最小的强化学习实例让一个虚拟角色在环境里根据奖励走起来。哪怕第一步只是随机动作都比你连续刷十遍科普视频更接近强化学习的本质。真正跑起来之后你会发现强化学习和其他深度学习方向最不一样的地方它不是一次训练出一个静态输出而是让一个决策者在一连串试错里逐步改变行为策略。这个循环本身就是训练的核心。鸭子也好机械臂也好无人机也好都在重复同一个逻辑尝试、得到反馈、调整策略、再次尝试。把这条链路理清楚强化学习的入门就算真正开始了。
返回列表