PPO
论文:Proximal Policy Optimization Algorithms
代码:https://github.com/CarperAI/trlx/blob/main/trlx/models/modeling_ppo.py
背景知识
策略梯度方法
策略梯度方法直接对策略进行参数化,并通过最大化预期 回报来优化策略参数。常用的策略梯度估计器为:
g ^ = E ^ t [ ∇ θ log π θ ( a t ∣ s t ) A ^ t ] {\hat{g}}={\hat{\mathbb{E}}}_{t} \Big[ \nabla_{\theta} \operatorname{l o g} \pi_{\theta} ( a_{t} \mid s_{t} ) {\hat{A}}_{t} \Big]
g ^ = E ^ t [ ∇ θ l o g π θ ( a t ∣ s t ) A ^ t ]
其中:
E ^ t [ ⋅ ] \hat{\mathbb{E}}_t[⋅] E ^ t [ ⋅ ] 表示对采样数据的经验平均;
π表示随机策略;
A ^ t \hat{A}_t A ^ t 是优势函数(Advantage Function)的估计,衡量动作a t a_t a t 相对于基准策略在状态s t s_t s t 下的好坏。
信赖域方法(TRPO)
为了解决策略更新不稳定的问题,信赖域策略优化(Trust Region Policy Optimization,TRPO) 被提出,核心思想是在策略更新时加入约束,限制新旧策略之间的差异。
TRPO解决以下优化问题:
maximize θ E ^ t [ π θ ( a t ∣ s t ) π θ old ( a t ∣ s t ) A ^ t ] subject to E ^ t [ KL [ π θ old ( ⋅ ∣ s t ) , π θ ( ⋅ ∣ s t ) ] ] ≤ δ \begin{array}{cl}
\underset{\theta}{\operatorname{maximize}} & \hat{\mathbb{E}}_t\left[\frac{\pi_\theta\left(a_t \mid s_t\right)}{\pi_{\theta_{\text {old }}}\left(a_t \mid s_t\right)} \hat{A}_t\right] \\
\text { subject to } & \hat{\mathbb{E}}_t\left[\operatorname{KL}\left[\pi_{\theta_{\text {old }}}\left(\cdot \mid s_t\right), \pi_\theta\left(\cdot \mid s_t\right)\right]\right] \leq \delta
\end{array}
θ m a x i m i z e subject to E ^ t [ π θ old ( a t ∣ s t ) π θ ( a t ∣ s t ) A ^ t ] E ^ t [ K L [ π θ old ( ⋅ ∣ s t ) , π θ ( ⋅ ∣ s t ) ] ] ≤ δ
其中:
π θ o l d π_{θ_{old}} π θ o l d 是旧的策略;
KL[⋅|⋅] 表示两个策略在状态st 下的KL散度(Kullback-Leibler Divergence);
δ 是预设的阈值,限制策略更新的幅度。
TRPO通过复杂的二阶优化方法(如共轭梯度算法)求解上述约束优化问题。虽然TRPO在实践中表现稳定,但其实现较为复杂,且不易与一些神经网络结构(如共享参数的网络、包含随机噪声的网络)结合。
重要性采样是一种数据利用技巧。首先用策略模型πθ去和环境交互,产生一系列轨迹,然后用新的相同策略模型πθ′和环境交互,产生一系列轨迹。然后用这些轨迹去多次更新之前的策略模型πθ。但是我们并不是直接用这些轨迹对我们需要求取的策略模型进行迭代,而是需要对采样动作的概率进行比例放缩。重要性采样的优势在于隔离采样的轨迹和目标策略模型的关系。
参考文章:https://zhuanlan.zhihu.com/p/1895169683969274027
近端策略优化(PPO)
PPO旨在保留TRPO性能稳定的优点,同时简化实现,并提高数据利用率。
截断的代理目标(Clipped Surrogate Objective)
PPO引入了截断的代理目标函数,限制策略更新的幅度,避免过大的策略变化。
首先,定义概率比率(Probability Ratio):
r t ( θ ) = π θ ( a t ∣ s t ) π θ o l d ( a t ∣ s t ) r_t(\theta)=\frac{\pi_\theta\left(a_t \mid s_t\right)}{\pi_{\theta_{\mathrm{old}}}\left(a_t \mid s_t\right)}
r t ( θ ) = π θ o l d ( a t ∣ s t ) π θ ( a t ∣ s t )
在TRPO中,优化的代理目标函数为:
L C P I ( θ ) = E ^ t [ π θ ( a t ∣ s t ) π θ old ( a t ∣ s t ) A ^ t ] = E ^ t [ r t ( θ ) A ^ t ] . L^{C P I}(\theta)=\hat{\mathbb{E}}_t\left[\frac{\pi_\theta\left(a_t \mid s_t\right)}{\pi_{\theta_{\text {old }}}\left(a_t \mid s_t\right)} \hat{A}_t\right]=\hat{\mathbb{E}}_t\left[r_t(\theta) \hat{A}_t\right] .
L C P I ( θ ) = E ^ t [ π θ old ( a t ∣ s t ) π θ ( a t ∣ s t ) A ^ t ] = E ^ t [ r t ( θ ) A ^ t ] .
上标 CPI (conservative policy iteration)指的是保守策略迭代。
为了避免策略的过度更新,PPO引入了截断函数,定义新的目标函数:
L C L I P ( θ ) = E ^ t [ min ( r t ( θ ) A ^ t , clip ( r t ( θ ) , 1 − ϵ , 1 + ϵ ) A ^ t ) ] L^{C L I P}(\theta)=\hat{\mathbb{E}}_t\left[\min \left(r_t(\theta) \hat{A}_t, \operatorname{clip}\left(r_t(\theta), 1-\epsilon, 1+\epsilon\right) \hat{A}_t\right)\right]
L C L I P ( θ ) = E ^ t [ min ( r t ( θ ) A ^ t , c l i p ( r t ( θ ) , 1 − ϵ , 1 + ϵ ) A ^ t ) ]
其中:
c l i p ( r t ( θ ) , 1 − ϵ , 1 + ϵ ) clip(r_t(θ), 1−ϵ, 1+ϵ) c l i p ( r t ( θ ) , 1 − ϵ , 1 + ϵ ) 表示将r t ( θ ) r_t(θ) r t ( θ ) 限制在[1−ϵ, 1+ϵ] 区间内;
ϵ 是超参数,控制截断的幅度,通常取值为0.1或0.2。
截断目标函数的作用:
限制策略更新幅度:通过截断r t ( θ ) r_t(θ) r t ( θ ) ,防止策略在一次更新中发生过大的变化。
保留优化灵活性:当优势A t A^t A t 为正时,允许r t ( θ ) r_t(θ) r t ( θ ) 增加,但不超过 1+ϵ ;当A t A^t A t 为负时,允许r t ( θ ) r_t(θ) r t ( θ ) 减少,但不低于 1−ϵ 。
提高数据利用率:由于有了稳定的目标函数,可以对同一批数据进行多次更新,而不会导致策略崩溃。
自适应的KL散度惩罚(Adaptive KL Penalty Coefficient)
另一种控制策略更新的方法是加入KL散度惩罚项,并自适应调整惩罚系数。
定义目标函数:
L K L P E N ( θ ) = E ^ t [ π θ ( a t ∣ s t ) π θ old ( a t ∣ s t ) A ^ t − β KL [ π θ old ( ⋅ ∣ s t ) , π θ ( ⋅ ∣ s t ) ] ] L^{K L P E N}(\theta)=\hat{\mathbb{E}}_t\left[\frac{\pi_\theta\left(a_t \mid s_t\right)}{\pi_{\theta_{\text {old }}}\left(a_t \mid s_t\right)} \hat{A}_t-\beta \operatorname{KL}\left[\pi_{\theta_{\text {old }}}\left(\cdot \mid s_t\right), \pi_\theta\left(\cdot \mid s_t\right)\right]\right]
L K L P E N ( θ ) = E ^ t [ π θ old ( a t ∣ s t ) π θ ( a t ∣ s t ) A ^ t − β K L [ π θ old ( ⋅ ∣ s t ) , π θ ( ⋅ ∣ s t ) ] ]
其中:
β 是KL散度的惩罚系数;
通过调整β ,控制策略更新的幅度。
自适应调整β:
当实际KL散度d 小于目标值d_targ 的1.5倍时,减小β ,允许更大的策略更新;
当d 大于d_targ 的1.5倍时,增大β ,限制策略更新的幅度。
这样,β 会根据策略更新的情况,自适应地调整,维持策略变化在合适的范围内。
算法(Algorithm)
PPO算法的主要步骤如下:
采样数据 :使用当前策略π θ o l d π_{θ_{old}} π θ o l d 与环境交互,收集数据(状态、动作、奖励等)。
计算优势函数 :使用 广义优势估计(Generalized Advantage Estimation,GAE) 等方法,计算优势函数A ^ t \hat{A}_t A ^ t 。
构建目标函数 :根据选择,构建LCLIP(θ) 或LKLPEN(θ) 。
多轮优化 :使用随机梯度上升法(如Adam),对目标函数进行K 轮优化。
更新策略 :将θ o l d θ_{old} θ o l d 更新为优化后的θ 。
重复上述步骤 :迭代进行,直到达到训练目标。
优势估计量是**广义优势估计(Generalized Advantage Estimation,GAE)**的截断版本,即
A ^ t = δ t + ( γ λ ) δ t + 1 + ⋯ + ⋯ + ( γ λ ) T − t + 1 δ T − 1 , where δ t = r t + γ V ( s t + 1 ) − V ( s t ) \begin{aligned}
& \hat{A}_t=\delta_t+(\gamma \lambda) \delta_{t+1}+\cdots+\cdots+(\gamma \lambda)^{T-t+1} \delta_{T-1}, \\
& \text { where } \quad \delta_t=r_t+\gamma V\left(s_{t+1}\right)-V\left(s_t\right)
\end{aligned}
A ^ t = δ t + ( γ λ ) δ t + 1 + ⋯ + ⋯ + ( γ λ ) T − t + 1 δ T − 1 , where δ t = r t + γ V ( s t + 1 ) − V ( s t )
其中:
r t r_t r t :当前奖励。
γ:折扣因子。
V ( s t ) V(s_t) V ( s t ) :当前状态价值估计。
V ( s t + 1 ) V(s_t+1) V ( s t + 1 ) :下一状态价值估计。
δ t = r t + γ V ( s t + 1 ) − V ( s t ) δ_t=r_t + γV(s_t+1) - V(s_t) δ t = r t + γ V ( s t + 1 ) − V ( s t ) 是TD-error(Temporal Difference error,时序差分误差)。
价值函数
t时刻状态s的总收益 = 身处状态s能带来的即时收益 + 从状态s出发后能带来的未来收益
V t = R t + γ V t + 1 V_t=R_t+\gamma V_{t+1}
V t = R t + γ V t + 1
其中:
V t V_t V t : t 时刻的总收益,注意这个收益蕴涵了“即时”和“未来”的概念
R t R_t R t : t 时刻的即时收益
V t + 1 V_{t+1} V t + 1 : t+1 时刻的总收益,注意这个收益蕴涵了“即时”和“未来”的概念。而 Vt+1 对 Vt 来说就是“未来”。
γ :折扣因子。它决定了我们在多大程度上考虑将“未来收益”纳入“当下收益”。
TD-error(Temporal Difference error,时序差分误差) 是强化学习中衡量当前价值估计与一步引导(bootstrap)目标之间偏差的核心量,用来指导参数更新。
TD误差有两种主要形式:
1-step TD误差:只考虑一步的未来奖励和价值,如上述公式所示。
n-step TD误差:考虑多步的未来奖励和价值,例如n-step TD(λ)算法,可以更平滑地估计长期价值。
广义优势估计
优势就是在当前状态下,这次选这个动作,是不是比平常更赚。
优势 = 实际表现 − 预测表现
r t + γ V ( s t + 1 ) r_t + γV(s_t+1) r t + γ V ( s t + 1 ) 表示实际表现,它表示当前奖励 + 折扣后的未来价值,V ( s t ) V(s_t) V ( s t ) 表示预测表现
优势计算:
def get_advantages_and_returns (self, values, rewards, start ): """ Adopted from https://github.com/CarperAI/trlx/blob/main/trlx/models/modeling_ppo.py#L134 没有引入GAE前的t时刻的优势值: detal_t = r_t + gamma * V_t+1 - V_t 其中: - r_t表示t时刻的即时收益 - V_t+1表示未来时刻的预期收益 - r_t + gamma * V_t+1可理解成t时刻的实际预期收益 - V_t可理解成t时刻的预估预期收益(是模型,例如critic model自己估算出来的) 引入GAE后的t时刻的优势值: A_t = delta_t + gamma * lambda * A_t+1 粗暴理解为在t时刻时,不仅考虑当下优势,还考虑了未来的优势 为了知道A_t, 我们得知道A_t+1,所以在本算法中采取了从后往前做动态规划求解的方法,也即: 假设T是最后一个时刻,则有A_T+1 = 0, 所以有: A_T = delta_T 知道了A_T, 就可以依次往前倒推,把A_t-1, A_t-2之类都算出来了 引入GAE后t时刻的实际预期收益 returns_t = A_t + V_t = delta_t + gamma * lambda * A_t+1 + V_t = r_t + gamma * V_t+1 - V_t + gamma * lambda * A_t+1 + V_t = r_t + gamma * (V_t+1 + lambda * A_t+1) 注意,这里不管是advantages还是returns,都只算response的部分 """ lastgaelam = 0 advantages_reversed = [] length = rewards.size()[-1 ] for t in reversed (range (start, length)): nextvalues = values[:, t + 1 ] if t < length - 1 else 0.0 delta = rewards[:, t] + self .gamma * nextvalues - values[:, t] lastgaelam = delta + self .gamma * self .lam * lastgaelam advantages_reversed.append(lastgaelam) advantages = torch.stack(advantages_reversed[::-1 ], dim=1 ) returns = advantages + values[:, start:] return advantages.detach(), returns
每次迭代,N个并行的参与者收集T个时间步长的数据。然后计算在这些数据上的损失,并使用minibatch SGD对K epoch进行优化。
Algorithm 1 PPO, Actor-Critic Style for iteration=1, 2, . . . do for actor=1, 2, . . . , N do Run policy πθold in environment for T timesteps Compute advantage estimates Aˆ1, ... , AˆT end for Optimize surrogate L wrt θ, with K epochs and minibatch size M ≤ NT θold ← θ end for
在强化学习里trajectory / episode / rollout 都是指“状态–动作–奖励序列 ”
实验与结果
在连续控制任务中,作者比较了以下几种方法:
无截断或惩罚:直接优化L C P I ( θ ) L^{CPI}(θ) L C P I ( θ ) 。
截断的目标函数:使用不同ϵ 值的L C L I P ( θ ) L^{CLIP}(θ) L C L I P ( θ ) 。
固定的KL惩罚:使用固定β 的L K L P E N ( θ ) L^{KLPEN}(θ) L K L P E N ( θ ) 。
自适应的KL惩罚:动态调整β 的L K L P E N ( θ ) L^{KLPEN}(θ) L K L P E N ( θ ) 。
实验结果表明:
使用截断的目标函数,尤其是ϵ=0.2 时,算法性能最好 。
自适应KL惩罚的方法次之。
固定KL惩罚的方法表现较差。
无截断或惩罚的方法由于策略更新过大,导致性能不稳定,甚至下降。
附录
PPO其他实现:
参考文章:
GRPO
论文:DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models
代码:https://github.com/huggingface/trl/blob/main/trl/trainer/grpo_trainer.py
PPO 需加载策略模型、价值模型、参考模型和奖励模型(共4个),显存占用高。
GRPO 仅需策略模型、参考模型和奖励模型(共3个),资源消耗更低。
GRPO相比PPO优化:
无价值模型优化 :GRPO 通过比较组内的响应消除了对评论模型的需求,从而显著减少了计算开销。
相对评估 :GRPO 不依赖外部评估者,而是使用群体动力学来评估某个响应相对于同一批次中其他响应的表现如何。
高效训练 :通过关注基于群体的优势,GRPO 简化了奖励估计过程,使其更快、更适用于大型模型。
GRPO计算流程:
采样一组输出并计算每个输出的奖励。
对组内奖励进行归一化处理。
使用归一化后的奖励计算优势函数。
通过最大化目标函数更新策略模型。
迭代训练,逐步优化策略模型。
PPO目标函数:
J P P O ( θ ) = E [ q ∼ P ( Q ) , o ∼ π θ old ( O ∣ q ) ] 1 ∣ o ∣ ∑ t = 1 ∣ 0 ∣ min [ π θ ( o t ∣ q , o < t ) π θ old ( o t ∣ q , o < t ) A t , clip ( π θ ( o t ∣ q , o < t ) π θ old ( o t ∣ q , o < t ) , 1 − ε , 1 + ε ) A t ] , \mathcal{J}_{P P O}(\theta)=\mathbb{E}\left[q \sim P(Q), o \sim \pi_{\theta_{\text {old }}}(O \mid q)\right] \frac{1}{|o|} \sum_{t=1}^{|0|} \min \left[\frac{\pi_\theta\left(o_t \mid q, o_{<t}\right)}{\pi_{\theta_{\text {old }}}\left(o_t \mid q, o_{<t}\right)} A_t, \operatorname{clip}\left(\frac{\pi_\theta\left(o_t \mid q, o_{<t}\right)}{\pi_{\theta_{\text {old }}}\left(o_t \mid q, o_{<t}\right)}, 1-\varepsilon, 1+\varepsilon\right) A_t\right],
J P P O ( θ ) = E [ q ∼ P ( Q ) , o ∼ π θ old ( O ∣ q ) ] ∣ o ∣ 1 t = 1 ∑ ∣ 0 ∣ min [ π θ old ( o t ∣ q , o < t ) π θ ( o t ∣ q , o < t ) A t , c l i p ( π θ old ( o t ∣ q , o < t ) π θ ( o t ∣ q , o < t ) , 1 − ε , 1 + ε ) A t ] ,
GRPO目标函数:
J G R P O ( θ ) = E [ q ∼ P ( Q ) , { o i } i = 1 G ∼ π θ old ( O ∣ q ) ] 1 G ∑ i = 1 G 1 ∣ o i ∣ ∑ t = 1 ∣ o i ∣ { min [ π θ ( o i , t ∣ q , o i , < t ) π θ old ( o i , t ∣ q , o i , < t ) A ^ i , t , clip ( π θ ( o i , t ∣ q , o i , < t ) π θ old ( o i , t ∣ q , o i , < t ) , 1 − ε , 1 + ε ) A ^ i , t ] − β D K L [ π θ ∥ π r e f ] } , \begin{aligned}
\mathcal{J}_{G R P O}(\theta) & =\mathbb{E}\left[q \sim P(Q),\left\{o_i\right\}_{i=1}^G \sim \pi_{\theta_{\text {old }}}(O \mid q)\right] \\
& \frac{1}{G} \sum_{i=1}^G \frac{1}{\left|o_i\right|} \sum_{t=1}^{\left|o_i\right|}\left\{\min \left[\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{\text {old }}}\left(o_{i, t} \mid q, o_{i,<t}\right)} \hat{A}_{i, t}, \operatorname{clip}\left(\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{\text {old }}}\left(o_{i, t} \mid q, o_{i,<t}\right)}, 1-\varepsilon, 1+\varepsilon\right) \hat{A}_{i, t}\right]-\beta \mathbb{D}_{K L}\left[\pi_\theta \| \pi_{r e f}\right]\right\},
\end{aligned}
J G R P O ( θ ) = E [ q ∼ P ( Q ) , { o i } i = 1 G ∼ π θ old ( O ∣ q ) ] G 1 i = 1 ∑ G ∣ o i ∣ 1 t = 1 ∑ ∣ o i ∣ { min [ π θ old ( o i , t ∣ q , o i , < t ) π θ ( o i , t ∣ q , o i , < t ) A ^ i , t , c l i p ( π θ old ( o i , t ∣ q , o i , < t ) π θ ( o i , t ∣ q , o i , < t ) , 1 − ε , 1 + ε ) A ^ i , t ] − β D K L [ π θ ∥ π r e f ] } ,
GRPO目标函数主要由三部分组成:
策略比值 (Policy Ratio) :衡量新旧策略的变化幅度。
裁剪目标 (Clipped Objective) :防止策略更新过大,确保稳定性。
KL 散度正则化 (KL Divergence Regularization) :防止新策略偏离参考策略过远。
优势估计
A ^ i , t = r ~ i = r i − mean ( r ) std ( r ) \hat{A}_{i, t}=\widetilde{r}_i=\frac{r_i-\operatorname{mean}(\mathbf{r})}{\operatorname{std}(\mathbf{r})}
A ^ i , t = r i = s t d ( r ) r i − m e a n ( r )
参考文章:
DPO
论文:Direct Preference Optimization: Your Language Model is Secretly a Reward Model
代码:https://github.com/eric-mitchell/direct-preference-optimization
DPO(Direct Preference Optimization)将 RLHF 的 2 阶段(训练 reward model和训练 PPO)多个模型的训练简化为了 1 阶段的 SFT 训练。
算法基于PPO的RLHF基础上进行了大幅简化,跳过了奖励建模步骤,直接使用偏好数据优化语言模型,解决了RLHF三个阶段的训练(SFT->RM->PPO)过程较长,更新迭代较慢的问题。DPO只有策略模型和参考模型,不再需要奖励模型。
DPO 提出了一种使用二进制交叉熵 目标来精确优化大模型的方法,以替代基于RLHF的优化目标,从而大大简化偏好学习流程。
目标函数:
∇ θ L D P O ( π θ ; π r e f ) = − β E ( x , y w , y l ) ∼ D [ σ ( r ^ θ ( x , y l ) − r ^ θ ( x , y w ) ) ⏟ higher weight when reward estimate is wrong [ ∇ θ log π ( y w ∣ x ) ⏟ increase likelihood of y w − ∇ θ log π ( y l ∣ x ) ⏟ decrease likelihood of y l ] ] , \begin{aligned}
& \nabla_\theta \mathcal{L}_{\mathrm{DPO}}\left(\pi_\theta ; \pi_{\mathrm{ref}}\right)= \\
& -\beta \mathbb{E}_{\left(x, y_w, y_l\right) \sim \mathcal{D}}[\underbrace{\sigma\left(\hat{r}_\theta\left(x, y_l\right)-\hat{r}_\theta\left(x, y_w\right)\right)}_{\text {higher weight when reward estimate is wrong }}[\underbrace{\nabla_\theta \log \pi\left(y_w \mid x\right)}_{\text {increase likelihood of } y_w}-\underbrace{\nabla_\theta \log \pi\left(y_l \mid x\right)}_{\text {decrease likelihood of } y_l}]],
\end{aligned}
∇ θ L D P O ( π θ ; π r e f ) = − β E ( x , y w , y l ) ∼ D [ higher weight when reward estimate is wrong σ ( r ^ θ ( x , y l ) − r ^ θ ( x , y w ) ) [ increase likelihood of y w ∇ θ log π ( y w ∣ x ) − decrease likelihood of y l ∇ θ log π ( y l ∣ x ) ] ] ,
其中:
r ^ θ ( x , y ) = β log π θ ( y ∣ x ) π r e f ( y ∣ x ) \hat{r}_{\theta} ( x , y )=\beta\operatorname{log} \frac{\pi_{\theta} ( y | x )} {\pi_{\mathrm{ref}} ( y | x )}
r ^ θ ( x , y ) = β l o g π r e f ( y ∣ x ) π θ ( y ∣ x )
参数β是控制策略模型(policy model)与参考模型(reference model)之间的 KL 散度约束强度。
为了方便分析,把log里面的分式展开,然后β设为1,并且忽略前面的log_sigmoid,那么目标函数可以简化为:
[ log p ( y w ) − log p r e f ( y w ) ] − [ log p ( y l ) − log p r e f ( y l ) ] [\operatorname{log} p(y_{w})-\operatorname{log} p_{ref}(y_{w})]-[\operatorname{log} p(y_{l})-\operatorname{log} p_{ref}(y_{l})]
[ l o g p ( y w ) − l o g p r e f ( y w ) ] − [ l o g p ( y l ) − l o g p r e f ( y l ) ]
由于最初loss前面是有个负号的,所以优化目标是让本简化公式最大,即我们希望左半部分和右半部分的margin越大越好。
简化目标函数存在下面三种变化:
左边变大,右边变小,理想情况,good response概率提升,bad response概率下降
左边变小,右边更小,good response概率下降,但是bad response概率下降的更多,生成的时候还是倾向于good response
左边变的更大,右边只大了一点点,和2)同理
“Reward hacking”是指在RLHF过程中,模型发现奖励函数中的漏洞或偏差,从而通过非预期行为获得高奖励的现象。
Q:为什么DPO里Chosen和Rejected概率会同时下降(防止hacking)?
在DPO优化过程中, 对于chosen优化的方向是有不确定性的,DPO实际上优化保证整体增大 ,而不是单一的让chosen prob增大。
解决方案:
为chosen/rejected ratio设定不同参数β
β⁺·logπ(y⁺) − β⁻·logπ(y⁻)(其中 β⁺ > β⁻,如 β⁺=0.6、β⁻=0.2)
我们在DPO优化时,可以确定性的优化使得正例reward>0,如DPO-P
max(0, −r(y⁺|x)),强制模型必须让 r (y⁺|x) > 0,即logπ(y⁺|x) > −C/τ(τ 为温度系数,C 为常数)。
在DPO优化时,同时对正例增加SFT优化
SFT(监督微调)的核心是最小化 y⁺的负对数似然损失(L_SFT = −logπ(y⁺|x)),其目标是直接最大化 y⁺的生成概率,具有极强的 “单向提升” 确定性。将其与 DPO 损失联合优化,可形成互补;
联合损失公式:L = L_DPO + α·L_SFT(α∈[0.1, 0.5],控制 SFT 的权重)。
切换为 KTO:重构目标为 “确定性优化单个策略”,从根源消除比值的不确定性
Q:DPO训练的模型效果如何评估?
核心评估维度:
偏好对齐度(核心)
人工偏好对比测试:赢率、偏好准确率
自动评估(奖励模型 RM):平均奖励得分、排序准确率
生成质量(避免能力损失)
流畅度:Perplexity(困惑度)
任务适配性:BLEU/ROUGE/METEOR(摘要 / 翻译等)
知识准确性:FactScore、TruthfulQA 正确率
安全性(规避有害内容)
对抗性测试:有害内容拒绝率(避免过度拒绝)
基准数据集:HarmBench、RealToxicityPrompts 毒性 / 偏见分数
代码实现:
def preference_loss (policy_chosen_logps: torch.FloatTensor, policy_rejected_logps: torch.FloatTensor, reference_chosen_logps: torch.FloatTensor, reference_rejected_logps: torch.FloatTensor, beta: float , label_smoothing: float = 0.0 , ipo: bool = False , reference_free: bool = False ) -> Tuple [torch.FloatTensor, torch.FloatTensor, torch.FloatTensor]: pi_logratios = policy_chosen_logps - policy_rejected_logps ref_logratios = reference_chosen_logps - reference_rejected_logps if reference_free: ref_logratios = 0 logits = pi_logratios - ref_logratios if ipo: losses = (logits - 1 /(2 * beta)) ** 2 else : losses = -F.logsigmoid(beta * logits) * (1 - label_smoothing) - F.logsigmoid(-beta * logits) * label_smoothing chosen_rewards = beta * (policy_chosen_logps - reference_chosen_logps).detach() rejected_rewards = beta * (policy_rejected_logps - reference_rejected_logps).detach() return losses, chosen_rewards, rejected_rewards
参考文章: