Skip to main content

策略梯度法公式推导

一、策略梯度法(Policy Gradient)解决了什么问题?

在讲任何一条公式之前,先回答一个必须先想清楚的问题:

前面已经有 Q-Learning、SARSA、DQN 这些"基于价值(Value-Based)"的方法了,为什么科学家还要发明"直接学策略 πθ\pi_{\theta}"的策略梯度法?它究竟补了什么坑?

1.1 Value-Based 方法(Q-Learning / DQN)的三个硬伤

序号痛点具体表现为什么策略梯度能治好
连续/巨大动作空间不可行机器人关节扭矩、大模型下一个 token、自动驾驶方向盘角度… aa 是实数向量或几万个离散值,argmaxaQ(s,a)\arg\max_{a} Q(s,a) 根本算不动(每步要做一次最大化,维数灾难)策略 πθ(as)\pi_{\theta}(a \mid s) 直接输出动作(离散:logits→softmax;连续:均值/方差的高斯分布),一次前向就采样得到动作,不需要 argmax。
学不出随机策略Q 表/Q 网络最后一定是"挑最大的那个动作",得到确定性贪心策略。但有些任务最优就是随机(比如石头剪刀布对抗、CartPole 少信息观测下的探索)策略网络本身就是概率分布 πθ(as)\pi_{\theta}(a \mid s),天然支持随机性。
更新不稳定 / 样本效率差Q-Learning 里每次更新会让 QQ 变,一变又导致 TD 目标变,还要靠经验回放、目标网络才能勉强稳策略梯度是直接对累计奖励做梯度上升,目标函数的语义非常清晰:"让高回报的轨迹出现概率更大、低回报的更小",收敛性分析更干净。

一句话总结策略梯度法的存在意义:

把"先学 QQ 再从 QQ 里抠出最优动作"的两阶段问题,直接替换成"对 πθ\pi_{\theta} 的参数 θ\theta 求『期望总奖励』的梯度,做梯度上升",一步到位。

1.2 我们的目标(先把 optimization problem 写清楚)

给定一个由 θ\theta 参数化的随机策略 πθ(as)\pi_{\theta}(a \mid s),我们要找到最好的 θ\theta,使得:用这个策略在环境里玩一整局,能拿到的期望总奖励最大

形式化写出来就是:

θ  =  argmaxθ    J(θ)其中J(θ)    Eτπθ[R(τ)]\theta_{*} \;=\; \arg\max_{\theta}\;\; J(\theta) \qquad\text{其中}\qquad J(\theta) \;\triangleq\; \mathbb{E}_{\tau \sim \pi_{\theta}}\Big[\, R(\tau) \,\Big]

这里 τ=(S0,A0,R1,S1,A1,R2,,ST)\tau = (S_{0}, A_{0}, R_{1}, S_{1}, A_{1}, R_{2}, \dots, S_{T})一条轨迹(一条样本路径),R(τ)=t=0T1Rt+1R(\tau)=\sum_{t=0}^{T-1} R_{t+1} 是这条轨迹的累计奖励。


二、策略梯度定理:从"要最大化 J(θ)J(\theta)"到"可实现的更新公式"

读这一节时请记住一个主线任务:θJ(θ)\nabla_{\theta} J(\theta) 推出来,并最终把它写成"用采样轨迹就能估计、且 θ\theta 只出现在 θlogπθ\nabla_{\theta} \log \pi_{\theta} 里"的样子。——因为那样就能在代码里实现了。

2.1 先把 J(θ)J(\theta) 展开成所有轨迹的加权求和

J(θ)J(\theta) 是在"按 πθ\pi_{\theta} 产生轨迹"下的期望。离散情况可以把期望写成"对每条可能轨迹 τ\tau,取它发生的概率 Pθ(τ)P_{\theta}(\tau) × 它的累计奖励":

J(θ)  =  τPθ(τ)R(τ)J(\theta) \;=\; \sum_{\tau} P_{\theta}(\tau)\, R(\tau)

连续状态/动作时把 \sum 换成 \intPθP_{\theta} 换成概率密度 pθp_{\theta},后续推导完全一样,不影响结论。

2.2 对 θ\theta 求导 —— 卡住了!

直接对上面的式子求梯度:

θJ(θ)  =  θτPθ(τ)R(τ)\nabla_{\theta} J(\theta) \;=\; \nabla_{\theta} \sum_{\tau} P_{\theta}(\tau)\, R(\tau)

线性算子可交换求和与求导:

θJ(θ)  =  τ[θPθ(τ)]R(τ)(1)\nabla_{\theta} J(\theta) \;=\; \sum_{\tau} \big[\, \nabla_{\theta} P_{\theta}(\tau) \,\big]\, R(\tau) \tag{1}

现在问题来了:你如果就按 (1) 实现,根本做不到——因为:

  1. 你根本没法把所有轨迹 τ\tau 枚举完(组合爆炸,像 2.1 节说的);
  2. θPθ(τ)\nabla_{\theta} P_{\theta}(\tau) 是对"概率本身"求导,在深度学习框架里反向传播没办法直接算 log_prob 以外的梯度形式(更重要的是:没有期望符号就没法做蒙特卡洛估计)。

2.3 关键一步:Log-Derivative Trick(对数导数恒等式)把问题变简单

科学家掏出一个"万能的"初等微积分恒等式,把"对概率求导"转化为"概率 × 对对数概率求导":

  θPθ(τ)  =  Pθ(τ)θlogPθ(τ)  \boxed{\;\nabla_{\theta} P_{\theta}(\tau) \;=\; P_{\theta}(\tau) \cdot \nabla_{\theta} \log P_{\theta}(\tau)\;}

证明(一行就够)

f(θ)=Pθ(τ)f(\theta) = P_{\theta}(\tau),由链式法则:

θlogf(θ)=1f(θ)θf(θ)θf(θ)=f(θ)θlogf(θ)\nabla_{\theta} \log f(\theta) = \frac{1}{f(\theta)} \nabla_{\theta} f(\theta) \quad\Rightarrow\quad \nabla_{\theta} f(\theta) = f(\theta)\cdot\nabla_{\theta} \log f(\theta)

QED.

把这个恒等式代回 (1) 式,得到:

θJ(θ)=τ[Pθ(τ)θlogPθ(τ)]R(τ)=τPθ(τ)  [θlogPθ(τ)R(τ)]\begin{aligned} \nabla_{\theta} J(\theta) &= \sum_{\tau} \Big[\, P_{\theta}(\tau)\,\nabla_{\theta} \log P_{\theta}(\tau) \,\Big]\, R(\tau) \\ &= \sum_{\tau} P_{\theta}(\tau)\;\Big[\, \nabla_{\theta} \log P_{\theta}(\tau) \cdot R(\tau) \,\Big] \end{aligned}

τPθ(τ)()\sum_{\tau} P_{\theta}(\tau)(\dots) 本身就是"在轨迹分布 τPθ\tau \sim P_{\theta} 下取期望"的定义!所以我们成功把公式写成了可采样的期望形式

θJ(θ)  =  EτPθ[θlogPθ(τ)R(τ)](2)\nabla_{\theta} J(\theta) \;=\; \mathbb{E}_{\tau \sim P_{\theta}}\Big[\, \nabla_{\theta} \log P_{\theta}(\tau) \cdot R(\tau) \,\Big] \tag{2}

2.4 把 logPθ(τ)\log P_{\theta}(\tau) 对 MDP 展开 —— 看看哪些项能消掉

一条 MDP 轨迹的联合概率,能按马尔可夫链规则拆成:初始状态分布、每一步选动作 πθ\pi_{\theta}、每一步环境转移 PP 的乘积:

Pθ(τ)=d0(S0)t=0T1[πθ(AtSt)  P(St+1St,At)]P_{\theta}(\tau) = d_{0}(S_{0}) \cdot \prod_{t=0}^{T-1}\Big[\,\pi_{\theta}(A_{t} \mid S_{t})\; P(S_{t+1} \mid S_{t},\, A_{t})\,\Big]

其中:

  • d0(S0)d_{0}(S_{0}):环境的初始状态分布(不依赖 θ\theta
  • P(St+1St,At)P(S_{t+1} \mid S_{t}, A_{t}):环境动力学 / 状态转移概率(环境说了算,也不依赖 θ\theta
  • 只有 πθ(AtSt)\pi_{\theta}(A_{t} \mid S_{t}) 这部分θ\theta 有关

对两边取对数,乘积变成求和:

logPθ(τ)=logd0(S0)  +  t=0T1logπθ(AtSt)  +  t=0T1logP(St+1St,At)\log P_{\theta}(\tau) = \log d_{0}(S_{0}) \;+\; \sum_{t=0}^{T-1}\log \pi_{\theta}(A_{t} \mid S_{t}) \;+\; \sum_{t=0}^{T-1} \log P(S_{t+1}\mid S_{t},\, A_{t})

现在θ\theta 求梯度。凡是不含 θ\theta 的项,导数都是 0——于是第一项、第三项全部清零!只剩:

  θlogPθ(τ)  =  t=0T1θlogπθ(AtSt)  (3)\boxed{\;\nabla_{\theta} \log P_{\theta}(\tau) \;=\; \sum_{t=0}^{T-1} \nabla_{\theta} \log \pi_{\theta}(A_{t} \mid S_{t})\;} \tag{3}

这个结果的两个重要直觉

  1. "对策略求梯度"只取决于策略本身,和环境转移动力学无关! 你不需要知道环境是怎么从 (s,a)(s,a) 跳到 ss' 的——这就是策略梯度方法的"模型无关(model-free)"根本来源。
  2. θlogPθ(τ)\nabla_{\theta} \log P_{\theta}(\tau) 是每一步 "log 概率的梯度"的。直觉:某一步你选 AtA_{t} 的 log-likelihood 变大,整条轨迹发生的 likelihood 也变大;反过来每一步都在做贡献。

2.5 代回 (2):我们得到了 REINFORCE 的"朴素版本"

把 (3) 代入 (2):

θJ(θ)=EτPθ[  (t=0T1θlogπθ(AtSt))整局所有 log-prob 梯度之和R(τ)整局累计奖励  ](4)\nabla_{\theta} J(\theta) = \mathbb{E}_{\tau \sim P_{\theta}}\left[\; \underbrace{\Big(\sum_{t=0}^{T-1} \nabla_{\theta} \log \pi_{\theta}(A_{t} \mid S_{t})\Big)}_{\text{整局所有 log-prob 梯度之和}} \cdot \underbrace{R(\tau)}_{\text{整局累计奖励}} \;\right] \tag{4}

这就能写代码了吗?能跑但有两个理论错误导致方差巨大,必须修:

  • ❌ 每一步 ttlogπt\nabla \log \pi_{t} 都被"整局的全部奖励 R(τ)R(\tau)"乘了一次——t=0t=0 的动作都吃到了 t=999t=999 的奖励权重,这在因果上是荒谬的(你 0 时刻的动作不可能影响它之前发生的东西);
  • ❌ 每一步吃到的奖励值绝对值太大,导致梯度的方差爆炸(CartPole 500 步一局的总奖励也有几百;如果是 Dota 那种一局几万步呢?)。

2.6 因果修正(Causality):第 tt 步的动作配它"之后"的奖励

修正非常自然:tt 个时刻动作 AtA_{t} 能影响的只有从 tt 时刻开始拿到的回报,我们用「从 tt 起算的折扣回报 GtG_{t}」替换掉它乘的权重:

Gt    k=0T1tγkRt+k+1G_{t} \;\triangleq\; \sum_{k=0}^{T-1-t} \gamma^{k} R_{t+k+1}

于是 (4) 式变成了因果正确的版本:

θJ(θ)=EτPθ[  t=0T1θlogπθ(AtSt)Gt  ](5)\nabla_{\theta} J(\theta) = \mathbb{E}_{\tau \sim P_{\theta}}\left[\; \sum_{t=0}^{T-1} \nabla_{\theta} \log \pi_{\theta}(A_{t} \mid S_{t}) \cdot G_{t} \;\right] \tag{5}

这个修改不引入偏差(数学上可以证明是等价的无偏估计,只是方差变小了)。直觉上相当于"功劳分配":越晚的动作,越只吃到后续奖励的功劳,不再被过去的噪声污染。

2.7 再减一个基线(Baseline):方差能更低

我们可以把上面乘的权重,再减去一个不依赖 AtA_{t}(因此条件期望为 0,不会带来偏差)的标量基线 bt(s)b_{t}(s)

G~t  =  Gtbt(St)\tilde{G}_{t} \;=\; G_{t} - b_{t}(S_{t})

数学上保证"无偏"的原因:对任意仅依赖 StS_{t} 的函数 b(St)b(S_{t}),都有

Eπθ[θlogπθ(AtSt)b(St)St]=b(St)θaπθ(aSt)1=b(St)θ1=0\mathbb{E}_{\pi_{\theta}}\Big[\, \nabla_{\theta} \log \pi_{\theta}(A_{t}\mid S_{t})\, b(S_{t}) \mid S_{t} \,\Big] = b(S_{t})\, \nabla_{\theta} \sum_{a} \pi_{\theta}(a\mid S_{t}) \cdot 1 = b(S_{t})\, \nabla_{\theta} 1 = 0

所以加一个基线只是减掉一个期望为 0 的向量,梯度估计仍然无偏,但方差会显著变小。

最常见、效果最好的选择是把状态价值函数 Vπθ(St)V^{\pi_{\theta}}(S_{t}) 当作基线(这也是"加 Critic"的 Actor-Critic 框架的由来),差值就叫优势函数

At    GtVπθ(St)(或等价用 TD 误差、GAE 等更稳的形式)A_{t} \;\triangleq\; G_{t} - V^{\pi_{\theta}}(S_{t}) \qquad(\text{或等价用 TD 误差、GAE 等更稳的形式})

代入 (5) 得到最常用的策略梯度(减基线版 / AC 版)

  θJ(θ)=EτPθ[  t=0T1θlogπθ(AtSt)At  ]  \boxed{\; \nabla_{\theta} J(\theta) = \mathbb{E}_{\tau \sim P_{\theta}}\left[\; \sum_{t=0}^{T-1} \nabla_{\theta} \log \pi_{\theta}(A_{t} \mid S_{t}) \cdot A_{t} \;\right] \;}

用代码能跑的蒙特卡洛形式(每条轨迹做一次累加、batch 内再平均)就是 REINFORCE / Actor-Critic 更新的本质:

θ    θ+η1BτBt=0T1θlogπθ(AtSt)At\theta \;\leftarrow\; \theta + \eta \cdot \frac{1}{|\mathcal{B}|} \sum_{\tau \in \mathcal{B}}\sum_{t=0}^{T-1} \nabla_{\theta} \log \pi_{\theta}(A_{t} \mid S_{t}) \cdot A_{t}

其中 η\eta 是学习率,B\mathcal{B} 是一个 batch 采样到的若干条轨迹。


三、REINFORCE 算法(最经典的 Monte Carlo 策略梯度法)— 每一步做什么

有了上面的定理,写代码就是把它机械地翻译出来:

算法 1:REINFORCE(无基线)

输入:可微策略 πθ\pi_{\theta}、学习率 η\eta、折扣因子 γ\gamma 对每个 episode k=1,2,k = 1, 2, \dots

  1. 用当前策略 πθ\pi_{\theta} 在环境里采样一条完整轨迹 τ=(S0,A0,R1,,ST1,AT1,RT)\tau = (S_{0}, A_{0}, R_{1}, \dots, S_{T-1}, A_{T-1}, R_{T})
  2. 对每个时间步 t=0,,T1t = 0, \dots, T-1,算该步起的折扣回报: Gt  =  i=tT1γitRi+1G_{t} \;=\; \sum_{i=t}^{T-1} \gamma^{i-t}\, R_{i+1}
  3. 把所有步的梯度乘以权重累加,做一次梯度上升: θ    θ+ηt=0T1γtGtθlogπθ(AtSt)\theta \;\leftarrow\; \theta + \eta \cdot \sum_{t=0}^{T-1} \gamma^{t} \, G_{t} \cdot \nabla_{\theta} \log \pi_{\theta}(A_{t} \mid S_{t})

注:工程上常用 logπθGt-\log \pi_{\theta} \cdot G_{t} 作为损失,直接调 torch 的反向传播 loss.backward()optimizer.step(),数学上等价于"对 JJ 做梯度上升,对 loss 做梯度下降"。

算法 2:REINFORCE with Baseline(减状态价值基线,训练更稳)

和算法 1 唯一区别是并行训练一个 Critic 网络 Vϕ(s)V_{\phi}(s) 估计状态价值,用 GtVϕ(St)G_{t} - V_{\phi}(S_{t}) 替换 GtG_{t}

  1. 采样完整轨迹(同 1)
  2. 计算各步 GtG_{t}(同 1)
  3. 用 Critic 最小化 MSE 拟合 Vϕ(St)GtV_{\phi}(S_{t}) \approx G_{t}(监督学习式的回归)
  4. 用优势 At=GtVϕ(St)A_{t} = G_{t} - V_{\phi}(S_{t}) 加权更新策略 θ\theta
    θθ+ηtγtAtθlogπθ(AtSt)\theta \leftarrow \theta + \eta \sum_{t} \gamma^{t} A_{t} \nabla_{\theta} \log \pi_{\theta}(A_{t} \mid S_{t})

四、一张表把"策略梯度解决了什么问题"说透

以前的问题(Value-Based / 朴素梯度)策略梯度定理如何解决
连续/高维动作,argmaxaQ\arg\max_{a} Q 算不出来直接学 πθ(as)\pi_{\theta}(a \mid s),采样直接出动作,不求 max
无法建模随机策略输出就是条件概率分布,天然支持随机
朴素公式 τPR\sum_{\tau} \nabla P \cdot R 无法采样计算Log-derivative trickP\nabla P 变成 PlogPP \nabla\log P,再写成 Eτ[logPR]\mathbb{E}_{\tau}[\nabla\log P \cdot R],蒙特卡洛可估计
梯度依赖环境模型 P(ss,a)P(s' \mid s,a)展开 logPθ(τ)\log P_{\theta}(\tau) 后,不含 θ\thetaP(ss,a)P(s' \mid s,a)d0d_{0} 对梯度贡献为 0,梯度里只剩 tlogπθ\sum_{t} \nabla \log \pi_{\theta}——模型无关
每一步权重用总奖励 R(τ)R(\tau):因果错误 + 大方差因果修正:只乘该步之后的回报 GtG_{t}
GtG_{t} 绝对值仍然太大导致梯度抖动减基线(通常是 VV)→ 优势 AtA_{t},保留动作相对好坏,进一步降方差

得到的最终可执行形式(REINFORCE / AC 通用梯度)就是:

  θJ(θ)  =  E[t=0T1θlogπθ(AtSt)At]  \boxed{\; \nabla_{\theta} J(\theta) \;=\; \mathbb{E}\left[\, \sum_{t=0}^{T-1} \nabla_{\theta} \log \pi_{\theta}(A_{t} \mid S_{t}) \cdot A_{t} \,\right] \;}

所有现代策略方法(PPO / TRPO / A2C / SAC / RLHF 里的 PPO 微调段)本质上都是围绕这条式子做"更稳的优势估计 + 更大的更新步长约束",但骨架没变过