一、策略梯度法(Policy Gradient)解决了什么问题?
在讲任何一条公式之前,先回答一个必须先想清楚的问题:
前面已经有 Q-Learning、SARSA、DQN 这些"基于价值(Value-Based)"的方法了,为什么科学家还要发明"直接学策略 πθ"的策略梯度法?它究竟补了什么坑?
1.1 Value-Based 方法(Q-Learning / DQN)的三个硬伤
| 序号 | 痛点 | 具体表现 | 为什么策略梯度能治好 |
|---|
| ① | 连续/巨大动作空间不可行 | 机器人关节扭矩、大模型下一个 token、自动驾驶方向盘角度… a 是实数向量或几万个离散值,argmaxaQ(s,a) 根本算不动(每步要做一次最大化,维数灾难) | 策略 πθ(a∣s) 直接输出动作(离散:logits→softmax;连续:均值/方差的高斯分布),一次前向就采样得到动作,不需要 argmax。 |
| ② | 学不出随机策略 | Q 表/Q 网络最后一定是"挑最大的那个动作",得到确定性贪心策略。但有些任务最优就是随机(比如石头剪刀布对抗、CartPole 少信息观测下的探索) | 策略网络本身就是概率分布 πθ(a∣s),天然支持随机性。 |
| ③ | 更新不稳定 / 样本效率差 | Q-Learning 里每次更新会让 Q 变,一变又导致 TD 目标变,还要靠经验回放、目标网络才能勉强稳 | 策略梯度是直接对累计奖励做梯度上升,目标函数的语义非常清晰:"让高回报的轨迹出现概率更大、低回报的更小",收敛性分析更干净。 |
一句话总结策略梯度法的存在意义:
把"先学 Q 再从 Q 里抠出最优动作"的两阶段问题,直接替换成"对 πθ 的参数 θ 求『期望总奖励』的梯度,做梯度上升",一步到位。
1.2 我们的目标(先把 optimization problem 写清楚)
给定一个由 θ 参数化的随机策略 πθ(a∣s),我们要找到最好的 θ,使得:用这个策略在环境里玩一整局,能拿到的期望总奖励最大。
形式化写出来就是:
θ∗=argθmaxJ(θ)其中J(θ)≜Eτ∼πθ[R(τ)] 这里 τ=(S0,A0,R1,S1,A1,R2,…,ST) 叫一条轨迹(一条样本路径),R(τ)=∑t=0T−1Rt+1 是这条轨迹的累计奖励。
二、策略梯度定理:从"要最大化 J(θ)"到"可实现的更新公式"
读这一节时请记住一个主线任务:把 ∇θJ(θ) 推出来,并最终把它写成"用采样轨迹就能估计、且 θ 只出现在 ∇θlogπθ 里"的样子。——因为那样就能在代码里实现了。
2.1 先把 J(θ) 展开成所有轨迹的加权求和
J(θ) 是在"按 πθ 产生轨迹"下的期望。离散情况可以把期望写成"对每条可能轨迹 τ,取它发生的概率 Pθ(τ) × 它的累计奖励":
J(θ)=τ∑Pθ(τ)R(τ) 连续状态/动作时把 ∑ 换成 ∫、Pθ 换成概率密度 pθ,后续推导完全一样,不影响结论。
2.2 对 θ 求导 —— 卡住了!
直接对上面的式子求梯度:
∇θJ(θ)=∇θτ∑Pθ(τ)R(τ) 线性算子可交换求和与求导:
∇θJ(θ)=τ∑[∇θPθ(τ)]R(τ)(1) 现在问题来了:你如果就按 (1) 实现,根本做不到——因为:
- 你根本没法把所有轨迹 τ 枚举完(组合爆炸,像 2.1 节说的);
- ∇θPθ(τ) 是对"概率本身"求导,在深度学习框架里反向传播没办法直接算
log_prob 以外的梯度形式(更重要的是:没有期望符号就没法做蒙特卡洛估计)。
2.3 关键一步:Log-Derivative Trick(对数导数恒等式)把问题变简单
科学家掏出一个"万能的"初等微积分恒等式,把"对概率求导"转化为"概率 × 对对数概率求导":
∇θPθ(τ)=Pθ(τ)⋅∇θlogPθ(τ) 证明(一行就够)
令 f(θ)=Pθ(τ),由链式法则:
∇θlogf(θ)=f(θ)1∇θf(θ)⇒∇θf(θ)=f(θ)⋅∇θlogf(θ) QED.
把这个恒等式代回 (1) 式,得到:
∇θJ(θ)=τ∑[Pθ(τ)∇θlogPθ(τ)]R(τ)=τ∑Pθ(τ)[∇θlogPθ(τ)⋅R(τ)] 但 ∑τPθ(τ)(…) 本身就是"在轨迹分布 τ∼Pθ 下取期望"的定义!所以我们成功把公式写成了可采样的期望形式:
∇θJ(θ)=Eτ∼Pθ[∇θlogPθ(τ)⋅R(τ)](2) 2.4 把 logPθ(τ) 对 MDP 展开 —— 看看哪些项能消掉
一条 MDP 轨迹的联合概率,能按马尔可夫链规则拆成:初始状态分布、每一步选动作 πθ、每一步环境转移 P 的乘积:
Pθ(τ)=d0(S0)⋅t=0∏T−1[πθ(At∣St)P(St+1∣St,At)] 其中:
- d0(S0):环境的初始状态分布(不依赖 θ)
- P(St+1∣St,At):环境动力学 / 状态转移概率(环境说了算,也不依赖 θ)
- 只有 πθ(At∣St) 这部分跟 θ 有关
对两边取对数,乘积变成求和:
logPθ(τ)=logd0(S0)+t=0∑T−1logπθ(At∣St)+t=0∑T−1logP(St+1∣St,At) 现在对 θ 求梯度。凡是不含 θ 的项,导数都是 0——于是第一项、第三项全部清零!只剩:
∇θlogPθ(τ)=t=0∑T−1∇θlogπθ(At∣St)(3) 这个结果的两个重要直觉
- "对策略求梯度"只取决于策略本身,和环境转移动力学无关! 你不需要知道环境是怎么从 (s,a) 跳到 s′ 的——这就是策略梯度方法的"模型无关(model-free)"根本来源。
- ∇θlogPθ(τ) 是每一步 "log 概率的梯度"的和。直觉:某一步你选 At 的 log-likelihood 变大,整条轨迹发生的 likelihood 也变大;反过来每一步都在做贡献。
2.5 代回 (2):我们得到了 REINFORCE 的"朴素版本"
把 (3) 代入 (2):
∇θJ(θ)=Eτ∼Pθ⎣⎡整局所有 log-prob 梯度之和(t=0∑T−1∇θlogπθ(At∣St))⋅整局累计奖励R(τ)⎦⎤(4) 这就能写代码了吗?能跑但有两个理论错误导致方差巨大,必须修:
- ❌ 每一步 t 的 ∇logπt 都被"整局的全部奖励 R(τ)"乘了一次——连 t=0 的动作都吃到了 t=999 的奖励权重,这在因果上是荒谬的(你 0 时刻的动作不可能影响它之前发生的东西);
- ❌ 每一步吃到的奖励值绝对值太大,导致梯度的方差爆炸(CartPole 500 步一局的总奖励也有几百;如果是 Dota 那种一局几万步呢?)。
2.6 因果修正(Causality):第 t 步的动作配它"之后"的奖励
修正非常自然:第 t 个时刻动作 At 能影响的只有从 t 时刻开始拿到的回报,我们用「从 t 起算的折扣回报 Gt」替换掉它乘的权重:
Gt≜k=0∑T−1−tγkRt+k+1 于是 (4) 式变成了因果正确的版本:
∇θJ(θ)=Eτ∼Pθ[t=0∑T−1∇θlogπθ(At∣St)⋅Gt](5) 这个修改不引入偏差(数学上可以证明是等价的无偏估计,只是方差变小了)。直觉上相当于"功劳分配":越晚的动作,越只吃到后续奖励的功劳,不再被过去的噪声污染。
2.7 再减一个基线(Baseline):方差能更低
我们可以把上面乘的权重,再减去一个不依赖 At(因此条件期望为 0,不会带来偏差)的标量基线 bt(s):
G~t=Gt−bt(St) 数学上保证"无偏"的原因:对任意仅依赖 St 的函数 b(St),都有
Eπθ[∇θlogπθ(At∣St)b(St)∣St]=b(St)∇θa∑πθ(a∣St)⋅1=b(St)∇θ1=0 所以加一个基线只是减掉一个期望为 0 的向量,梯度估计仍然无偏,但方差会显著变小。
最常见、效果最好的选择是把状态价值函数 Vπθ(St) 当作基线(这也是"加 Critic"的 Actor-Critic 框架的由来),差值就叫优势函数:
At≜Gt−Vπθ(St)(或等价用 TD 误差、GAE 等更稳的形式) 代入 (5) 得到最常用的策略梯度(减基线版 / AC 版):
∇θJ(θ)=Eτ∼Pθ[t=0∑T−1∇θlogπθ(At∣St)⋅At] 用代码能跑的蒙特卡洛形式(每条轨迹做一次累加、batch 内再平均)就是 REINFORCE / Actor-Critic 更新的本质:
θ←θ+η⋅∣B∣1τ∈B∑t=0∑T−1∇θlogπθ(At∣St)⋅At 其中 η 是学习率,B 是一个 batch 采样到的若干条轨迹。
三、REINFORCE 算法(最经典的 Monte Carlo 策略梯度法)— 每一步做什么
有了上面的定理,写代码就是把它机械地翻译出来:
算法 1:REINFORCE(无基线)
输入:可微策略 πθ、学习率 η、折扣因子 γ
对每个 episode k=1,2,…:
- 用当前策略 πθ 在环境里采样一条完整轨迹 τ=(S0,A0,R1,…,ST−1,AT−1,RT)
- 对每个时间步 t=0,…,T−1,算该步起的折扣回报:
Gt=∑i=tT−1γi−tRi+1
- 把所有步的梯度乘以权重累加,做一次梯度上升:
θ←θ+η⋅∑t=0T−1γtGt⋅∇θlogπθ(At∣St)
注:工程上常用 −logπθ⋅Gt 作为损失,直接调 torch 的反向传播 loss.backward() 再 optimizer.step(),数学上等价于"对 J 做梯度上升,对 loss 做梯度下降"。
算法 2:REINFORCE with Baseline(减状态价值基线,训练更稳)
和算法 1 唯一区别是并行训练一个 Critic 网络 Vϕ(s) 估计状态价值,用 Gt−Vϕ(St) 替换 Gt:
- 采样完整轨迹(同 1)
- 计算各步 Gt(同 1)
- 用 Critic 最小化 MSE 拟合 Vϕ(St)≈Gt(监督学习式的回归)
- 用优势 At=Gt−Vϕ(St) 加权更新策略 θ:
θ←θ+ηt∑γtAt∇θlogπθ(At∣St)
四、一张表把"策略梯度解决了什么问题"说透
| 以前的问题(Value-Based / 朴素梯度) | 策略梯度定理如何解决 |
|---|
| 连续/高维动作,argmaxaQ 算不出来 | 直接学 πθ(a∣s),采样直接出动作,不求 max |
| 无法建模随机策略 | 输出就是条件概率分布,天然支持随机 |
| 朴素公式 ∑τ∇P⋅R 无法采样计算 | Log-derivative trick 把 ∇P 变成 P∇logP,再写成 Eτ[∇logP⋅R],蒙特卡洛可估计 |
| 梯度依赖环境模型 P(s′∣s,a) | 展开 logPθ(τ) 后,不含 θ 的 P(s′∣s,a)、d0 对梯度贡献为 0,梯度里只剩 ∑t∇logπθ——模型无关 |
| 每一步权重用总奖励 R(τ):因果错误 + 大方差 | 因果修正:只乘该步之后的回报 Gt |
| Gt 绝对值仍然太大导致梯度抖动 | 减基线(通常是 V)→ 优势 At,保留动作相对好坏,进一步降方差 |
得到的最终可执行形式(REINFORCE / AC 通用梯度)就是:
∇θJ(θ)=E[t=0∑T−1∇θlogπθ(At∣St)⋅At] 所有现代策略方法(PPO / TRPO / A2C / SAC / RLHF 里的 PPO 微调段)本质上都是围绕这条式子做"更稳的优势估计 + 更大的更新步长约束",但骨架没变过。