最近在看 PPO / GRPO 的 policy gradient 实现时,我注意到一个挺有意思的问题:

当 advantage 为负,而 importance ratio 非常大时,PPO 的 clipping 并不会阻止一个非常大的负向梯度。

这件事乍看有点反直觉。很多人对 PPO clipping 的第一印象是:

ratio 太大或者太小,就把它截断,避免 policy 更新过猛。

但严格来说,这并不完全正确。

这篇文章从这个问题出发,尝试构造一种不依赖 hard clipping,而是平滑限制 policy gradient 强度的 surrogate objective。


1. 从最基本的 Policy Gradient 开始

对于一个 token/action,最简单的 importance-weighted policy objective 可以写成:

\[ J_t(\theta)=r_tA_t \]

其中:

\[ r_t= \frac{\pi_\theta(a_t|s_t)} {\pi_{\mathrm{old}}(a_t|s_t)} \]

\(A_t\) 是 advantage。

因为:

\[ \nabla_\theta r_t = r_t\nabla_\theta\log\pi_\theta(a_t|s_t) \]

所以:

\[ \nabla_\theta J_t = A_t r_t \nabla_\theta\log\pi_\theta(a_t|s_t) \]

这个公式其实已经说明了两个东西:

\[ \boxed{ A_t\text{ 决定强化还是抑制,} \quad r_t\text{ 决定梯度被放大多少} } \]

当 \(A_t>0\),我们希望提高当前 token 的概率。

当 \(A_t<0\),我们希望降低当前 token 的概率。

问题在于,如果:

\[ A_t=-1,\qquad r_t=10000 \]

那么:

\[ \nabla_\theta J_t = -10000 \nabla_\theta\log\pi_\theta \]

负向更新可能非常大。


2. PPO clipping 能解决这个问题吗?

PPO 的 clipped objective 是:

\[ J_t^{\mathrm{PPO}} = \min \left( r_tA_t,\; \operatorname{clip}(r_t,1-\epsilon,1+\epsilon)A_t \right) \]

假设:

\[ A_t=-1,\qquad r_t=10000,\qquad \epsilon=0.2 \]

第一项:

\[ r_tA_t=-10000 \]

第二项:

\[ 1.2\times(-1)=-1.2 \]

于是:

\[ \min(-10000,-1.2)=-10000 \]

也就是说,这里并没有被 clip。

梯度依然是:

\[ \nabla_\theta J_t = -10000\nabla_\theta\log\pi_\theta \]

为什么?

因为 PPO clipping 本身就是非对称的。

对于 \(A>0\),PPO 防止一个好 action 的概率被提高得太多:

\[ r>1+\epsilon \quad\Rightarrow\quad \nabla J=0 \]

对于 \(A<0\),PPO 防止一个坏 action 的概率被降低得太多:

\[ r<1-\epsilon \quad\Rightarrow\quad \nabla J=0 \]

但是:

\[ \boxed{ A<0,\quad r\gg1 } \]

意味着一个“坏 action”的概率反而比 old policy 高了很多。

PPO 认为这是一个应该被强烈纠正的方向,所以不会把它 clip 掉。

逻辑上没有错。

但问题是:真的有必要让这种纠正强度随着 \(r\) 无限增长吗?


3. 我真正想限制的不是 ratio,而是梯度强度

这里可以换一个思路。

我们不一定需要说:

\(r\) 超过某个值以后,直接把梯度变成 0。

我们真正想要的可能是:

\(r\) 越大,负向抑制越强;但是这种抑制应该逐渐饱和,而不是无限增长。

也就是希望找到一个函数 \(h(r)\),满足:

\[ h(1)=1 \]

这样 policy 没有明显 drift 时,不改变原始 PG。

同时:

\[ h(r)\approx r \]

在正常区域尽量保持 importance sampling 的行为。

但当:

\[ r\rightarrow\infty \]

希望:

\[ h(r)\rightarrow B \]

其中 \(B\) 是我们允许的最大梯度放大倍数。

一个很简单的候选是:

\[ \boxed{ h_B(r)=\frac{Br}{B-1+r} } \]

其中 \(B>1\)。


4. 一个 Smooth Saturation Importance Weight

这个函数有几个不错的性质。

首先:

\[ h_B(1)=1 \]

所以在 \(r=1\) 处,它和原始 importance weight 完全一致。

其次:

\[ \lim_{r\rightarrow\infty}h_B(r)=B \]

所以无论 ratio 多大:

\[ \boxed{ h_B(r)\le B } \]

例如取 \(B=2\):

\(r\) 原始 \(r\) \(h_2(r)\)
0.5 0.5 0.667
1 1 1
2 2 1.333
10 10 1.818
100 100 1.980
10000 10000 1.9998

于是刚才:

\[ A=-1,\qquad r=10000 \]

原本对应:

\[ -10000\nabla\log\pi \]

现在变成大约:

\[ -2\nabla\log\pi \]

方向没有改变,但更新强度有界。

这和 hard clipping 有明显区别。

PPO 更像:

\[ \text{正常梯度} \rightarrow \text{突然变成 0} \]

而 smooth saturation 是:

\[ \text{正常增长} \rightarrow \text{增长逐渐变慢} \rightarrow \text{趋近有限上限} \]


5. 不能只改梯度:能否找到对应的 Objective?

如果只是手工把梯度中的 \(r\) 换成 \(h(r)\),当然可以实现。

但更自然的问题是:

是否存在一个真正的 surrogate objective,它求导之后恰好得到这个梯度?

假设:

\[ J_{\mathrm{smooth}}=A f(r) \]

我们希望:

\[ \nabla_\theta J_{\mathrm{smooth}} = A h_B(r) \nabla_\theta\log\pi_\theta \]

又因为:

\[ \nabla_\theta r = r\nabla_\theta\log\pi_\theta \]

所以:

\[ \nabla_\theta f(r) = f'(r)r\nabla_\theta\log\pi_\theta \]

因此只需要满足:

\[ rf'(r)=h_B(r) \]

代入:

\[ h_B(r)=\frac{Br}{B-1+r} \]

得到:

\[ f'(r)=\frac{B}{B-1+r} \]

积分:

\[ f(r)=B\log(B-1+r)+C \]

如果希望 \(f(1)=1\),可以写成:

\[ \boxed{ f_B(r) = 1+ B\log \left( \frac{B-1+r}{B} \right) } \]

于是得到一个完整的 smooth surrogate:

\[ \boxed{ J_{\mathrm{smooth}} = A \left[ 1+ B\log \left( \frac{B-1+r}{B} \right) \right] } \]

它的梯度正好是:

\[ \boxed{ \nabla_\theta J_{\mathrm{smooth}} = A \frac{Br}{B-1+r} \nabla_\theta\log\pi_\theta } \]

这就比较有意思了。

它不是简单做 gradient clipping,而是从 objective 本身构造出了一个有界的 effective importance weight。


6. 如果只担心 Negative Advantage 呢?

实际上,我最初关注的问题并不是所有 \(r\),而是:

\[ A<0,\qquad r\gg1 \]

因此可以进一步做成 asymmetric objective。

定义:

\[ A^+=\max(A,0) \]

\[ A^-=\min(A,0) \]

然后:

\[ \boxed{ J = A^+r + A^-f_B(r) } \]

对应梯度:

\[ \boxed{ \nabla J = \left[ A^+r + A^- \frac{Br}{B-1+r} \right] \nabla\log\pi } \]

这样:

对于 positive advantage:

\[ A>0 \]

仍然保持原始 importance-weighted PG。

而对于 negative advantage:

\[ A<0 \]

使用:

\[ A\frac{Br}{B-1+r} \]

因此:

\[ \left| A\frac{Br}{B-1+r} \right| \le B|A| \]

也就是说:

坏 action 仍然会受到惩罚,但单个 token 的 importance weight 不会无限放大这种惩罚。

这正是我想要的性质。


7. 另一种思路:在 Log-Ratio 空间做 Saturation

还有一种思路也很自然。

定义:

\[ z=\log r \]

然后直接构造:

\[ J=A B\tanh(z/B) \]

由于:

\[ \nabla_\theta z = \nabla_\theta\log\pi_\theta \]

所以:

\[ \nabla_\theta J = A\operatorname{sech}^2(z/B) \nabla_\theta\log\pi_\theta \]

这里会出现一个完全不同的行为:

\[ r\rightarrow\infty \quad\Rightarrow\quad \nabla J\rightarrow0 \]

它表达的思想是:

一个样本如果已经严重 off-policy,那么这个样本本身可能已经不值得信任,因此逐渐忽略它。

而前面的 rational saturation:

\[ h_B(r)=\frac{Br}{B-1+r} \]

表达的是:

即使严重 off-policy,我仍然认为这个负反馈是有效的,只是不允许它无限主导更新。

这其实是两种不同的 inductive bias。


8. 三种方法背后的不同哲学

把它们放在一起看,会非常清楚。

PPO clipping

\[ \text{越界} \Rightarrow \text{部分区域直接停止更新} \]

Log-ratio saturation

\[ \text{越离谱} \Rightarrow \text{越不相信这个样本} \Rightarrow \nabla J\rightarrow0 \]

Bounded importance gradient

\[ \text{越离谱} \Rightarrow \text{仍然纠正} \Rightarrow \text{但纠正强度存在上限} \]

我目前更感兴趣的是第三种。

因为对于:

\[ A<0,\qquad r\gg1 \]

这个样本传递的信息其实是明确的:

当前 policy 相比 rollout policy,大幅提高了一个 negative-advantage action 的概率。

完全不给梯度似乎有点浪费。

但让:

\[ r=10^4 \]

产生 \(10^4\) 量级的 importance weighting,又可能让极少数异常 token 对优化产生过大的影响。

所以一个折中的目标是:

\[ \boxed{ \text{Keep the direction, bound the strength.} } \]


9. 一个值得继续验证的问题

当然,上面的构造目前更多是一个 objective-design idea,而不是说它一定比 PPO 更好。

真正需要实验回答的问题很多。

例如:

  • \(B\) 应该取多少?
  • positive / negative advantage 是否应该使用不同的 \(B\)?
  • 是否应该只处理 \(A<0,r>1\) 这个象限?
  • 对 GRPO 的 group-relative advantage 有什么影响?
  • token-level ratio 的长尾到底有多严重?
  • 是否会降低 exploration?
  • 是否影响 PPO 原本的 pessimistic surrogate 性质?
  • 和直接 gradient norm clipping 相比有什么区别?
  • 在 stale rollout / fully-async RL 场景下是否更有价值?

尤其是最后一点。

在 asynchronous RL 中,policy version lag 会天然增加:

\[ \left| \log\pi_\theta-\log\pi_{\mathrm{old}} \right| \]

importance ratio 的长尾问题可能因此更加明显。

这种情况下,与其单纯丢掉 stale trajectory,或让极端 ratio 产生非常大的梯度,也许存在第三种选择:

\[ \boxed{ \text{保留 trajectory,但平滑限制它能施加的最大更新强度。} } \]

我觉得这是这个思路最值得继续实验的地方。


总结

最初的问题其实非常简单:

当 \(A<0\) 且 \(r\gg1\) 时,我们真的希望 policy gradient 随着 \(r\) 无限增长吗?

PPO 的答案基本是:在这个方向上允许,因为 policy 正在严重增加一个 negative-advantage action 的概率。

但另一种可能是:

\[ \boxed{ \text{惩罚应该继续,但惩罚强度不需要无限增长。} } \]

于是可以构造:

\[ h_B(r)=\frac{Br}{B-1+r} \]

以及对应的 smooth surrogate:

\[ \boxed{ J_{\mathrm{smooth}} = A \left[ 1+ B\log \left( \frac{B-1+r}{B} \right) \right] } \]

它保留了 advantage 的强化/抑制方向,同时把 effective importance weight 平滑限制在有限范围内。

这未必是最终最优的形式,但我觉得它提供了一个挺直接的视角:

PPO 不一定只能在“保留梯度”和“clip 成 0”之间二选一。我们也可以让梯度保留方向,同时让强度平滑饱和。

这可能尤其适合 importance ratio 长尾明显、policy lag 较大的异步 RL 场景。