尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
解读 VeRL 框架源码:PPO 和 GRPO 算法如何计算优势 (Advantage)
最近正在入门大模型 RL 微调阅读 VeRL 框架代码。在这篇博客中我们从 VeRL 源码入手解读一下 ppo 和 grpo 算法的 advantage 计算方法# 来自 verl/trainer/ppo/core_algos.pyregister_adv_est(AdvantageEstimator.GAE)# or simply: register_adv_est(gae)defcompute_gae_advantage_return(token_level_rewards:torch.Tensor,values:torch.Tensor,response_mask:torch.Tensor,gamma:torch.Tensor,lam:torch.Tensor,):Adapted from https://github.com/huggingface/trl/blob/main/trl/trainer/ppo_trainer.py Args: token_level_rewards: (torch.Tensor) shape is (bs, response_length) values: (torch.Tensor) shape is (bs, response_length) response_mask: (torch.Tensor) shape is (bs, response_length). [EOS] mask. The token after [EOS] have mask zero. gamma is (float) discounted factor used in RL lam: (float) lambda value when computing Generalized Advantage Estimation (https://arxiv.org/abs/1506.02438) Returns: advantages: (torch.Tensor) shape: (bs, response_length) Returns: (torch.Tensor) shape: (bs, response_length) withtorch.no_grad():nextvalues0lastgaelam0advantages_reversed[]gen_lentoken_level_rewards.shape[-1]fortinreversed(range(gen_len)):deltatoken_level_rewards[:,t]gamma*nextvalues-values[:,t]lastgaelam_deltagamma*lam*lastgaelam# skip values and TD-error on observation tokensnextvaluesvalues[:,t]*response_mask[:,t](1-response_mask[:,t])*nextvalues lastgaelamlastgaelam_*response_mask[:,t](1-response_mask[:,t])*lastgaelam advantages_reversed.append(lastgaelam)advantagestorch.stack(advantages_reversed[::-1],dim1)returnsadvantagesvalues advantagesverl_F.masked_whiten(advantages,response_mask)returnadvantages,returns# NOTE(sgm): this implementation only consider outcome supervision, where the reward is a scalar.register_adv_est(AdvantageEstimator.GRPO)# or simply: register_adv_est(grpo)defcompute_grpo_outcome_advantage(token_level_rewards:torch.Tensor,response_mask:torch.Tensor,index:np.ndarray,epsilon:float1e-6,norm_adv_by_std_in_grpo:boolTrue,config:Optional[AlgoConfig]None,)-tuple[torch.Tensor,torch.Tensor]: Compute advantage for GRPO, operating only on Outcome reward (with only one scalar reward for each response). Args: token_level_rewards: (torch.Tensor) shape is (bs, response_length) response_mask: (torch.Tensor) shape is (bs, response_length) index: (np.ndarray) index array for grouping epsilon: (float) small value to avoid division by zero norm_adv_by_std_in_grpo: (bool) whether to scale the GRPO advantage config: (Optional[AlgoConfig]) algorithm configuration object Note: If norm_adv_by_std_in_grpo is True, the advantage is scaled by the std, as in the original GRPO. If False, the advantage is not scaled, as in Dr.GRPO (https://arxiv.org/abs/2503.20783). Returns: advantages: (torch.Tensor) shape is (bs, response_length) Returns: (torch.Tensor) shape is (bs, response_length) scorestoken_level_rewards.sum(dim-1)id2scoredefaultdict(list)id2mean{}id2std{}withtorch.no_grad():bszscores.shape[0]foriinrange(bsz):id2score[index[i]].append(scores[i])foridxinid2score:iflen(id2score[idx])1:id2mean[idx]torch.tensor(0.0)id2std[idx]torch.tensor(1.0)eliflen(id2score[idx])1:scores_tensortorch.stack(id2score[idx])id2mean[idx]torch.mean(scores_tensor)id2std[idx]torch.std(scores_tensor)else:raiseValueError(fno score in prompt index:{idx})foriinrange(bsz):ifnorm_adv_by_std_in_grpo:scores[i](scores[i]-id2mean[index[i]])/(id2std[index[i]]epsilon)else:scores[i]scores[i]-id2mean[index[i]]scoresscores.unsqueeze(-1)*response_maskreturnscores,scores以上的两段代码来自 VeRL 框架分别实现了PPO 中的 GAE广义优势估计和GRPO组相对策略优化的 advantage 计算方法。下面我们逐一解读并对比它们的设计思路。文章目录1 PPO GAE 优势计算 (compute_gae_advantage_return)1.1 函数签名1.2 核心逻辑GAE 原理2 GRPO 优势计算 (compute_grpo_outcome_advantage)2.1 函数签名2.2 核心逻辑GRPO 原理3 PPO(GAE) 与 GRPO 优势计算对比1 PPO GAE 优势计算 (compute_gae_advantage_return)1.1 函数签名defcompute_gae_advantage_return(token_level_rewards:torch.Tensor,values:torch.Tensor,response_mask:torch.Tensor,gamma:torch.Tensor,lam:torch.Tensor,):token_level_rewards: 形状(batch_size, response_length)每个 token 的即时奖励通常由奖励模型或规则给出。如果是 LLM 做数学题整个回答的 reward 可能只会给在最后一个 token。values: 形状与 reward 相同Critic 网络输出的每个 token 的状态价值估计。response_mask: 形状相同标记哪些 token 属于有效响应[EOS] 之后的 token 被 mask 掉值为0。gamma: 折扣因子控制未来奖励的重要性。lam: GAE 中的 λ 参数平衡偏差与方差。1.2 核心逻辑GAE 原理GAE 的递推公式为δ t r t γ ⋅ V ( s t 1 ) − V ( s t ) , A t δ t γ ⋅ λ ⋅ A t 1 δ_t r_t γ·V(s_{t1}) - V(s_t), \quad A_t δ_t γ·λ·A_{t1}δt​rt​γ⋅V(st1​)−V(st​),At​δt​γ⋅λ⋅At1​其中A t A_tAt​是优势V VV是价值函数。δ t Q ( s t , a t ) − V ( s t ) \delta_t Q(s_t, a_t) - V(s_t)δt​Q(st​,at​)−V(st​)而 advantage 的这种计算方法相当于不仅考虑当前时刻的 advantage还以 γ 的 discount factor 考虑未来的 advantage。代码中从最后一个 token 反向计算避免了显式循环的多次张量操作同时利用response_mask处理变长序列。nextvalues,lastgaelam0,0advantages_reversed[]gen_lentoken_level_rewards.shape[-1]fortinreversed(range(gen_len)):# 计算 TD 误差 deltadeltatoken_level_rewards[:,t]gamma*nextvalues-values[:,t]# 递推计算优势lastgaelam_deltagamma*lam*lastgaelam# 用 mask 控制哪些位置的 value 和 advantage 要传播nextvaluesvalues[:,t]*response_mask[:,t](1-response_mask[:,t])*nextvalues lastgaelamlastgaelam_*response_mask[:,t](1-response_mask[:,t])*lastgaelam advantages_reversed.append(lastgaelam)advantagestorch.stack(advantages_reversed[::-1],dim1)# 恢复正序returnsadvantagesvalues# 计算 returns (用于价值网络更新)advantagesverl_F.masked_whiten(advantages,response_mask)# 对有效 token 做白化标准化returnadvantages,returns关键点使用response_mask确保填充位置不参与计算也不传播梯度。masked_whiten对每个 batch 的有效 token 进行标准化均值 0方差 1有助于稳定训练。最终返回的advantages和returns形状均为(batch_size, response_length)。2 GRPO 优势计算 (compute_grpo_outcome_advantage)2.1 函数签名defcompute_grpo_outcome_advantage(token_level_rewards:torch.Tensor,response_mask:torch.Tensor,index:np.ndarray,epsilon:float1e-6,norm_adv_by_std_in_grpo:boolTrue,config:Optional[AlgoConfig]None,):token_level_rewards: 形状(batch_size, response_length)每个 token 的奖励。这里假设是结果监督outcome supervision即一个响应只对应一个标量奖励如正确/错误因此所有 token 的奖励和等于该响应的最终得分。response_mask: 同上标记有效 token。index: 形状(batch_size,)每个样本所属的组 ID例如同一个 prompt 的不同采样。GRPO 需要在组内进行标准化。norm_adv_by_std_in_grpo: 如果为 True则按原始 GRPO 方式除以标准差如果为 False则只减均值Dr.GRPO 风格。epsilon: 防止除零。2.2 核心逻辑GRPO 原理GRPO 不使用 Critic 网络而是用同一 prompt 下多个采样输出的平均奖励作为 baseline。advantage 就是组内标准化的奖励将 token 奖励求和得到每个 response 的标量得分scorestoken_level_rewards.sum(dim-1)# shape: (batch_size,)按 index 分组计算每个 group 的均值和标准差id2scoredefaultdict(list)foriinrange(bsz):id2score[index[i]].append(scores[i])foridxinid2score:scores_tensortorch.stack(id2score[idx])id2mean[idx]torch.mean(scores_tensor)id2std[idx]torch.std(scores_tensor)如果组内只有一个样本均值为 0标准差为 1避免除零。根据均值和标准差对每个得分进行标准化foriinrange(bsz):ifnorm_adv_by_std_in_grpo:scores[i](scores[i]-id2mean[index[i]])/(id2std[index[i]]epsilon)else:scores[i]scores[i]-id2mean[index[i]]标准化后每个组内的平均优势为 0可能方差为 1。每个 token 都被赋值为相同的标量 advantage非响应位置仍为 0scoresscores.unsqueeze(-1)*response_mask# shape: (bs, response_length)returnscores,scores# 这里 returns 和 advantages 相同GRPO 不更新价值网络关键点GRPO 完全抛弃了价值网络baseline 来自同组的其他样本避免了训练 Critic 的开销和不稳定性。标准化操作可以在组内消除奖励尺度差异使策略更新更稳健。返回的两个张量相同因为 GRPO 没有独立的 returns 概念一般直接使用优势更新策略。3 PPO(GAE) 与 GRPO 优势计算对比维度PPO GAEGRPObaseline 来源Critic 网络估计的状态值V ( s t ) V(s_t)V(st​)同一 prompt 下多个样本的平均奖励优势形式每个时间步t tt都有一个 advantageA t A_tAt​整个响应共用一个标量 advantage广播到每个 token是否需要价值网络是否处理变长序列通过 mask 控制逐 token 计算汇总为标量后广播mask 仅用于置零计算复杂度较高需维护价值网络并做反向传播较低仅需组内统计适用场景一般 RLHF需要细粒度信用分配结果监督任务如数学推理、代码生成可节省资源总结PPO-GAE代码是标准的 GAE 实现考虑了 mask 和最终的 whitening适用于需要 Critic 的在线策略优化。GRPO代码则利用了结果监督和分组归一化的思想简化了优势计算适合大模型微调中每个响应只有一个标量奖励的场景如 RLHF 中的“正确/错误”信号。这两段代码清晰体现了两种算法在设计哲学上的差异PPO 追求细粒度时序信用分配而 GRPO 通过组内比较降低方差并简化实现。
RELATED

相关推荐

轻量级 jQuery 折叠插件 jQuery-Collapse:3 分钟读懂内容渐进式披露的终极方案

轻量级 jQuery 折叠插件 jQuery-Collapse:3 分钟读懂内容渐进式披露的终极方案

【免费下载链接】jQuery-Collapse A lightweight (~1kb) jQuery plugin that enables expanding and collapsing content 项目地址: https://gitcode.com/gh_mirrors/jq/jQuery-Collapse 点击查看 免费下载 网页内容太多时,直接全部展示会让用户感到 ov…

📅 2026/11/5 1:30:57
C++将字符串转换为整数和浮点数的几种方法

C++将字符串转换为整数和浮点数的几种方法

1. 常见的字符串转整数方法1.1 atoi()atoi 是C语言中最简单、最基础的字符串转整数函数。它接受一个字符串并返回对应的整数值。1int atoi(const char *str);优点:简单易用,适合处理非常基础的字符串转整数操作。缺点:没有错误处理机制。如果…

📅 2026/11/5 1:30:57
OpenCreator:Codex 内核的开源 AI 创作工作台

OpenCreator:Codex 内核的开源 AI 创作工作台

OpenCreator:Codex 内核的开源 AI 创作工作台 【免费下载链接】OpenCreator Formerly KrillinAI, VideoTranslation and Dubbing Tool for 120 Languages. Open-source AI workspace for creators, powered by Codex. Video downloader, video translation, create …

📅 2026/11/5 1:25:57
MORE NEWS

更多资讯

📰

2025年Data Agent技术演进与行业应用解析

1. 榜单背景与行业价值2025年中国大数据产业正经历从规模扩张向价值深挖的关键转型期。Data Agent(数据智能体)作为融合大模型与垂直场景的新范式,正在重构企业数据应用的基础架构。金猿奖作为国内大数据领域最具公信力的行业奖项之一&#x…

📰

有感FOC三环实现:时序分层、PI整定与轨迹规划

简介:面向电机控制与嵌入式开发学习者的有感FOC位置、速度与电流三环算法实现资料,围绕坐标变换、PID调节、SVPWM调制、编码器反馈与电流采样等关键环节展开,代码在STM32F4平台上运行,适合希望理解有感控制链路、搭建实验样机或对…

📰

STM32 FATFS SD卡读写:diskio、扇区寻址与写同步避坑

简介:面向嵌入式学习者与需在STM32上实现存储读写的开发者,这份资料展示KEIL环境下通过SPI或SDIO驱动SD卡并挂载FATFS的完整思路,涉及引脚配置、扇区读写、FATFS裁剪及f_open、f_read等文件操作,也包含未检测到卡、文件不存在、读…

📰

AI时代工程师转型:从编码到架构设计的技能升级

1. 从代码编写到架构设计:AI如何重塑工程师角色十年前我刚入行时,工程师的核心竞争力是能写出高效可靠的代码。现在打开GitHub Copilot,它能在几秒内生成比我当年更规范的函数实现。上周团队新来的应届生用GPT-4重构了我们的日志模块&#xf…

📰

基于DWVD与MCNN的机械故障诊断方法研究

1. 项目概述这个项目提出了一种创新的机械故障诊断方法,将时频分析领域的离散韦格纳分布(DWVD)与深度学习中的多尺度卷积神经网络(MCNN)相结合。作为一名长期从事机械状态监测的工程师,我深知传统故障诊断方…

📰

GEC2410 WinCE底层实验包:手册与源码对照实战指南

简介:这份资源面向嵌入式系统初学者与进阶开发者,围绕三星S3C2410(ARM920T内核)硬件平台与Windows CE系统的集成开发展开,提供实验手册与配套源码,帮助读者理解从系统架构、硬件接口到驱动与应用程序开发的…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬