前两天在一个技术交流群里看到有人问:“现在规则和规划算法都这么成熟了,还有人老老实实写强化学习吗?”群里立刻分成两派,一派说业务里直接用规则加A*就够,另一派说深度强化学习算法已经卷出花了。我回了一句:强化学习解决的从来不是“能不能动”,而是“在不确定性中怎么持续做对选择”。这句话算是我这些年在机器人调度、游戏AI、仿真控制之间反复横跳后最想表达的东西。
这篇文章算是一份阶段性的强化学习综述,也可以当作一份给团队新人做入门地图的内容。我会先聊清楚强化学习到底在研究什么问题,再顺着算法的发展脉络梳理主流方法,然后按在线、离线、基于模型、因果强化学习这几个方向拆开讲,最后用PPO跑通一个CartPole最小闭环,并落到Gazebo仿真里的多AGV路径规划这类实用场景。内容覆盖概念、公式直觉、代码和踩坑经验,适合刚接触强化学习的读者,也适合已经跑过几个环境但缺乏体系化脉络的工程师。
1. 从多臂老虎机到自动驾驶:强化学习到底解决的是什么问题
1.1 强化学习研究的不是“学一套答案”,而是“学一套决策方式”
你先忘掉那些复杂的神经网络,想象一个最简单的场景:面前有十台老虎机,每台的中奖概率不同,但你不知道哪台高。你手里有有限次机会,怎么在“多试几台获取信息”和“死磕已知最好的那台拿收益”之间做权衡?这就是经典的多臂老虎机问题,也是强化学习(Reinforcement Learning)最朴素的原型。它研究的是如何在未知环境中通过试错来最大化长期累积奖励。
强化学习一般由四个基本要素组成:
- 状态(State):智能体当前观察到的环境描述,比如AGV小车的位置、速度、周围障碍物距离。
- 动作(Action):智能体可选的行为集合,比如左转、直行、刹车,或者输出一个连续的速度指令。
- 奖励(Reward):环境对智能体行为的即时反馈,一个标量,可以正可以负。
- 策略(Policy):智能体从状态到动作的映射规则,也就是“看到什么情况,做什么决策”的核心。
用学骑自行车来类比。你刚骑上车时没有任何经验,摔倒一次,小腿疼一次,大脑就知道这个弯不能转这么急。再摔几次以后,你开始能根据车身倾斜角提前调整重心,科目就对应状态,动作是扭车把和踩踏板,奖励是“没摔”和“顺利前进”。你最终学到的不是某一帧画面下该干什么,而是一整套应对不同路况的决策习惯,这就是策略。
1.2 和监督学习、无监督学习的本质区别
很多人刚接触强化学习时最迷惑的就是:它和机器学习里其他两派到底什么关系?我自己总结过一个很直白的对比:
| 学习范式 | 输入信号 | 目标 | 典型场景 |
|---|---|---|---|
| 监督学习 | 带标签的样本 | 拟合输入到输出的映射 | 图像分类、文本分类、回归预测 |
| 无监督学习 | 无标签的样本 | 发现数据内部结构 | 聚类、降维、异常检测 |
| 强化学习 | 环境返回的奖励 | 通过试错学习最优决策序列 | 游戏AI、机器人控制、调度优化 |
监督学习像判断题,答案就在数据集里,你只需要归纳规律;无监督学习像看一堆拼图,你得自己找出哪块和哪块有关系;强化学习更像闯关游戏,没有人告诉你每步怎么走才对,只有系统在你做完动作后给你一个分数,延迟还可能很长——你可能连着做对了好几步,最后一步走错了,才知道前面也该调整。
这种“延迟奖励”和“序列决策”特性,是强化学习和传统机器学习最不一样的地方。比如棋类对弈,你没法对每一步贴标签说“这步是对是错”,只有终局才见胜负。强化学习可以在这种长链条反馈下,把哪一步的价值都反向估计出来。
1.3 哪些任务适合用强化学习,哪些其实不适合
从我实际项目经验看,适合用强化学习解决的任务一般满足三个条件:状态可以被表达、动作可以被执行、目标可以被量化成奖励信号。比如雅达利游戏、围棋、机器人运动控制、仓库多AGV调度、换热站温度控制、推荐系统里的长期价值优化,这些都有明确边界和反馈信号。
反过来,有些任务用规则和传统优化方法反而更爽。比如单纯的路径最短问题,用A*或者Dijkstra几分钟就出结果,非要上强化学习就是杀鸡用牛刀。还有一些场景,比如医疗决策,错一次代价极高,奖励函数很难定义,强化学习在这里只能做辅助研究。我的判断标准是:如果环境交互成本低、试错空间大、奖励能清晰定义,强化学习就能发挥价值;如果三个条件缺了任何一个,先想清楚再动手。
2. 主流的算法家族:从表格型到深度网络
2.1 免模型与基于模型是一条分岔路
强化学习算法最粗的分叉,是免模型(Model-Free)和基于模型(Model-Based)。
基于模型的方法是先去学习一个环境动态模型,也就是“做了动作a,环境大概会怎么反馈”,然后在这个模型上规划或优化策略。典型的代表有PILCO、Dreamer、MuZero。优势是样本效率高,因为可以在学到的虚拟模型里“脑补”很多数据;劣势是学模型本身很难,模型不准,后面的策略就全歪了。
免模型方法不显式建模环境,直接从交互数据中学策略或价值函数,包括DQN、PPO、SAC、TD3等一大批主流算法。它们实现相对简单,通用性强,是工程落地的主力。代价是样本消耗量通常很大,所以仿真环境在强化学习项目里几乎是标配。
2.2 价值型算法:从Q-Learning到SAC
早期表格型方法里最有名的就是Q-Learning。它维护一张Q表,记录每个状态动作对的长期回报估计,更新公式是:
Q(s, a) ← Q(s, a) + α * [ r + γ * max(a') Q(s', a') - Q(s, a) ]看起来简单,但这套“拿下一步最优Q值回传当前步”的思路,到现在还在几乎所有深度强化学习算法内部跑着。
当状态空间大到表格装不下时,就有深度Q网络(DQN)。DQN把Q表换成了神经网络,用过的都知道两个关键技巧不能少:经验回放和固定目标网络。这两个设计解决的是样本相关性和训练稳定性问题,是深度强化学习算法的奠基性工作。
再到连续动作控制场景,比如机器人关节速度输出,DQN没法直接处理,于是出现DDPG这类确定策略梯度方法。但DDPG出了名地对超参数敏感,所以后来TD3和SAC明显更稳。尤其SAC引入了最大熵思想,让它不只会最大化回报,还会刻意保持策略随机性,避免过早收敛到次优方案。我在仿真环境里做连续控制时,第一选择基本就是SAC。
2.3 策略型算法:策略梯度与Actor-Critic
价值型方法先学“每个动作有多好”,再根据价值选动作;策略型方法更直接,把策略本身参数化,沿着“期望回报对策略参数的梯度”往上涨。最早的REINFORCE属于蒙特卡洛策略梯度,用整个回合的总回报来估计梯度,直观但方差极大。
后来把价值网络和策略网络结合起来,就有了Actor-Critic。Actor负责出动作,Critic负责给当前状态一个基线评分,这样策略网络不用等完整回合就能每步更新,大幅降低方差。A2C、A3C、PPO、SAC、TD3都算这个家族。
PPO是目前工程里最常见的算法之一。它通过裁剪目标函数让策略更新不迈太大步,防止一次更新过多破坏已有策略,稳定性非常好。我自己的感受是:PPO可能不是每个任务上Test得分最高的,但几乎在所有任务上都“不会把你带沟里”,这是它能成为默认起点的原因。
2.4 算法选型速查
| 算法 | 适用动作空间 | 特点 | 工程常见场景 |
|---|---|---|---|
| DQN | 离散 | 引入经验回放与固定目标网络 | 棋类、雅达利、简单离散控制 |
| DDPG | 连续 | 确定性策略,但对超参数敏感 | 经典连续控制 |
| TD3 | 连续 | DDPG的稳定版,双Critic+延迟更新 | 机器人运动控制 |
| SAC | 连续 | 最大熵训练,探索强且稳定 | 机械臂、仿真车辆控制 |
| PPO | 离散/连续 | 稳定、通用、易调 | 游戏AI、AGV调度、多智能体场景 |
| IQL/CQL | 离线数据 | 处理分布外动作,离线专用 | 日志数据策略提取 |
3. 数据流向决定派别:在线、离线与基于模型
3.1 在线闭环:一个“采样、评估、改进”的循环
在线强化学习的流程,所有跑过代码的人都很熟:Agent在环境里探索,收集(状态、动作、奖励、下一状态)四元组,扔进回放缓冲区;学习网络从中采样一批经验,用TD误差更新价值函数或者策略网络;更新完继续让Agent带着新策略和环境交互,反复循环。
这里最核心的矛盾是“探索”和“利用”:如果一直利用当前最优策略,可能错过更好的路线;如果一直乱试,累积奖励又上不去。常用的办法是ε-greedy,即以一个小概率随机探索,其余时间选择当前Q值最高的动作。SAC这类基于熵的算法更优雅,把探索作为目标的一部分写进优化公式里。
在线方法效果直观,但最现实的痛点是环境交互成本。真实机器人跑一步要好几秒,碰撞一次还要维修;而仿真环境下几分钟能跑上万步。这也是为什么大家在做真实控制前,一定先在Gazebo、MuJoCo这类仿真器里训练模型,训练好了再迁移到真实设备上。
3.2 离线强化学习:只有历史日志也能学
很多业务场景根本没有“随时在线试错”的许可。电商推荐系统不可能为了探索新策略就让用户刷到很多低质量内容;医院也不允许算法在真实诊疗里胡试。这种时候就需要离线强化学习(Offline RL),也叫批处理强化学习:只用一份已经收集好的固定数据集,不再与环境交互,直接学一个策略出来。
离线强化学习的最大难点叫分布外动作。简单说,数据里没有的(状态,动作)组合,训练时一旦网络随口说某个未知动作“会值很多分”,就会出现严重的Q值过估计。因为Q网络是用贝尔曼方程递推的,对没见过动作的估值没有真实反馈来纠正,越迭代越离谱。
IQL(Implicit Q-Learning)是一个很能说明问题的代表性算法。它避开了“需要读数据里没出现过的动作Q值”这个麻烦,改为从隐式方式估计状态价值,只关注数据集内部有样本支撑的部分,鼓励学到数据集所表达的行为,而不是盲目外推。CQL则从另一个角度下手,在Q学习的目标里加上一项对Q值期望的正则约束,压低那些没有数据支撑的动作的价值。两种思路都属于“保守估计”路线:宁可少赚,不赌未知。
3.3 基于模型强化学习:先把环境装进脑子里
基于模型方法的核心是先学一个世界模型(World Model),让Agent能“脑补”交互结果。Dreamer系列在这个方向上做得很典型:先通过历史经验学出下一帧状态预测模型,然后在虚拟环境里基于隐空间做想象推演来训练策略。这样大量策略更新都不需要跟真实环境通信,样本效率能提升一个数量级。
MuZero更是把这套思路推进到了棋类和Atari等场景,直接用神经网络做隐状态转移和价值预测,不依赖精确规则,也能拿到非常强的结果。这类算法的工程直觉是:既然真实环境交互贵,那就先建一个便宜的高保真模拟器,在模拟器里把试错成本降到接近零。
3.4 因果强化学习在改什么
再往深一层看,最近我比较关注的还有因果强化学习(Causal RL)。传统强化学习学到的很多关联关系其实只是数据上的相关性,而非因果性。比如AGV在某个画面里频繁撞到货架,画面中的某个像素颜色和碰撞事件高度相关,但真正导致碰撞的是机器人到货架的距离和速度。如果只学到像素相关,换一批货架颜色可能就失效了。
因果强化学习的核心机制,是把因果推断工具嵌入强化学习流程,先识别出“哪个变量直接决定系统反馈,哪个变量只是伴随现象”,再在环境模型或策略学习里保留因果结构。一个典型做法是:先结构学习得到因果图,抽出因果特征,再让策略只依赖这些特征做决策,丢掉那些虚假相关。这样的策略更容易跨环境泛化,也更容易被解释。目前这个方法还在发育期,但方向上我认为值得持续关注。
4. 用Python把PPO跑通一遍:从Gym到自定义环境
4.1 环境准备
不谈安装的教程都是耍流氓。先准备环境,我推荐直接用Miniconda建独立虚拟环境,避免包依赖冲突:
conda create -n rl python=3.10 -y conda activate rl pip install gymnasium[classic-control] stable-baselines3gymnasium是之前OpenAI Gym库的继任者,接口变化不大但维护更积极。stable-baselines3是SB3,封装了PPO、SAC、DQN等一堆成熟算法,接口统一,非常适合入门和做实验原型。如果你想自己写算法理解细节,可以用PyTorch从零撸一个简单PPO,但第一遍我建议先用SB3跑通流程,再回头读源码。
4.2 最小闭环:训练与推理
下面这段代码,十几行就能完成“定义环境、创建模型、训练、跑一次推理”的完整闭环:
import gymnasium as gym from stable_baselines3 import PPO # 创建倒立摆环境 env = gym.make("CartPole-v1") # 初始化PPO,使用两层MLP策略网络 model = PPO("MlpPolicy", env, verbose=1, learning_rate=3e-4, n_steps=2048) # 训练20万步 model.learn(total_timesteps=200_000) # 重置环境并让模型跑一轮 obs, info = env.reset() for _ in range(1000): action, _ = model.predict(obs, deterministic=True) obs, reward, terminated, truncated, info = env.step(action) env.render() if terminated or truncated: break这里有几个容易被忽略的细节:
learning_rate=3e-4是我跑过很多环境后觉得在PPO里最稳妥的起点,盲目调大很容训练发散。n_steps=2048是每次更新收集的步数,太小会让梯度噪声过大。deterministic=True表示推理时不再采样随机探索,直接输出当前策略的确定性动作,评估模型时更稳定。
4.3 从CartPole到Gazebo和多AGV路径规划
跑通CartPole之后,绝大多数人下一步会想碰真实场景。做机器人方向的人通常绕不开Gazebo,它是ROS生态里最常用的物理仿真器之一,可以加载机器人模型、传感器仿真、障碍物布局。要做Gazebo里的强化学习,最普遍的做法是写一个Python环境类,通过ROS订阅激光雷达和里程计话题得到状态,通过发布速度指令话题作为动作,当机器人收到碰撞传感器信号时返回负奖励并回合结束。
多AGV路径规划是这类场景里挺典型的问题。一个仓库里有若干辆AGV,从不同起点去往不同卸货点,容易互相堵路,甚至死锁。用强化学习来求解时,普通建模方式有两种:一种是把每个AGV当作独立智能体,各自决定下一步往哪走,这就成了多智能体强化学习问题;另一种是先把AGV的可能路径离散成有限集合,再让策略从中选路径,配合交通管制规则避免死锁。
根据我自己的经验,多AGV强化学习项目里最影响效果的,倒不是算法本身,而是仿真保真度和奖励设计。比如Gazebo里如果没开好碰撞检测,那AGV撞了货架也不报终止,奖励信号全乱,策略根本学不出来。所以我每次都先在Gazebo里手动远程操控AGV跑几遍,确认碰撞话题、里程计噪声、障碍物布局都真实了,再开始训练策略。
5. 实战中的奖励设计、超参数与任务建模
5.1 奖励设计:稀疏奖励、奖励塑形与奖励黑客
奖励函数是强化学习项目里影响最直接、也最容易被轻视的部分。第一个问题是稀疏奖励:如果AGV只在最终卸货那一刻拿到一个“+10”,其他所有步都是0,那你得试多少条路才偶然而一次正向信号?可能几万步都学不动。解决办法是奖励塑形,给中间过渡提供密度更高的反馈,比如每靠近目标一步给一个小正分,每碰撞一次给一个负分,让对方策略能一步步摸到目标。
但奖励塑形会引发新的问题,就是奖励黑客。你设计的靠近奖励可能让AGV绕着目标转圈不冲进去,只为了每步都拿靠近奖励;也可能让它在离目标很近但撞墙的位置卡住,因为靠近奖励大于碰撞处罚。我见过最典型的翻车案例:给机械臂设计了一个“末端接近目标减距离误差”的奖励,结果机械臂学会把目标物体推远来减少误差。所以要设一些容易判定的全局约束,比如步数上限、距离阈值强制终止,并对异常行为做合法性校验。
5.2 需要盯住的超参数
强化学习超参数很多,但真正需要手工调的核心参数就那么几个:
| 参数 | 含义 | 常见起点 | 调高效果 | 调低效果 |
|---|---|---|---|---|
| 学习率 | 网络权重更新步长 | 3e-4 | 学习快,容易发散 | 稳定,但收敛慢 |
| 折扣因子γ | 未来奖励的重要性 | 0.99 | 更看重远期收益 | 更看重眼前收益 |
| 熵系数/熵权重 | 策略随机性惩罚 | SAC默认自动调 | 探索更多 | 接近确定性策略 |
| 经验回放容量 | 旧样本保留量 | 100_000 | 多样性高,占内存 | 样本旧信息丢弃快 |
| 梯度裁剪阈值 | 防止梯度过大 | 0.5或1.0 | 容忍大更新 | 更保守 |
我见过太多人一上来就试图把γ调到0.999,结果策略过分关注远期,短视任务怎么都学不好。先保持0.99起步,观察回报曲线是否平稳上涨,再根据需求更变。
5.3 训练不稳时的排查链
训练过程中回报曲线震荡是一个再普通不过的事。按照我自己的排查习惯,顺序大概是:
- 先确认环境本身没问题:手动采样动作,观察奖励是否合理、回合是否正常结束,这一步排掉80%的“学不动”问题。
- 看训练时的平均回报曲线,而不是单回合回报。单回合方差极大,容易让人误判。
- 检查探索是否充足:如果策略过早收敛到“一直输出同一个动作”,往往是熵塌缩了,需要提高熵系数或者提高学习率。
- 检查Q值或Critic loss:如果Q值一路飙升,但实际回报纹丝不动,基本就是过估计,需要降低学习率、调大回放buffer,或者换成更保守的目标更新方式。
- 最后检查环境随机种子是否固定,不确定的随机环境会直接导致复现困难。
5.4 我的调试顺序
跑强化学习项目以来,我逐渐形成一套固定节奏。第一步,先把环境当成随机智能体跑几百步,只看数据流是否通、奖励是否合理。第二步,用PPO或SAC跑一个小batch实验,比如10万步,观察那条奖励曲线能不能在一个小时内有明显上升趋势。第三步,如果曲线没动静,我不去改网络结构,先改奖励函数和状态表征,这两项对训练效果的影响远大于网络层数。第四步,等基本能学通后,再去做超参数小范围网格搜索,一次只改一个变量。这套流程看起来老套,但对比“遇到问题就加网络”的野路子,成功率提升非常大。
6. 强化学习目前的三个瓶颈,以及一些破局思路
6.1 绕不开的样本效率
深度强化学习算法的最大瓶颈还是样本效率。一个标准的Atari游戏需要几百万帧才能达到人类水平,真实机器人根本耗不起这个交互量,这也是强化学习在工业里主要活在仿真场景的原因。破局思路目前有四条线:一是基于模型方法,用学出来的世界模型自动补样本;二是离线强化学习,把历史日志数据用起来;三是仿真到现实迁移,把仿真里学到的策略做域随机化,再迁移到真实设备;四是多智能体并行仿真,同时开几十个Gazebo实例加速采样。这几个方向不是互斥的,实际项目里经常组合使用。
6.2 奖励从哪来:人写还是学
奖励函数是很多项目推不动的深层原因。尤其像“路径规划得好不好”“驾驶风格冷不冷”这类评价,很难写成标量函数。近几年出现了逆强化学习(IRL)和偏好学习,从专家示范数据里反推奖励,或者让人类给成对轨迹打分,再由算法拟合一个人的偏好模型。DeepMind在多机器人控制里还用过一个思路,先学一个辅助价值函数来评估行为规范,再把这个函数作为强化学习信号的一部分。从工程角度讲,与其绞尽脑汁手造奖励,不如强化学习环境下同时采集导师反馈,既高效又不容易被奖励黑客钻空子。
6.3 因果、世界模型和离线数据怎么走到一起
把现阶段几个热点放在一起看,其实有一个共同趋势:都在想办法让强化学习不那么“白手起家”。因果强化学习给模型注入因果结构,让策略基于真正起作用的变量做决策,提高泛化能力;基于模型的强化学习给策略一个可以反复演练的“沙盘”;离线强化学习让先前积累的数据具备再利用价值。三者在生产实践里可以配合成一套管线:先用离线数据学习一个可信的世界模型和保守策略,再用因果工具剔除虚假相关特征,最后在仿真沙盘里微调策略,再到现实环境小成本验证。这基本就是我从科研项目转向工业落地时,最后沉淀下来的主流做法。
6.4 入门资料怎么选,避免只刷代码
最后分享一点学习路线方面的体会。很多人以为强化学习很难,是数学劝退,其实更准确地说,是“直觉门槛”太高。Q值、TD误差、策略梯度这些概念如果不结合具体环境去体会,看公式会非常吃力。我推荐两条路径并行:一边读Sutton的经典红宝书《Reinforcement Learning: An Introduction》,这本书虽然老,但对基本概念的直觉讲得最好;一边在Gymnasium里跑SB3的现成实现,把DQN、PPO、SAC都先当成黑盒玩一遍,再回去读论文里的公式推导,会顺畅得多。市面上也有一些很适合中文读者的开源书籍,比如“动手学强化学习”,我常把它当作新人团队的百日入门手册。
我自己的习惯是“必须自己重写一遍核心算法”。哪怕写出来的版本比SB3慢十倍,这个过程里能学到的东西,远比调包跑几千步要多。等你能从零写出一个能让CartPole收敛的PPO,再去看MuZero、Dreamer、IQL这些进阶方向,会发现整个强化学习地图已经在脑子里成形了。剩下的,无非是拿着地图,去你自己的场景里踩地平坑。