强化学习算法的设计美学——从 Bellman 到 PPO 的直觉路径
强化学习算法的设计美学——从 Bellman 到 PPO 的直觉路径
前面两篇我们聊了损失函数和优化器的设计哲学。但有一个领域的损失函数和优化器设计,比监督学习更"绕"——强化学习。
在监督学习中,你的标签是上帝给的,错了就是错了。但在强化学习中,你只有一个延迟的、嘈杂的、稀疏的标量奖励信号。更麻烦的是:你在用当前策略收集的数据来更新这个策略本身,更新完你又拿新策略去跑数据——你的训练数据一直在变。
这种"自己给自己出题,自己又去解题"的循环,使得 RL 的算法设计比监督学习多了一层曲折。这篇博客会沿着 RL 的算法演进路径,拆解每个关键设计背后的直觉——不是为了列公式,而是为了理解为什么一个问题被反复用不同方式解决。
1. 核心难题:状态价值和动作价值
先确立两个基本概念。
在 RL 中,智能体需要回答的根本问题是:在某个状态下,做哪个动作最好?
但"好"的定义是模糊的——好的动作会带来即时奖励,也可能带来长期回报。于是我们定义了两种价值函数:
- 状态价值 $V(s)$:从这个状态出发,按当前策略 $ \pi $,未来期望总回报是多少
- 动作价值 $Q(s,a)$:在这个状态执行动作 $a$,之后按当前策略 $ \pi $,未来期望总回报是多少
它们通过 Bellman 方程关联:
$$
V(s) = \max_a Q(s,a)
$$
或者更标准地,通过时序一致性:
$$
Q(s,a) = r(s,a) + \gamma \mathbb{E}_{s’ \sim P(\cdot | s,a)} [V(s’)]
$$
这句话直白地说就是:一个动作的价值 = 立即回报 + 折损后的后续状态价值。
这个式子看似简单,但它蕴含了整个 RL 算法设计的核心 tension:你教的(价值估计)和你要学的(策略)是同一个东西的回声——你用当前的估计去更新自己,形成自我指涉的循环。后面所有的算法,本质上都是不同方式来处理这个循环的稳定性问题。
2. Q-learning:用一个近似去逼近另一个近似
$$
Q(s,a) \leftarrow Q(s,a) + \alpha [r + \gamma \max_{a’} Q(s’, a’) - Q(s,a)]
$$
Q-learning 的核心思想是:用 TD target ($r + \gamma \max_{a’} Q(s’,a’)$) 作为"伪标签"去更新 $Q(s,a)$。TD target 本身也是 $Q$ 函数的估计,所以这个更新是在用一个近似去逼近另一个近似。
这带来两个问题:
1. 过度估计(Overestimation Bias)
$\max_{a’} Q(s’,a’)$ 天然会高估——因为如果 $Q$ 对每个动作的估计有随机误差,取最大值会选中误差为正的那个。误差叠加,Q 值越学越虚高。
2. Bootstrapping 的误差累积
每一步更新都依赖于下一步的估计,误差会沿着时间步传导和放大。在复杂环境中,这种误差传播可以导致价值估计的级联偏离。
Double Q-learning:把选择器和评估器分开
解决方案出奇简洁:用两个独立的 Q 网络,一个负责选动作,另一个负责估价值。
$$
Q_1(s,a) \leftarrow Q_1(s,a) + \alpha [r + \gamma Q_2(s’, \arg\max_{a’} Q_1(s’, a’)) - Q_1(s,a)]
$$
选动作用 $Q_1$,估值用 $Q_2$。误差被正负抵消的概率大于被叠加放大的概率,有效缓解了高估问题。这就像两个裁判:一个说你该打这个球,另一个说这球值多少分——如果同一个裁判又选又评,他很容易给自己的选择打高分。
3. DQN:当深度网络遇上 Q-learning
2013 年,Mnih 等人把 Q-learning 搬到深度网络上(DQN),在 Atari 游戏上取得了突破。但光替换网络架构远远不够,他们还加了两项关键创新。
3.1 经验回放(Experience Replay)
打破数据之间的时序相关性。监督学习假设数据是 i.i.d. 的,但 RL 的 $s_{t+1}$ 直接依赖于 $s_t, a_t$——前后状态强相关。用这样的时序数据做 SGD,梯度方差极大,网络很难收敛。
经验回放的解决方案:把经历存起来,随机采样训练。每个 transition 来自不同的时间步、不同的 episode,相关性被打破。同时,一条经验可以复用多次,提升了样本效率。
3.2 Target Network
DQN 面临的同一个问题,只是换了形式。如果 $Q$ 网络在时刻 $t$ 和目标值 $r + \gamma \max Q(s’, a’)$ 都用同一个网络计算,这个网络在更新自己,而目标也在跟着变——就像在移动的靶子上射箭。
DQN 的做法是:维持一个冻结的 target network $Q^-$,每隔 $C$ 步才复制一次主网络的参数。
$$
y_t = r_t + \gamma \max_{a’} Q^-(s_{t+1}, a’)
$$
这样 target 在一个固定周期内不变,避免了"自己追自己尾巴"的情况。
这两个设计的直觉可以简化为:
- 经验回放 → 别让数据太相关,否则梯度像喝了假酒
- Target Network → 别让目标跑太快,否则你永远追不上
4. Policy Gradient:直接学策略不香吗?
Q-learning 学派在学价值函数,然后根据价值选动作。那能不能直接学一个策略 $\pi_\theta(a|s)$,然后用梯度上升去最大化期望回报?
这就是 Policy Gradient 的思路,核心是 Policy Gradient Theorem:
$$
\nabla J(\theta) = \mathbb{E}{\tau \sim \pi\theta} \left[ \sum_t \nabla_\theta \log \pi_\theta(a_t|s_t) \cdot G_t \right]
$$
直白翻译:收集一组交互轨迹,如果一个 trajectory 的总回报 $G_t$ 高,就增加这条轨迹上每个动作的概率;如果回报低,就降低概率。
但这有一个问题:方差极大。 同一个策略跑两次,第一次可能不小心通关了,第二次可能开局就死。两条轨迹的 $G_t$ 差天差地别,梯度方向会受到"运气好"或"运气差"的强烈影响。
于是有了 REINFORCE with baseline:减掉一个基线 $b(s)$ 来降低方差。
$$
\nabla J(\theta) = \mathbb{E} \left[ \sum_t \nabla_\theta \log \pi_\theta(a_t|s_t) \cdot (G_t - b(s_t)) \right]
$$
但这样做还不够——$G_t$ 本身的方差仍然很大。
5. Actor-Critic:两种思路的结合
如果既学价值函数,又学策略呢?
Actor-Critic 的做法是:Actor 负责学策略(做什么),Critic 负责学价值函数(做得好不好)。 Critic 的输出充当一个更稳定的"打分"信号,替代掉 $G_t$。
$$
\nabla J(\theta) = \mathbb{E} \left[ \nabla_\theta \log \pi_\theta(a|s) \cdot \delta \right]
$$
其中 $\delta = r + \gamma V(s’) - V(s)$ 是 TD-error——衡量当前 Critic 认为这个动作比预期好还是差。
- $\delta > 0$:这个动作比 Critic 预期好 → 提升它的概率
- $\delta < 0$:这个动作比预期差 → 降低它的概率
Critic 会不断学习,让自己对 $V(s)$ 的估计越来越准;Actor 则根据越来越准的 Critic 信号调整策略。两者互相促进,形成了 RL 中一个经典的共生结构。
但这种共生也有风险:Critic 和 Actor 是彼此依赖的,如果 Critic 学偏了,Actor 就会往错误方向走,然后收集到歪数据再训练 Critic——恶化循环。 几乎所有高级算法都在处理这个问题。
6. PPO:稳定压倒一切
从 REINFORCE 到 A2C/A3C,Policy Gradient 方法已经能在很多任务上工作了,但有一个核心痛点:样本效率低,而且一次更新太大就会崩。
所谓"一次更新太大",指的是 $\pi_\theta$ 一步偏离 $\pi_{\theta_{old}}$ 太多。一旦走歪,新策略收集的数据就会和旧策略偏差太大,Critic 的那个假设就失效了——你不再能可靠地用旧数据来更新新策略。
TRPO 的解决思路
TRPO(Trust Region Policy Optimization)的做法是:限制每次更新的步长,保证新旧策略的 KL 散度不超过 $\delta$。
$$
\max_\theta \mathbb{E} \left[ \frac{\pi_\theta(a|s)}{\pi_{\theta_{old}}(a|s)} A(s,a) \right] \quad \text{s.t. } D_{KL}(\pi_{\theta_{old}} \parallel \pi_\theta) \leq \delta
$$
它把优化问题变成了一个带约束的优化,然后用共轭梯度等方法求解。理论上漂亮,但实现复杂、计算量大。
PPO 的简化:用 Clip 代替约束
PPO 的想法更直接粗暴:如果不限制步长,那就限制收益。 它不对更新幅度做约束,而是对目标函数做了裁剪:
$$
L^{CLIP}(\theta) = \mathbb{E} \left[ \min\left( r_t(\theta) \hat{A}_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) \hat{A}_t \right) \right]
$$
其中 $r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)}$ 是新旧策略的比值。
直觉是这样的:
- 如果 $\hat{A}_t > 0$(这个动作好):$r_t(\theta)$ 希望变大(提升这个动作的概率),但 clip 限制了它最大涨到 $1+\epsilon$——步子不要迈太大
- 如果 $\hat{A}_t < 0$(这个动作不好):$r_t(\theta)$ 希望变小,但 clip 限制了它最小跌到 $1-\epsilon$
PPO 的 “clip” 是一个极有工程美感的操作。TRPO 需要一个复杂的二次规划求解器来处理约束;PPO 只用了一行 torch.clamp 就达到类似效果。它没有 TRPO 的严格保证,但实践中往往更好用。
你几乎可以这样说:PPO 之所以成功,不是因为它在理论上比 TRPO 更优,而是因为它把 TRPO 的"复杂约束"变成了一个可以一行代码实现的"粗糙但有效"的裁剪。
PPO 在今天的主流 RL 库中几乎是标配。从 Isaac Lab 中的四足机器人训练,到 LLM 的 RLHF 微调,PPO 的身影无处不在。
7. 算法演进的底层脉络
把几大算法串起来,你会看到一条清晰的设计进化路径:
| 阶段 | 代表算法 | 核心创新 | 解决了什么 |
|---|---|---|---|
| 基础理论 | Q-learning | Bellman 更新 | 让价值函数自洽 |
| 加上深度 | DQN | 经验回放 + Target Network | 打破相关性 + 稳定目标 |
| 直接学策略 | REINFORCE | Policy Gradient Theorem | 不用学 V 也能优化 |
| 结合两者 | A2C / A3C | Actor-Critic | 用 V 降方差、稳梯度 |
| 稳定训练 | TRPO / PPO | Trust Region / Clip | 防止一次更新崩掉 |
这条路径的内在动力是:RL 的训练稳定性问题比监督学习严重得多。 在监督学习中,标签是固定的,数据分布也不是你改参数就变的。但在 RL 中,你更新一次策略,整个数据分布就变了——下一批数据的 “难易程度”、"反馈信号"完全取决于你刚刚更新的策略。
所以每一代算法都在努力做同一件事:让这个"自指"的循环稳定下来。
从 DQN 的 target network(隔一段时间冻结目标),到 TRPO 的约束优化(限制策略变化幅度),到 PPO 的 clip(用简单粗暴的方式限制变化),再到 SAC 的熵正则化(鼓励探索来避免策略坍塌)——它们本质上是同一个焦虑的多种解法。
8. 一个贯穿三篇的 meta 视角
最后,我想用一个小小的 meta 视角把这三篇串起来。
损失函数、优化器、RL 算法——这三个主题看似独立,但它们背后是同一个问题:
怎么让一个数学上的优化过程,在现实生活中稳定、高效地运行?
- 损失函数定义了"好"的标准
- 优化器定义了"怎么走"的方案
- RL 算法则在更高维度上定义了"数据从哪来、目标往哪去"
你会发现,高级的算法设计者都有一个共同特质:他们知道什么时候该加约束,什么时候该放松约束。
MSE 到 Huber 是加了"对大误差的容忍边界",Adam 的 bias correction 是加了"初始阶段的校正",PPO 的 clip 是加了"动作概率比值的边界"——看似不同的操作,本质上都是在划定一个安全的信任区间,在这个区间内信任梯度信号,超出区间则谨慎对待。
这就是所有优化算法背后那个最朴素的设计直觉:相信梯度,但别全信。
总结
- Bellman 方程奠定了价值学习的基石,包办了整个 RL 的递归结构
- Q-learning 用 TD target 做自举更新,DQN 用经验回放和 target network 解决了深度化的两大难题
- Policy Gradient 方法跳过了价值函数直接优化策略,Actor-Critic 把它们结合起来
- TRPO/PPO 的核心贡献是解决"更新太大就崩"的问题,PPO 用 clip 以极简方式达成目标
- 所有 RL 算法的底层焦虑都是稳定性——因为数据分布会随策略变化,形成了自指循环
从第一篇的损失函数、到第二篇的优化器、再到这一篇的 RL 算法,这三篇文章共同呈现了一个渐变:越复杂的问题,你的"优化工具"就需要越多的约束和机制来保持稳定。 但这个思路是通用的——理解每个约束和机制为什么存在,比记住公式本身重要得多。




