当前位置: 首页 > news >正文

LLM - 理解 DeepSeek 的 GPRO (分组相对策略优化) 公式与源码 教程(2)

欢迎关注我的CSDN:https://spike.blog.csdn.net/
本文地址:https://spike.blog.csdn.net/article/details/145640762


GPRO,即 Group Relative Policy Optimization分组相对的策略优化,是 PPO(Proximal Policy Optimization, 近端策略优化) 的优化版本,省略优化 评论家模型(Critic Model),用于估计价值(Value Function Model),降低模型训练的资源消耗。

GRPO 目标的工作原理如下:

  1. 为查询生成一组响应。
  2. 根据预定义的标准(例如准确性、格式),计算每个响应的奖励。
  3. 比较组内的反应以计算他们的相对优势。
  4. 更新策略以支持具有更高优势的响应,剪裁(clip)确保的稳定性。
  5. 规范更新以防止模型偏离基线太远。

GRPO 有效的原因:

  • 无需评论:GRPO 依靠群体比较,避免对于单独评估者的需求,从而降低了计算成本。
  • 稳定学习:剪裁(clip) 和 KL 正则化确保模型稳步改进,不会出现剧烈波动。
  • 高效训练:通过关注相对性能,GRPO 非常适合推理等绝对评分困难的任务。

在 DeepSeekMath (2024.4) 中,使用 GPRO 代替 PPO。

GRPO

回顾一下 PPO 模型的公式与框架,PPO 是先训练 奖励模型(RM),通过强化学习策略,将奖励模型的能力,学习到大语言模型中,同时,注意模型的输出符合之前的预期,不要偏离过远(KL Divergence)。即:

  • RM(Reward Model, 奖励模型) m a x r ϕ { E ( x , y w i n , y l o s s ) ∼ D [ l o g   σ ( r ϕ ( x , y w i n ) − r ϕ ( x , y l o s s ) ) ] } \underset{r_{\phi}}{max} \{ {E_{(x,y_{win},y_{loss}) \sim D}}[log \ \sigma(r_{\phi}(x,y_{win}) - r_{\phi}(x,y_{loss}))] \} rϕmax{E(x,ywin,yloss)D[log σ(rϕ(x,ywin)rϕ(x,yloss))]}
  • PPO(Proximal Policy Optimization, 近端策略优化) m a x π θ { E x ∼ D , y ∼ π θ ( y ∣ x ) [ r ϕ ( x , y ) ] − β D K L [ π θ ( y ∣ x ) ∣ ∣ π r e f ( y ∣ x ) ] } \underset{\pi_{\theta}}{max} \{ E_{x \sim D,y \sim \pi_{\theta}(y|x)}[r_{\phi}(x,y)] - \beta D_{KL}[\pi_{\theta}(y|x) || \pi_{ref}(y|x)] \} πθmax{ExD,yπθ(yx)[rϕ(x,y)]βDKL[πθ(yx)∣∣πref(yx)]}
  • KL 散度(KL Divergence)

D K L [ π θ ( y ∣ x ) ∣ ∣ π r e f ( y ∣ x ) ] = π r e f ( y ∣ x )   l o g π r e f ( y ∣ x ) π θ ( y ∣ x ) = π r e f ( y ∣ x ) ( l o g π r e f ( y ∣ x ) − l o g π θ ( y ∣ x ) ) \begin{align} D_{KL}[\pi_{\theta}(y|x) || \pi_{ref}(y|x)] &= \pi_{ref}(y|x) \ log{\frac{\pi_{ref}(y|x)}{\pi_{\theta}(y|x)}} \\ &= \pi_{ref}(y|x) (log \pi_{ref}(y|x) - log\pi_{\theta}(y|x)) \end{align} DKL[πθ(yx)∣∣πref(yx)]=πref(yx) logπθ(yx)πref(yx)=πref(yx)(logπref(yx)logπθ(yx))

其中,Actor 和 Critic 损失函数如下:
a [ i , j ] = r e t u r n s [ i , j ] − v a l u e s [ i , j ] L o s s a c t o r = − 1 M N ∑ i = 1 M ∑ j = 1 N a [ i , j ] × e x p ( l o g _ p r o b [ i , j ] − o l d _ l o g _ p r o b [ i , j ] ) L o s s c r i t i c = 1 2 M N ∑ i = 1 M ∑ j = 1 N ( v a l u e s [ i , j ] − r e t u r n s [ i , j ] ) 2 L o s s = L o s s a c t o r + 0.1 ∗ L o s s c r i t i c \begin{align} a[i,j] &= returns[i,j] - values[i,j] \\ Loss_{actor} &= -\frac{1}{MN} \sum_{i=1}^{M} \sum_{j=1}^{N} a[i,j] \times exp(log\_prob[i,j]-old\_log\_prob[i,j]) \\ Loss_{critic} &= \frac{1}{2MN} \sum_{i=1}^{M} \sum_{j=1}^{N} (values[i,j] - returns[i,j])^{2} \\ Loss & = Loss_{actor} + 0.1*Loss_{critic} \end{align} a[i,j]LossactorLosscriticLoss=returns[i,j]values[i,j]=MN1i=1Mj=1Na[i,j]×exp(log_prob[i,j]old_log_prob[i,j])=2MN1i=1Mj=1N(values[i,j]returns[i,j])2=Lossactor+0.1Losscritic
PPO 的奖励(Reward 计算),一般而言,超参数 β = 0.1 \beta=0.1 β=0.1
r t = r ψ ( q , o ≤ t ) − β l o g ( π θ ( o t ∣ q , o < t ) π r e f ( o t ∣ q , o < t ) ) r_{t} = r_{\psi}(q,o_{\leq t}) - \beta log(\frac{\pi_{\theta}(o_{t}|q,o_{<t})}{\pi_{ref}(o_{t}|q,o_{<t})}) rt=rψ(q,ot)βlog(πref(otq,o<t)πθ(otq,o<t))
在 PPO 中使用的价值函数(Critic Model),通常与策略模型(Policy Model)大小相当,带来内存和计算负担。在强化学习训练中,价值函数作为基线,以减少优势函数计算中的方差。然而,在 大语言模型(LLM) 的场景中,只有最后一个 Token 被奖励模型赋予奖励分数,使训练一个在每个标记处都准确的价值函数,变得复杂。GRPO 无需像 PPO 那样,使用额外的近似价值函数,而是使用同一问题产生的多个采样输出的平均奖励,作为基线。

GRPO 使用基于 组相对(Group Relative) 的优势计算方式,与奖励模型比较特性一致,因为奖励模型通常是在同一问题上不同输出之间的比较数据集上进行训练的。同时,GRPO 没有在 奖励(Reward) 中加入 KL 惩罚,而是直接将训练策略与参考策略之间的KL散度添加到损失函数中,从而避免了在计算优势时增加复杂性。

GPRO 的公式, Q Q Q 表示 Query,即输入的问题,采样出问题 q q q,推理大模型,输出 G G G 个输出 o i o_{i} oi
J G R P O ( θ ) = E [ q ∼ P ( Q ) , { o i } i = 1 G ∼ π θ o l d ( O ∣ q ) ] L o s s = 1 G ∑ i = 1 G ( m i n ( ( π θ ( o i ∣ q ) π θ o l d ( o i ∣ q ) ) A i , c l i p ( π θ ( o i ∣ q ) π θ o l d ( o i ∣ q ) , 1 − ϵ , 1 + ϵ ) A i − β D K L ( π θ ∣ ∣ π r e f ) ) D K L ( π θ ∣ ∣ π r e f ) = π r e f ( o i ∣ q ) π θ ( o i ∣ q ) − l o g π r e f ( o i ∣ q ) π θ ( o i ∣ q ) − 1 A i = r i − m e a n ( { r 1 , r 2 , … , r G } ) s t d ( { r 1 , r 2 , … , r G } ) \begin{align} J_{GRPO}(\theta) &= \mathbb{E}[q \sim P(Q), \{{o_{i}}\}_{i=1}^{G} \sim \pi_{\theta_{old}}(O|q)] \\ Loss &= \frac{1}{G}\sum_{i=1}^{G}(min((\frac{\pi_{\theta}(o_{i}|q)}{\pi_{\theta_{old}}(o_{i}|q)})A_{i}, clip(\frac{\pi_{\theta}(o_{i}|q)}{\pi_{\theta_{old}}(o_{i}|q)},1-\epsilon,1+\epsilon)A_{i}-\beta \mathbb{D}_{KL}(\pi_{\theta}||\pi_{ref})) \\ \mathbb{D}_{KL}(\pi_{\theta}||\pi_{ref}) &= \frac{\pi_{ref}(o_{i}|q)}{\pi_{\theta}(o_{i}|q)} - log\frac{\pi_{ref}(o_{i}|q)}{\pi_{\theta}(o_{i}|q)} - 1 \\ A_{i} &= \frac{r_{i}-mean(\{r_{1},r_{2},\ldots,r_{G}\})}{std(\{r_{1},r_{2},\ldots,r_{G}\})} \end{align} JGRPO(θ)LossDKL(πθ∣∣πref)Ai=E[qP(Q),{oi}i=1Gπθold(Oq)]=G1i=1G(min((πθold(oiq)πθ(oiq))Ai,clip(πθold(oiq)πθ(oiq),1ϵ,1+ϵ)AiβDKL(πθ∣∣πref))=πθ(oiq)πref(oiq)logπθ(oiq)πref(oiq)1=std({r1,r2,,rG})rimean({r1,r2,,rG})
GRPO 的 KL 散度,使用蒙特卡洛(Monte-Carlo) 近似计算 KL散度(Kullback-Leibler Divergence),结果始终为正数。

参考源码,TRL - GRPO:

# Advantages
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)
# KL 散度
per_token_kl = torch.exp(ref_per_token_logps - per_token_logps) - (ref_per_token_logps - per_token_logps) - 1
# 期望
per_token_loss = torch.exp(per_token_logps - per_token_logps.detach()) * advantages.unsqueeze(1)
# 联合 loss
per_token_loss = -(per_token_loss - self.beta * per_token_kl)
# mask loss
loss = ((per_token_loss * completion_mask).sum(dim=1) / completion_mask.sum(dim=1)).mean()

GRPO 的 训练源码:trl/trainer/grpo_trainer.py

GRPO

PPO 的伪码流程:

policy_model = load_model()
ref_model = policy_model.copy()  # 不更新
critic_model = load_reward_model(only_last=False)
reward_model = critic_mode.copy()    # 不更新

for i in steps:
    # 1. 采样阶段
    prompts = sample_prompt()
    # old_log_probs[i][j](from policy_model), old_values[i][j](from critic_model)
    responses, old_log_probs, old_values = respond(policy_model, critic_model, prompts)
    
    # 2. 反馈阶段
    scores = reward_model(prompts, responses)
    # ref_log_probs[i][j](from ref_model)
    ref_log_probs = analyze_responses(ref_model, prompts, responses)  # ref logps
    # rewards[i][j] = scores[i] - (old_log_probs[i][j] - ref_log_prob[i][j])
    rewards = reward_func(scores, old_log_probs, ref_log_probs) # 奖励计算
    # advantages[i][j] = rewards[i][j] - old_values[i][j] 
    advantages = advantage_func(rewards, old_values)  # 奖励(r)-价值(v)=优势(a)
    
    # 3. 学习阶段
    for j in ppo_epochs:  # 多次更新学习,逐渐靠近奖励
        log_probs = analyze_responses(policy_model, prompts, responses)
        values = analyze_responses(critic_model, prompts, responses)
        
        # 更新 actor(policy) 模型,学习更新的差异,advantages[i][j]越大,强化动作
        actor_loss = actor_loss_func(advantages, old_log_probs, log_probs)  
        critic_loss = critic_loss_func(rewards, values)  # 更新 critic 模型
        
        loss = actor_loss + 0.1 * critic_loss   # 更新
        train(loss, policy_model.parameters(), critic_model.parameters())   # 参数

参考 知乎 - 图解大模型RLHF系列之:人人都能看懂的PPO原理与源码解读

KL 散度的实现,如下:

import torch
import torch.nn.functional as F
# 假设我们有两个概率分布 P 和 Q
P = torch.tensor([0.1, 0.2, 0.7])   # 参考的、真实的
Q = torch.tensor([0.2, 0.3, 0.5])   # 模型生成的
# 计算 Q 的对数概率
log_Q = torch.log(Q)
# 使用 PyTorch 的 kl_div 函数计算 KL 散度
kl_divergence = F.kl_div(log_Q, P, reduction='sum')  # 注意先Q后P
print(f"KL Div (PyTorch): {kl_divergence}")
log_P = torch.log(P)
kl_elementwise = P * (log_P - log_Q)
# 对所有元素求和,得到 KL 散度
kl_divergence = torch.sum(kl_elementwise)

参考:

  • 知乎 - GRPO: Group Relative Policy Optimization
  • GitHub - GRPO Trainer
  • Medium - The Math Behind DeepSeek: A Deep Dive into Group Relative Policy Optimization (GRPO)

相关文章:

  • 2025.2.10——1400
  • stm32电机驱动模块
  • python 基础知识100问
  • 第一章嵌入式系统概论考点02嵌入式系统的组成
  • ASP.NET Core 如何使用 C# 向端点发出 POST 请求
  • HTTP相关面试题
  • 利用MATLAB的linkaxes函数实现子图频率轴同步缩放
  • DateConverter does not support default String to ‘Date‘ conversion.
  • HARCT 2025 分论坛9:专用设备和机器人系统
  • WebGL 导入 OBJ 文件全解析
  • jenkins-获取当前时间戳
  • 买卖股票的最佳时机II(力扣122)
  • Python使用Flask结合DeepSeek开发
  • 2D 游戏艺术、动画和光照
  • Vue 2 — 配置请求转发
  • 【第5章:深度生成模型— 5.4 深度生成模型前沿全景:从Diffusion到多模态,揭秘AI生成技术的未来】
  • $ npx electron-forge import 一直报权限问题 resource busy or locked,
  • EasyRTC嵌入式WebRTC视频通话SDK支持Web浏览器、Linux、ARM、Android、iOS
  • win10右键使用IDEA打开
  • 日志2025.2.14
  • b2b网站的特点/怎么建网站卖东西
  • 教育培训的网站建设/app推广工作靠谱吗
  • 深喉咙企业网站生成系统/福建网络seo关键词优化教程
  • 主流网站/广告位招商怎么找客户
  • nba新闻那个网站做的好/网络运营推广
  • 秦皇岛网站开发费用/广州百度推广排名优化