强化学习

PPO算法与公式推导

PPO算法与公式推导

本节内容总览

模块核心问题你需要先抓住什么
PPO 要解决什么为什么不能直接用原始策略梯度原始策略梯度能学,但方差大、效率低、更新不稳定
策略梯度怎么来PPO 的根基是什么先有“最大化期望回报”的目标,再推到策略梯度公式
baseline 为什么要加为什么奖励要减去一个基线为了降方差,让训练更稳定
on-policy / off-policy 是什么数据为什么不能随便复用因为策略一变,旧数据分布就和新策略不一致
importance sampling 为什么有用为什么可以“狸猫换太子”用概率比值修正分布差异,让旧数据还能辅助新策略训练
PPO 的核心创新PPO 为什么稳定又好用用“概率比值 + clip 截断”限制策略更新不要太猛

一句话理解 PPO

PPO(Proximal Policy Optimization,近端策略优化)可以看成是:

在策略梯度的基础上,允许我们把一批采样数据多用几次,但同时强行限制新策略不要离旧策略太远。

所以 PPO 的关键词有两个:

  • 复用数据
  • 限制更新幅度

一、总览

  1. 强化学习的目标是让策略获得更高的期望累计奖励。
  2. 为了优化这个目标,我们先得到策略梯度公式。
  3. 直接用原始策略梯度,方差太大,所以引入 baseline 来稳定训练。
  4. 但是原始 on-policy 方法每更新一次就得重新采样,样本效率低。
  5. 为了让旧数据也能继续发挥作用,引入 importance sampling。
  6. 但如果新旧策略差太远,重要性权重会爆炸,于是要限制新旧策略差异。
  7. PPO 就是在这个基础上,用 clip 机制做一个简单、稳定、易实现的约束。

如果把这条线想通,PPO 的公式就不会显得突兀。

二、PPO 前的基本问题:我们到底在优化什么

1. 目标不是“每一步都对”,而是“整局回报更高”

设一条完整轨迹为:

τ={s1,a1,s2,a2,,sT,aT}\tau = \{s_1, a_1, s_2, a_2, \ldots, s_T, a_T\}

其中:

  • sts_t 是第 tt 步状态
  • ata_t 是第 tt 步动作
  • rtr_t 是第 tt 步奖励

一条轨迹的总回报可以写成:

R(τ)=trtR(\tau) = \sum_t r_t

更一般地,也常写成折扣回报:

Gt=rt+γrt+1+γ2rt+2+G_t = r_t + \gamma r_{t+1} + \gamma^2 r_{t+2} + \cdots

策略网络记作 πθ(as)\pi_\theta(a \mid s),表示在状态 ss 下选择动作 aa 的概率。
我们的目标就是让参数 θ\theta 变得更好,使得策略产生的轨迹平均回报更高:

J(θ)=Eτπθ[R(τ)]J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta}[R(\tau)]

一句话概括它的核心思想:通过调整策略参数 θ\theta,让智能体(Agent)在与环境交互的整个过程中,获得的“平均总回报”最大化。

1. 拆解公式中的每一个符号

把公式分成左、中、右三部分来看:

J(θ)=Eτπθ[R(τ)]J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta}[R(\tau)]

符号概念通俗解释
J(θ)J(\theta)目标函数 (Objective Function)衡量当前策略参数 θ\theta 好坏的指标。我们的终极任务就是找到一组 θ\theta,让 J(θ)J(\theta) 的值尽可能大。
τ\tau (Tau)轨迹 (Trajectory)智能体从头到尾完成一次任务(或玩完一把游戏)的完整流水账。它是一个序列,包含了一路上所有的状态和动作:τ=(s0,a0,s1,a1,,sT)\tau = (s_0, a_0, s_1, a_1, \dots, s_T)
πθ\pi_\theta参数化的策略 (Policy)智能体的“大脑”(通常是一个神经网络),θ\theta 是网络的权重。它负责输入当前状态 ss,输出动作 aa 的概率分布。
τπθ\tau \sim \pi_\theta采样分布 (Sampling)读作“τ\tau 服从 πθ\pi_\theta 后的分布”。意思是:这条流水账 τ\tau,是智能体拿着当前策略 πθ\pi_\theta 去跟环境实际互动玩出来的。
R(τ)R(\tau)轨迹总回报 (Return)这一趟跑下来,智能体拿到的总分。即把一路上每一步获得的奖励(Reward)加起来:R(τ)=t=0TrtR(\tau) = \sum_{t=0}^T r_t(有时会乘上折扣因子 γ\gamma)。
E...[]\mathbb{E}_{...}[\cdot]数学期望 (Expectation)概率论中的加权平均值

2. 通俗的直觉理解(举个例子)

如果把强化学习比作学开车

  • θ\theta 是司机的“大脑神经元连接权重”(决定了司机的驾驶技术和习惯)。

  • πθ\pi_\theta 是司机面对不同路况(状态 ss)时,做出踩油门、打方向盘(动作 aa)的反应倾向

  • τ\tau 是司机开完一整趟行程的行车记录仪录像

  • R(τ)R(\tau) 是这一趟开下来,安全、省油、速度快的综合评分

把它们组合起来,公式的意思就是:

“按照现在的驾驶习惯(θ\theta),让这个司机去开无数次车,所有行程的平均得分是多少。”

3. 为什么公式里必须要加“期望 E\mathbb{E}”?

为什么不直接最大化某一次玩游戏的分数 R(τ)R(\tau),而要最大化期望?

因为强化学习的环境和策略通常充满随机性(不确定性)

  1. 策略的随机性:在同一个十字路口(状态 ss),策略可能以 70% 的概率建议左转,30% 的概率建议右转。

  2. 环境的随机性:就算你决定左转,地面也可能因为突降暴雨结冰,导致车子滑向意想不到的方向(状态转移具有随机性)。

由于这些随机性存在,哪怕参数 θ\theta 完全不变,司机去开十趟车,每趟的轨迹 τ\tau 和最终得分 R(τ)R(\tau) 也会不一样。 所以,我们不能当“赌徒”去赌某一次单次最高分,而是要看统计意义上的平均表现(期望值)。只有平均分提高了,才说明策略 θ\theta 真的变优秀了。

三、策略梯度:PPO 的根

1. 为什么要用策略梯度

在监督学习里,我们知道“正确标签”,可以直接定义损失函数。
但在强化学习里,我们没有每一步的标准答案,只知道整局玩完以后结果好不好。

所以我们不能直接说:

  • 这个动作绝对对
  • 那个动作绝对错

我们只能说:

  • 产生高回报的动作序列,应该更容易再次出现
  • 产生低回报的动作序列,应该更不容易再次出现

2. 策略梯度的核心公式

通过==对数求导技巧==,可以把目标函数的梯度写成:

θJ(θ)=Eτπθ[θlogπθ(τ)R(τ)]\nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta}\left[\nabla_\theta \log \pi_\theta(\tau)\, R(\tau)\right]

这是策略梯度最核心的形式。

==把一个函数的梯度 θf(θ)\nabla_\theta f(\theta),转换成了函数本身和它对数梯度的乘积。== 对数求导技巧对强化学习核心公式的处理

直观解释:

  • 如果一条轨迹 R(τ)R(\tau) 很大,就增强这条轨迹对应动作的概率
  • 如果一条轨迹 R(τ)R(\tau) 很小,就削弱这条轨迹对应动作的概率

再拆到每一步,常见写法会变成:

θJ(θ)=E[tθlogπθ(atst)R(τ)]\nabla_\theta J(\theta) = \mathbb{E}\left[\sum_t \nabla_\theta \log \pi_\theta(a_t \mid s_t)\, R(\tau)\right]

课程里先从轨迹级公式讲起,这是合理的入门路径。

3. 对数技巧在这里做了什么

dlogf(x)dx=1f(x)df(x)dx\frac{d \log f(x)}{dx} = \frac{1}{f(x)} \frac{df(x)}{dx}

它的作用不是为了炫技巧,而是为了把难算的 πθ\nabla \pi_\theta 变成更好算的 logπθ\nabla \log \pi_\theta

这是策略梯度推导里最关键的一步变形。

四、轨迹、采样和期望近似

理论上我们希望对所有可能轨迹求期望,但这基本不现实。
实际做法是:

  1. 用当前策略去环境里跑很多局
  2. 收集很多条轨迹 τ1,τ2,,τN\tau_1, \tau_2, \ldots, \tau_N
  3. 用样本均值近似期望

于是策略梯度可以用蒙特卡洛方式近似:

θJ(θ)1Ni[tθlogπθ(ai,tsi,t)R(τi)]\nabla_\theta J(\theta) \approx \frac{1}{N} \sum_i \left[\sum_t \nabla_\theta \log \pi_\theta(a_{i,t} \mid s_{i,t})\, R(\tau_i)\right]

这就是“与环境交互得到数据”的本质。 蒙特卡洛近似方法

也就是说,强化学习的数据不是预先给好的,而是策略自己跑出来的。

五、原始策略梯度为什么不好用

虽然原始策略梯度理论上能工作,但它有几个明显问题。

1. 方差大

同一个策略,多跑几次,得到的轨迹和奖励可能差很多。
这会让梯度估计抖得很厉害,训练不稳定。

2. 奖励信号太粗

最原始的写法里,一整条轨迹的总奖励 R(τ)R(\tau) 会乘到轨迹里所有动作上。
这很粗糙,因为:

  • 不是每一步都同等重要
  • 有些动作其实贡献大,有些贡献小

3. 样本效率低

每次参数更新后,策略就变了。
如果坚持严格的 on-policy 思路,旧数据就不太能直接再用,必须重新采样。

这会导致:

  • 跑环境花很多时间
  • 真正更新网络的效率不高

六、baseline:先把梯度抖动降下来

1. baseline 的基本想法

课程里给出的 baseline 形式是:

R(τ)bR(\tau) - b

其中 bb 可以取一批样本回报的平均值。

于是梯度近似变成:

θJ(θ)1Ni[tθlogπθ(ai,tsi,t)(R(τi)b)]\nabla_\theta J(\theta) \approx \frac{1}{N} \sum_i \left[\sum_t \nabla_\theta \log \pi_\theta(a_{i,t} \mid s_{i,t})\, (R(\tau_i) - b)\right]

2. 为什么这有用

因为它把“绝对奖励”变成了“相对平均水平的好坏”。

直观上:

  • 比平均水平更好的轨迹,Rb>0R - b > 0,就增强
  • 比平均水平更差的轨迹,Rb<0R - b < 0,就削弱

这样做的好处是:

  • ==奖励更接近零中心==
  • ==更新方向更清晰==
  • ==方差更小,训练更稳定==

3. 更准确的补充:baseline 进一步会发展成 advantage

课程里先讲“减均值 baseline”非常适合入门。
但更准确地说,==现代策略梯度和 PPO 里常用的是 advantage:==

At=GtV(st)A_t = G_t - V(s_t)

其中:

  • G_t 是从第 t 步开始的回报
  • V(s_t) 是状态价值函数,表示“站在这个状态上,平均来说能拿多少回报”

这比简单减均值更细,因为它是“针对当前状态”的基线,不是“整批样本共用一个均值”。

所以你可以把理解顺序记成:

baseline 是大思路,advantage 是更精细、更常用的 baseline。

七、On-policy 与 Off-policy

1. On-policy 是什么

on-policy 的核心意思是:

用当前策略采样的数据,来更新当前策略。

比如:

  • 当前策略是 pi_theta
  • 它去环境里跑出一批数据
  • 再用这批数据更新 theta

它的优点是“理论上比较干净”,缺点是“每次都得重新采样”。

2. Off-policy 是什么

off-policy 的核心意思是:

可以用别的策略生成的数据,来训练当前策略。

比如:

  • 旧策略生成数据
  • 行为策略生成数据
  • 回放缓冲区里的历史数据

它的优点是样本效率高,缺点是分布不一致会带来偏差或高方差问题。

3. “狸猫换太子”比喻

这个比喻讲得很形象:

  • 真正想优化的是当前策略
  • 但采样很贵
  • 所以先让“替代策略”去收集数据
  • 再想办法把这批数据修正后给当前策略用

这正好引出了下一步的重要性采样。

4. 一个重要补充:标准 PPO 更准确地说是“近端 on-policy”

这里需要补一个很关键的概念校正:

用 off-policy 的视角来帮助理解“数据复用”,这对初学者是有帮助的。
但从更常见的专业表述来说,标准 PPO 通常不被归为典型 off-policy 算法

更准确的说法是:

  • PPO 主要还是使用“当前旧策略刚采样出来的一批数据”
  • 然后在这批数据上做多个 epoch 的更新
  • 因此它常被称为 on-policynear-on-policy

也就是说:

  • 它确实复用了同一批数据
  • 但通常不会像 DQN、SAC 那样长期复用很旧的数据

这个区别你现在先有印象就够了,后面学 DQN、DDPG、SAC 时会更清楚。

八、Importance Sampling:为什么旧数据还能拿来修正

1. 核心想法

如果我们真正想计算的是:

ExP[f(x)]\mathbb{E}_{x \sim P}[f(x)]

但手里采样到的数据来自另一个分布 QQ,那可以写成:

ExP[f(x)]=ExQ[P(x)Q(x)f(x)]\mathbb{E}_{x \sim P}[f(x)] = \mathbb{E}_{x \sim Q}\left[\frac{P(x)}{Q(x)} f(x)\right]

其中:

w(x)=P(x)Q(x)w(x) = \frac{P(x)}{Q(x)}

叫做重要性权重。

2. 放到策略学习里怎么理解

在策略优化里:

  • QQ 可以理解成旧策略产生数据的分布
  • PP 可以理解成新策略对应的分布

于是我们就能用“旧策略采到的数据”,去近似“新策略下的目标”。

3. 为什么新旧策略不能差太远

因为如果 PQ\frac{P}{Q} 这个比值特别大或特别小,训练会很不稳定。

直观上:

  • 如果旧策略几乎不会做某动作
  • 新策略却特别想做这个动作
  • 那么概率比值就可能爆炸

这会带来:

  • 梯度方差很大
  • 更新不稳定
  • 训练容易崩

所以重要性采样虽然能复用数据,但有一个前提:

新旧策略必须足够接近。

九、PPO 的真正核心:限制新旧策略别差太远

PPO 的名字里,Proximal 就是“近端、不要离太远”的意思。

1. 先定义概率比值

PPO 里最关键的量是:

rt(θ)=πθ(atst)πθold(atst)r_t(\theta) = \frac{\pi_\theta(a_t \mid s_t)}{\pi_{\theta_{\text{old}}}(a_t \mid s_t)}

它表示:

  • 在同一个状态动作对上
  • 新策略相对旧策略
  • 把这个动作概率放大了多少倍

理解这个比值很重要:

  • rt=1r_t = 1:新旧策略对这个动作看法一样
  • rt>1r_t > 1:新策略更偏爱这个动作
  • rt<1r_t < 1:新策略更不偏爱这个动作

2. PPO 为什么不能只最大化 rtAtr_t A_t

如果只写:

rt(θ)Atr_t(\theta) A_t

那模型可能会为了快速增大奖励,疯狂把某些动作概率拉高或拉低。
这样虽然短期看目标在变好,但策略会一下子改得太猛,训练容易不稳定。

3. clip 的核心形式

PPO 最经典的目标函数是:

LCLIP(θ)=Et[min(rt(θ)At,clip(rt(θ),1ϵ,1+ϵ)At)]L^{\text{CLIP}}(\theta) = \mathbb{E}_t \left[ \min\left( r_t(\theta) A_t,\, \operatorname{clip}(r_t(\theta), 1 - \epsilon, 1 + \epsilon) A_t \right) \right]

其中:

  • AtA_t 是 advantage
  • ϵ\epsilon 是裁剪范围,常见如 0.20.2

4. clip 到底在做什么

它的作用可以理解成:

你可以改,但别改得太离谱。

如果:

  • 新策略只是小幅调整,PPO 允许你继续优化
  • 新策略把概率改得太狠,PPO 就把这次“过猛更新”截断掉

所以 clip 本质上是在防止:

  • 好动作被过度放大
  • 坏动作被过度压低
  • 一次更新走太远

5. 为什么公式里要取 min

这是很多初学者第一次看到 PPO 时最困惑的地方。

可以这样理解:

  • At>0A_t > 0 时,我们希望增加这个动作概率,但不能增加得太夸张
  • At<0A_t < 0 时,我们希望减少这个动作概率,但也不能一下减得太狠

min(...) 的作用就是在“原始目标”和“裁剪后的目标”之间取更保守的那个。
所以 PPO 常被说成是一种 pessimistic surrogate objective,也就是“偏保守的替代目标”。

十、从课程视角重建 PPO 的完整逻辑

如果完全按这节课的讲法来整理,PPO 的逻辑可以这样复述:

1. 第一步:定义目标

我们希望策略获得更高的期望累计奖励:

θ=argmaxθEτpθ(τ)[trt]\theta^* = \arg\max_\theta \mathbb{E}_{\tau \sim p_\theta(\tau)} \left[\sum_t r_t\right]

2. 第二步:推导策略梯度

用对数求导技巧,把难求的梯度变成可采样估计的形式:

θJ(θ)=E[θlogπθ(τ)R(τ)]\nabla_\theta J(\theta) = \mathbb{E}\left[\nabla_\theta \log \pi_\theta(\tau)\, R(\tau)\right]

3. 第三步:引入 baseline

把“绝对奖励”改成“相对基线的奖励”,降低方差。

4. 第四步:发现 on-policy 太慢

每更新一次就要重新采样,环境交互成本高。

5. 第五步:引入 importance sampling

让旧策略产生的数据也能服务于新策略更新。

6. 第六步:发现重要性权重会失控

如果新旧策略差太远,训练会爆炸。

7. 第七步:引入 clip 限制

把概率比值限制在一个合理范围内,让每一步更新更稳。

这就是 PPO 的核心思路闭环。

十一、PPO 的实际训练流程

你可以把 PPO 的训练过程记成下面这几步:

  1. 用旧策略 πold\pi_{\text{old}} 与环境交互,收集一批轨迹数据。
  2. 计算每一步的回报 GtG_t,以及更常用的 advantage AtA_t
  3. 计算概率比值:
rt(θ)=πθ(atst)πold(atst)r_t(\theta) = \frac{\pi_\theta(a_t \mid s_t)}{\pi_{\text{old}}(a_t \mid s_t)}
  1. 用 clip 目标函数更新当前策略若干轮。
  2. 更新完成后,把当前策略拷贝给 πold\pi_{\text{old}}
  3. 再次与环境交互,进入下一轮。

你会发现 PPO 的节奏是:

采一批反复学几轮再采一批\text{采一批} \rightarrow \text{反复学几轮} \rightarrow \text{再采一批}

这就是它比原始 on-policy 方法更高效的地方。

十二、课程里出现的几个超参数,怎么理解

课程笔记里提到了一些常见超参数:

  • γ=0.99\gamma = 0.99
  • lr=0.0007\mathrm{lr} = 0.0007
  • Kepochs=4K_{\text{epochs}} = 4
  • ϵclip=0.2\epsilon_{\text{clip}} = 0.2

可以这样理解:

1. γ\gamma

折扣因子,越接近 1,越重视长期收益。

2. lr\mathrm{lr}

学习率,控制每次更新走多大步。

3. KepochsK_{\text{epochs}}

同一批采样数据会被重复训练多少轮。

4. ϵclip\epsilon_{\text{clip}}

PPO 的“安全护栏”宽度。
太小,更新太保守;太大,容易不稳定。

十三、这节最容易混淆的点

1. PPO 不是凭空来的

PPO 不是突然冒出来的新公式,而是沿着:

策略梯度 -> baseline -> 数据复用 -> importance sampling -> clip 约束

这条线自然长出来的。

2. baseline 不等于“随便减个常数”

baseline 的本质是降方差。
简单减均值是入门版,更常见的是用状态价值函数构造 advantage。

3. importance sampling 不是“旧数据一定都能安全复用”

只有当新旧策略分布接近时,重要性采样才靠谱。
否则概率比值会很极端,训练会不稳定。

4. PPO 不等于典型 off-policy

虽然它确实复用了同一批数据,但标准 PPO 通常仍被视为 on-policy / near-on-policy 方法。

5. PPO 限制的是“策略变化”,不是简单限制参数变化

真正关心的是:

  • 同一个状态下
  • 新旧策略对动作概率的看法差了多少

而不是仅仅看 theta 本身的数值差。

十四、本节关键词速记

术语简单解释
Trajectory / tau一整局的状态动作序列
Return / Reward一步奖励或累计奖励
Policy Gradient直接优化策略参数的梯度方法
Baseline用来降低方差的基线
Advantage“比平均水平好多少”的量
On-policy用当前策略采样、当前策略学习
Off-policy可以用别的策略生成的数据学习
Importance Sampling用概率比值修正分布差异
Ratio rtr_t新旧策略在同一动作上的概率比
Clip对更新幅度加限制,防止步子太大

十五、适合初学者的复习模板

如果你要口头解释“PPO 为什么成立”,可以按下面这套模板说:

  1. 强化学习想最大化策略的期望累计奖励。
  2. 先通过策略梯度把这个目标转成可采样估计的梯度形式。
  3. 原始策略梯度方差大,所以先加 baseline 降方差。
  4. 但 on-policy 每次都要重新采样,样本效率低。
  5. 所以用 importance sampling 让旧策略数据也能辅助新策略。
  6. 但如果新旧策略差太远,概率比值会爆炸。
  7. PPO 用 clip 把新旧策略的差异限制在一个安全范围内,从而兼顾效率和稳定性。

十六、本节和分节笔记的对应关系

十七、我的补充理解

如果把这节课压缩成一个最关键的认识,那就是:

PPO 不是“更复杂的策略梯度”,而是“更稳、更省样本、更敢用”的策略梯度。

它成功的原因不在于公式看起来复杂,而在于它同时解决了三个非常实际的问题:

  • 原始策略梯度噪声大
  • 数据太贵,不能只用一次
  • 策略更新太猛,容易学崩

后面你再学 PPO 代码时,只要始终盯住下面这三个问题,就不会迷路:

  • 这一步是在算哪种回报或 advantage?
  • 这一步是在比较新旧策略的哪个概率?
  • 这一步是在防止哪种不稳定?

想清楚这三点,PPO 代码就会比公式更容易懂。

相关笔记

强化学习

强化学习简介

强化学习简介及应用,初步了解强化学习

打开笔记

NLP

预训练语言模型BERT源码解读

预训练语言模型BERT谷歌老版的源码解读

打开笔记
PPO算法与公式推导 | 三火