编辑
2025-04-03
深度学习
00

目录

GRPO (Generalized Rewards with Policy Optimization) 训练方法分析
1. GRPO 的核心思想
2. GRPO 算法流程
2.1 初始化阶段
2.2 训练循环
3. GRPO 的关键参数
4. GRPO 的实现细节
4.1 数据处理
4.2 奖励计算
4.3 策略优化
5. GRPO 与其他方法的比较
5.1 与 PPO 的区别
5.2 与 DPO 的区别
5.3 GRPO 的优势
6. 结论
GRPO 中 KL 散度惩罚项的实现方式和相关公式
KL 散度惩罚项的实现
1. KL 散度的数学公式
2. GRPO 中的 KL 散度计算
3. 在代码中的实现
4. 完整的 KL 惩罚过程
小结

https://github.com/om-ai-lab/VLM-R1/tree/main

GRPO (Generalized Rewards with Policy Optimization) 训练方法分析

GRPO 是一种起源于 DeepSeekMath 论文的强化学习方法,用于优化语言模型或多模态模型。它特别适用于优化特定任务的性能,如数学推理或遵循指令。

1. GRPO 的核心思想

GRPO 结合了两个主要思想:

  1. 基于群组的奖励优化:在同一提示下生成多个可能的输出,然后根据这些输出的相对优劣进行优化
  2. 近端策略优化 (PPO) 的变体:使用裁剪目标函数来确保策略更新不会偏离太远

2. GRPO 算法流程

2.1 初始化阶段

  • 加载策略模型(待训练的模型)
  • 加载参考模型(通常是策略模型的初始副本)
  • 加载一个或多个奖励函数,用于评估生成的回答质量

2.2 训练循环

每个批次的训练过程如下:

  1. 生成样本

    • 对于每个提示,生成 num_generations(默认为8)个不同的完成(回答)
    • 使用温度采样使生成的回答多样化
  2. 评估奖励

    • 对每个生成的回答应用奖励函数
    • 如果有多个奖励函数,将它们的结果加权求和
  3. 计算优势

    • 对于每个提示,计算其所有回答的平均奖励和标准差
    • 将每个回答的奖励标准化:优势 = (奖励 - 平均奖励) / (标准差 + ε)
    • 这样做的目的是比较同一提示下不同回答的相对优劣
  4. 策略优化

    • 计算策略比率:r = exp(新策略对数概率 - 旧策略对数概率)
    • 应用 PPO 的裁剪目标:min(r * 优势, clip(r, 1-ε, 1+ε) * 优势)
    • 将上述目标取负用于梯度下降
  5. KL 惩罚项(可选):

    • 添加一个 KL 散度惩罚项:β * KL(参考策略 || 当前策略)
    • 这有助于防止模型偏离初始行为太远
  6. 多次迭代更新(可选):

    • 可以对同一批数据执行多次梯度更新(通过 num_iterations 参数控制)
    • 这提高了样本效率,但需要小心避免过拟合

3. GRPO 的关键参数

从代码中可以看出,GRPO 有几个关键参数影响其训练行为:

  • num_generations:每个提示生成的回答数量(默认为8)
  • epsilon:PPO 裁剪阈值(默认为0.2)
  • beta:KL 惩罚系数(默认为0.04)
  • num_iterations:每批数据的更新次数(默认为1)
  • max_completion_length:生成回答的最大长度
  • temperature:生成时的温度参数,控制随机性

4. GRPO 的实现细节

从代码实现中,我们可以看到一些重要的实现细节:

4.1 数据处理

  • 使用 RepeatRandomSampler 确保每个提示生成多个回答
  • 处理多模态输入(如图像)以支持 VLM(视觉语言模型)训练

4.2 奖励计算

python
# 计算分组奖励统计 mean_grouped_rewards = rewards.view(-1, self.num_generations).mean(dim=1) std_grouped_rewards = rewards.view(-1, self.num_generations).std(dim=1) # 标准化奖励以计算优势 mean_grouped_rewards = mean_grouped_rewards.repeat_interleave(self.num_generations, dim=0) std_grouped_rewards = std_grouped_rewards.repeat_interleave(self.num_generations, dim=0) advantages = (rewards - mean_grouped_rewards) / (std_grouped_rewards + 1e-4)

4.3 策略优化

python
# 计算策略比率和裁剪版本 coef_1 = torch.exp(per_token_logps - old_per_token_logps) coef_2 = torch.clamp(coef_1, 1 - self.epsilon, 1 + self.epsilon) per_token_loss1 = coef_1 * advantages.unsqueeze(1) per_token_loss2 = coef_2 * advantages.unsqueeze(1) per_token_loss = -torch.min(per_token_loss1, per_token_loss2) # 添加 KL 惩罚(如果 beta > 0) if self.beta > 0: ref_per_token_logps = inputs["ref_per_token_logps"] per_token_kl = torch.exp(ref_per_token_logps - per_token_logps) - (ref_per_token_logps - per_token_logps) - 1 per_token_loss = per_token_loss + self.beta * per_token_kl

5. GRPO 与其他方法的比较

5.1 与 PPO 的区别

  • GRPO 使用群组相对奖励,而不是绝对奖励
  • 这减少了对显式人类反馈的依赖,通过相对比较自动发现更好的生成

5.2 与 DPO 的区别

  • DPO(Direct Preference Optimization)需要成对偏好数据
  • GRPO 不需要显式的偏好对,而是通过相对奖励隐式创建偏好信号

5.3 GRPO 的优势

  • 不需要人类标注的偏好对
  • 可以利用任意奖励函数组合
  • 通过批量生成并比较,有效地搜索更好的回答

6. 结论

GRPO 是一种用于优化语言模型或多模态模型的强大方法,特别适合没有大量人类偏好数据但有明确奖励信号的场景。它通过生成多样化的回答并比较它们的相对奖励来优化模型,将标准的 PPO 与相对奖励结合,形成一种有效的自我改进机制。

该方法的核心创新在于将"群组"内的相对比较融入到策略优化框架中,从而使模型能够学习到何种回答更好,而不仅仅是尝试增加绝对奖励值。

GRPO 中 KL 散度惩罚项的实现方式和相关公式

KL 散度惩罚项的实现

在 GRPO 中,KL 散度惩罚的具体实现如下:

python
per_token_kl = torch.exp(ref_per_token_logps - per_token_logps) - (ref_per_token_logps - per_token_logps) - 1 per_token_loss = per_token_loss + self.beta * per_token_kl

1. KL 散度的数学公式

KL 散度(Kullback-Leibler 散度)衡量两个概率分布 P 和 Q 的差异,其标准数学公式为:

KL(PQ)=xP(x)logP(x)Q(x)=xP(x)logP(x)xP(x)logQ(x)KL(P||Q) = \sum_{x} P(x) \log\frac{P(x)}{Q(x)} = \sum_{x} P(x) \log P(x) - \sum_{x} P(x) \log Q(x)

2. GRPO 中的 KL 散度计算

在 GRPO 中,我们计算的是参考策略(ref_model)与当前策略(policy_model)之间的 KL 散度:

KL(πrefπθ)=Exπref[logπref(x)πθ(x)]KL(\pi_{ref}||\pi_{\theta}) = \mathbb{E}_{x \sim \pi_{ref}} \left[ \log \frac{\pi_{ref}(x)}{\pi_{\theta}(x)} \right]

其中:

  • πref\pi_{ref} 是参考策略(初始模型)
  • πθ\pi_{\theta} 是当前策略(正在训练的模型)

3. 在代码中的实现

代码中使用了一种更直接的计算方式,利用了对数概率:

  • ref_per_token_logps 是参考模型的对数概率
  • per_token_logps 是当前模型的对数概率

具体实现是:

python
per_token_kl = torch.exp(ref_per_token_logps - per_token_logps) - (ref_per_token_logps - per_token_logps) - 1

这个公式是 KL 散度的一种数值计算形式,我们可以通过数学推导来理解:

我们想计算 KL(PQ)KL(P||Q),其中 P 是参考策略,Q 是当前策略。

定义 r=logP(x)logQ(x)r = \log P(x) - \log Q(x),那么: KL(PQ)=ExP[r]KL(P||Q) = \mathbb{E}_{x \sim P}[r]

将对数展开成 Taylor 级数并取期望,可以得到: KL(PQ)ExP[err1]KL(P||Q) \approx \mathbb{E}_{x \sim P}[e^r - r - 1]

这就是代码中的实现: per_token_kl=e(ref_logppolicy_logp)(ref_logppolicy_logp)1per\_token\_kl = e^{(ref\_logp - policy\_logp)} - (ref\_logp - policy\_logp) - 1

4. 完整的 KL 惩罚过程

  1. 计算每个 token 位置的 KL 散度:

    python
    per_token_kl = torch.exp(ref_per_token_logps - per_token_logps) - (ref_per_token_logps - per_token_logps) - 1
  2. 将 KL 惩罚项添加到策略优化损失中:

    python
    per_token_loss = per_token_loss + self.beta * per_token_kl

    其中 beta 是控制 KL 惩罚强度的超参数。

  3. 计算平均 KL 散度用于监控:

    python
    mean_kl = ((per_token_kl * completion_mask).sum(dim=1) / completion_mask.sum(dim=1)).mean()

完整的 GRPO 损失函数

将 KL 散度整合到完整的 GRPO 损失函数中,我们得到:

LGRPO(θ)=min(rθ(x)A(x),clip(rθ(x),1ϵ,1+ϵ)A(x))+βKL(πrefπθ)L_{GRPO}(\theta) = -\min\left(r_{\theta}(x) A(x), \text{clip}(r_{\theta}(x), 1-\epsilon, 1+\epsilon) A(x)\right) + \beta \cdot KL(\pi_{ref}||\pi_{\theta})

其中:

  • rθ(x)=πθ(x)πθold(x)=exp(logπθ(x)logπθold(x))r_{\theta}(x) = \frac{\pi_{\theta}(x)}{\pi_{\theta_{old}}(x)} = \exp(\log \pi_{\theta}(x) - \log \pi_{\theta_{old}}(x)) 是策略比率
  • A(x)A(x) 是优势函数,在 GRPO 中是基于组内归一化的奖励
  • ϵ\epsilon 是裁剪参数(默认为 0.2)
  • β\beta 是 KL 惩罚系数(默认为 0.04)
  • KL(πrefπθ)KL(\pi_{ref}||\pi_{\theta}) 是参考策略与当前策略之间的 KL 散度

小结

GRPO 中的 KL 散度惩罚项是通过以下公式实现的:

KL(πrefπθ)e(logP(x)logQ(x))(logP(x)logQ(x))1KL(\pi_{ref}||\pi_{\theta}) \approx e^{(\log P(x) - \log Q(x))} - (\log P(x) - \log Q(x)) - 1

这个惩罚项确保当前策略不会偏离初始参考策略太远,帮助保持模型行为的稳定性,防止过度优化导致灾难性遗忘或行为偏离。KL 散度的强度由超参数 β 控制,β 越大,模型越倾向于保持接近参考策略。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!