1. k3 是怎么来的?
先定义概率比:
r=πrefπnewr=\frac{\pi_{ref}}{\pi_{new}}r=πnewπref
如果样本来自 new policy,那么:
DKL(πnew∥πref)=E[−logr]D_{KL}(\pi_{new}\|\pi_{ref})=E[-\log r]DKL(πnew∥πref)=E[−logr]
所以最直接的 KL 估计就是:
k1=−logrk_1=-\log rk1=−logr
但还有一个性质:
E[r]=1E[r]=1E[r]=1
原因是:
E[r]=∑aπnew(a)πref(a)πnew(a)=∑aπref(a)=1E[r]=\sum_a \pi_{new}(a)\frac{\pi_{ref}(a)}{\pi_{new}(a)}=\sum_a \pi_{ref}(a)=1E[r]=a∑πnew(a)πnew(a)πref(a)=a∑πref(a)=1
因此:
E[r−1]=0E[r-1]=0E[r−1]=0
也就是说,给k1k_1k1加上r−1r-1r−1,不会改变它的期望:
E[−logr+r−1]=E[−logr]E[-\log r+r-1]=E[-\log r]E[−logr+r−1]=E[−logr]
于是得到:
k3=r−1−logrk_3=r-1-\log rk3=r−1−logr
所以k3 本质上就是在 k1 上加了一个期望为 0 的修正项,使得不会出现有负数的情况。
2. 为什么从 k1、k2 到 k3?
k1:最直接
k1=−logrk_1=-\log rk1=−logr
优点:期望就是真实 KL,无偏。
缺点:单个样本可能为负,波动较大。
k2:二阶近似
k2=12(logr)2k_2=\frac{1}{2}(\log r)^2k2=21(logr)2
当 new policy 和 reference policy 很接近,即r≈1r\approx1r≈1时,KL 可以近似成这个平方形式。
优点:永远非负,数值比较稳定。
缺点:它只是近似,因此存在 bias。
k3:实际更常用
k3=r−1−logrk_3=r-1-\log rk3=r−1−logr
它同时满足:
- 期望仍然是真实 KL,也就是无偏
- 每个样本都大于等于 0
- 通常比 k1 更稳定
写成代码形式
kl=ref_logprob-logprob ratio=torch.exp(kl)# ref / newk3=ratio-kl-1因此可以简单记:
k1:无偏,但噪声大
k2:稳定,但有近似误差
k3:无偏 + 非负 + 通常更稳定
3. KL 放 Reward 还是 Loss?
两种都可以,目的都是限制 policy 不要离 reference model 太远。
PPO / RLHF 常见:放 Reward
R=RRM−βKLR=R_{RM}-\beta KLR=RRM−βKL
然后:
Reward → Advantage → Policy Loss
所以 KL 是先惩罚 reward,再间接影响 loss。
GRPO 常见:放 Loss
L=Lpolicy+βKLL=L_{policy}+\beta KLL=Lpolicy+βKL
KL 直接作为正则项限制 policy。
因此可以简单记:
PPO / RLHF:KL 常放 Reward
GRPO:KL 常放 Loss
但这只是常见实现方式,并不是硬性规定。