open-r1,代码解析~

大模型机器学习数据库

仔细瞅瞅抱抱脸针对R1的开源复现代码。

背景

DeepSeek R1训练分为2个阶段。通过课程学习持续优化,第二阶段的数据部分来源于第一阶段。

第一阶段纯RL, 第二阶段 SFT + RLpicture.image

R1训练完成之后,通过蒸馏到小模型,可以让小模型获得非常好的推理性能,同时是优于使用小模型直接进行强化学习的。picture.image

OpenR1

蒸馏复刻,使用 R1 构造推理思维链数据,使用小模型SFT

picture.image

数据集来源包括中国高中数学练习、美国和国际数学奥林匹克竞赛问题。数据主要来自在线考试试卷 PDF 和数学讨论论坛。处理步骤包括(a)从原始 PDF 中进行 OCR,(b)分割成问题-解决方案对,(c)翻译成英语,(d)重新排列以产生 CoT 推理格式,以及(e)最终答案格式化。

构造思维链数据

picture.image

SFT训练

picture.image https://github.com/huggingface/transformers/blob/main/src/transformers/trainer\_pt\_utils.py#L554

transformers 默认针对生成式模型用到的是标签平滑的损失。

标签平滑, 将正确标签的设为1-epsilon,而其他标签平均分配epsilon的部分。

->

->

picture.image

GRPO

picture.image

Reward:

  1. 准确率

        
          
def accuracy_reward(completions, solution, **kwargs):  
    """Reward function that checks if the completion is the same as the ground truth."""  

      
  1. 大格式

        
          
def format_reward(completions, **kwargs):  
    """Reward function that checks if the completion has a specific format."""  
    pattern = r"^<think>.*?</think>\s*<answer>.*?</answer>$"  

      
  1. 逐步格式

        
          
def reasoning_steps_reward(completions, **kwargs):  
    r"""Reward function that checks for clear step-by-step reasoning.  
    Regex pattern:  
        Step \d+: - matches "Step 1:", "Step 2:", etc.  
        ^\d+\. - matches numbered lists like "1.", "2.", etc. at start of line  
        \n- - matches bullet points with hyphens  
        \n\* - matches bullet points with asterisks  
        First,|Second,|Next,|Finally, - matches transition words  
    """  
    pattern = r"(Step \d+:|^\d+\.|\n-|\n\*|First,|Second,|Next,|Finally,)"  

      
  1. 长度

        
          
    def cosine_scaled_reward(completions, solution, **kwargs):  
        """Reward function that scales based on completion length using a cosine schedule.  
  
        Shorter correct solutions are rewarded more than longer ones.  
        Longer incorrect solutions are penalized less than shorter ones.  

      
  1. 重复的ngram惩罚

        
          
def get_repetition_penalty_reward(ngram_size: int, max_penalty: float):  
    """  
    Computes N-gram repetition penalty as described in Appendix C.2 of https://arxiv.org/abs/2502.03373.  
    Reference implementation from: https://github.com/eddycmu/demystify-long-cot/blob/release/openrlhf/openrlhf/reward/repetition.py  

      

picture.image

https://github.com/huggingface/trl/blob/main/trl/trainer/grpo\_trainer.py#L459

  • 左边是:ratio * advantage(优势)
  • 右边是:KL散度

advantage 表示当前completion相对于组内平均水平的好坏,如果当前样本奖励大于组内(batch内)平均值,advantage > 0,否则小于0。

picture.image

  • 正值:比平均水平好
  • 负值:比平均水平差

ratio * advantage(优势)

  • 如果advantage > 0:增加该行为的概率
  • 如果advantage < 0:减少该行为的概率

初始 :模型A(优化模型) 模型B(Ref_model)

数据 D

模型A, 针对数据D, 得到一批生成结果 C, 这个可以用VLLM加速,因为生成是一个token一个token生成的,比较慢。

结果C可以用规则奖励函数算出Rewards, Rewards可以进一步算出advantages。

picture.image https://github.com/huggingface/trl/blob/main/trl/trainer/grpo\_trainer.py#L579

算损失

  1. KL散度,通过 模型A 和 参考模型B 在C上的概率分布的差异,在保持模型稳定性的同时,逐步改进生成策略。

picture.image https://github.com/huggingface/trl/blob/main/trl/trainer/grpo\_trainer.py#L643

  1. 根据Advantage,优化策略模型。

picture.image

正常做梯度传导,比如AC模型,格式长这样:

loss = (log_probs * advantages).mean() # 梯度:advantages * (1/log_probs)

trl的实现是:

per_token_loss = torch.exp(per_token_logps - per_token_logps.detach()) * advantages.unsqueeze(1) = (1 * advantages).mean()

per_token_logps - per_token_logps.detach() 数值是0,但是会将数值Advantage带来的优势传导到策略模型上,可以避免log_prob的数值不稳定?

大体上就这些,step3是sft+grpo,就是2步串联起来。

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
火山引擎边缘渲染的探索与实践 | 第 11 期边缘云主题Meetup
《火山引擎边缘渲染的探索与实践》黄旭能|火山引擎边缘渲染产品经理
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论