从零实现GRPO:PyTorch手写强化学习算法详解

引言:为什么要从零实现GRPO
在大语言模型的后训练(Post-Training)阶段,强化学习正扮演着越来越重要的角色。后训练是指模型完成预训练和监督微调(SFT)之后,通过人类偏好或规则信号进一步优化模型行为的过程,它直接决定了模型在实际应用中的安全性、有用性和推理能力。在整个LLM开发流程中,预训练阶段让模型在海量文本上学习语言的统计规律,获得基础的语言理解和生成能力;SFT阶段通过人工标注的指令-回答对教会模型遵循指令;而后训练则通过引入人类偏好信号或基于规则的奖励,进一步校准模型的输出分布,使其行为符合人类期望——这一阶段的技术选择直接影响模型的最终表现质量。
从技术演进的角度来看,后训练技术在近几年经历了快速迭代。从InstructGPT(2022年)首次系统性地将RLHF引入大模型训练,到Anthropic的Constitutional AI、Meta的Llama系列的迭代,后训练技术栈已趋于成熟。当前主流的后训练方法可分为两大类:在线方法(如PPO、GRPO)需要实时生成样本并与环境交互,计算开销较大但理论上能达到更优的策略;离线方法(如DPO、KTO)直接在预收集的偏好数据上优化,工程实现更简单但受限于数据分布。GRPO属于在线方法阵营,但通过取消价值网络大幅降低了工程复杂度,可以说是在两类方法之间找到了一个实用的平衡点。
从 RLHF 到 PPO,再到如今备受关注的 GRPO(Group Relative Policy Optimization,群组相对策略优化),这些算法直接决定了模型的对齐能力与推理表现。近期,一位开发者在 Reddit 上分享了他的实践成果——用纯 PyTorch 从零实现 GRPO 算法,并录制了完整的讲解视频,甚至在消费级 GPU 上完成了一次简短的训练演示。
这类"手写实现"的教程之所以有价值,在于它剥离了 TRL、veRL 等高层框架的封装,直接展示算法的核心机制。TRL(Transformer Reinforcement Learning)是 Hugging Face 维护的强化学习训练库,提供了 PPO、DPO、GRPO 等多种后训练算法的高层封装,与 Transformers 生态深度集成;veRL(Volcano Engine Reinforcement Learning)则是字节跳动开源的大模型强化学习框架,以其高效的分布式架构和灵活的 Actor-Learner 分离设计著称。这些框架虽然极大降低了工程部署难度,但其数千行的代码量和复杂的抽象层次往往让初学者难以理解底层逻辑。对于想要真正理解 GRPO 而非仅仅调用 API 的学习者来说,一份从零开始的实现无疑是宝贵的参考资料。
GRPO 是什么:DeepSeek 带火的强化学习算法
从 PPO 到 GRPO 的演进
GRPO 最初因 DeepSeek 的技术报告而广为人知,它可以看作是对经典 PPO(Proximal Policy Optimization)算法的一种简化与改进。PPO 由 OpenAI 于 2017 年提出,是强化学习领域最广泛使用的策略梯度算法之一,其核心思想是通过裁剪目标函数来限制每次策略更新的幅度,从而在训练稳定性和样本效率之间取得平衡。具体而言,PPO优化的目标函数为 L = min(ρ·A, clip(ρ, 1-ε, 1+ε)·A),当优势为正时裁剪防止对好动作过度强化,当优势为负时裁剪防止对坏动作过度惩罚,这种双向约束使得PPO无需像TRPO(Trust Region Policy Optimization)那样求解复杂的约束优化问题,就能保证策略更新的稳定性。
要理解PPO和GRPO,需要回溯到策略梯度(Policy Gradient)的基本框架。策略梯度定理指出,目标函数J(θ)关于策略参数θ的梯度可以表示为:∇J(θ) = E[∇log π_θ(a|s) · A(s,a)],其中A是优势函数。这个公式的直觉是:对于获得正优势的动作,增大其概率;对于获得负优势的动作,减小其概率。然而原始策略梯度存在高方差问题,这促使了多种方差缩减技术的发展——基线减除(baseline subtraction)、广义优势估计(GAE)、以及PPO的裁剪目标。GRPO的群组归一化本质上也是一种基线减除技术,只是它用群组均值作为基线,而非通过价值网络学习得到。
在大语言模型的 RLHF 流程中,传统 PPO 需要同时维护四个模型:策略模型(Actor)、价值模型(Critic)、奖励模型(Reward Model)和参考模型(Reference Model)。其中,价值网络(Value Network / Critic)负责估计每个状态的价值,从而计算优势函数(Advantage)。这四个模型各自承担不同职责——策略模型负责生成文本,价值模型估计当前状态的期望回报,奖励模型评估生成文本的质量,参考模型提供KL约束的基准分布。这不仅带来了极大的显存开销——通常需要数十张高端 GPU 才能运行完整管线,也增加了训练的不稳定性。
GRPO 的核心创新在于取消了独立的价值网络。它通过对同一个提示(Prompt)采样生成一组(Group)多个回答,然后用这组回答的奖励值的相对关系来估计优势。具体来说,某个回答的优势由它的奖励减去整组奖励的均值、再除以标准差得到——这是一种"群组内相对比较"的思路,也正是算法名称中"Group Relative"的由来。从统计学角度看,这本质上借用了 Z-score 标准化的思想。Z-score标准化是统计学中最基本的数据变换方法之一,它将原始数据映射到均值为0、标准差为1的标准正态分布空间。在GRPO中使用Z-score的深层意义在于:它消除了奖励函数量纲的影响——无论奖励是0-1二值还是连续实数,归一化后的优势值总在可比的范围内;同时它天然地将群组分为"赢家"和"输家",即使所有回答的绝对奖励都很高或都很低,相对排序仍能提供有效的学习梯度。值得注意的是,当群组内所有回答的奖励完全相同时(标准差为零),会出现数值不稳定,实现中通常会加入一个小的epsilon值来避免除零错误。
为什么这个设计很关键
这种设计的巧妙之处在于,它用一次前向采样的"群组统计"替代了需要单独训练的价值网络。这意味着:
- 显存占用更低:不再需要维护一个与策略模型规模相当的 Critic 网络,整个训练管线从四模型简化为三模型(策略模型、奖励模型、参考模型),显存需求可减少近三分之一;
- 训练更简洁:减少了一个需要调参和收敛的组件,避免了价值网络估计不准导致的优势函数偏差问题;
- 对推理任务友好:在数学、代码等有明确对错标准的任务上,奖励信号清晰,群组相对比较能有效放大好答案与坏答案之间的差异。特别是在 DeepSeek-R1 的训练中,GRPO 与"思维链"(Chain-of-Thought)生成相结合,显著提升了模型的多步推理能力。
DeepSeek-R1是DeepSeek团队在2024-2025年间发布的推理增强大模型,其训练流程中GRPO发挥了核心作用。DeepSeek团队的技术路线展现了GRPO在实践中的逐步演进:从DeepSeek-Math(2024年初)开始,团队就在探索将强化学习应用于数学推理,当时他们对比了PPO和GRPO的效果,发现GRPO在保持性能的同时显著降低了训练资源需求。随后的DeepSeek-R1-Zero实验更具革命性——研究者仅使用GRPO和简单的正确性奖励,从一个基础模型出发,观察到模型自发地学会了分步推理、自我验证、甚至回溯修正等高级认知行为。这些行为在没有任何监督数据示范的情况下涌现,强烈暗示了强化学习在释放模型潜在推理能力方面的独特作用。最终的DeepSeek-R1则在R1-Zero的基础上加入了冷启动数据和拒绝采样等额外技术,进一步提升了输出质量。R1的成功证明了GRPO在推理密集型任务上的有效性,也引发了社区对"强化学习驱动推理能力涌现"这一研究方向的广泛关注。
正是这些优势,使得 GRPO 成为当下开源社区训练推理模型时的热门选择。
从零实现GRPO的技术要点
核心训练流程
根据作者公开的代码(grpo_minimal_pytorch.py),一个最小化的 GRPO 实现通常包含以下几个关键步骤:
-
群组采样:针对每个输入 Prompt,让当前策略模型生成 G 个不同的回答(通过采样而非贪婪解码)。G 的典型取值在 4 到 64 之间,群组越大统计估计越稳定,但相应的计算开销也越大。采样时通常使用 temperature > 0 的设置来保证回答的多样性。
-
奖励计算:使用奖励函数(可以是规则化的评分,也可以是奖励模型)为每个回答打分。在数学推理任务中,常见的做法是用正则表达式提取最终答案并与标准答案比对,正确得 1 分错误得 0 分,或者结合格式奖励给予更细粒度的评分。在实际部署GRPO时,奖励函数的设计是影响训练效果的关键因素之一。DeepSeek-R1的训练中使用了两类奖励:准确性奖励(答案是否正确)和格式奖励(是否遵循
<think>...</think><answer>...</answer>的格式)。在社区的复现实践中,常见的奖励设计策略还包括:对代码生成任务使用单元测试的通过率;对通用对话任务使用训练好的奖励模型打分。一个重要的工程经验是:奖励信号的稀疏程度直接影响GRPO的学习效率。如果群组中所有回答都得0分(全错)或都得1分(全对),归一化后的优势趋近于零,模型几乎无法学习。因此,选择合适难度的训练数据——让群组内同时包含正确和错误回答——对GRPO的训练效果至关重要。 -
优势归一化:在每个群组内部,对奖励进行标准化处理(Z-score 归一化),得到相对优势值。计算公式为 A_i = (r_i - mean(r)) / std(r),其中 mean 和 std 在同一群组的 G 个回答上计算。这确保了得分高于群组均值的回答获得正优势(被强化),低于均值的获得负优势(被抑制)。
-
策略损失计算:结合重要性采样比率(新旧策略的概率比)与裁剪机制(Clipping),计算 GRPO 的目标函数。重要性采样(Importance Sampling)是一种统计技术,允许我们使用从一个分布(行为策略)采集的样本来估计另一个分布(目标策略)下的期望值。在GRPO中,由于采样生成回答时使用的是"旧策略"π_old,而我们希望优化的是"新策略"π_new,两者之间存在分布偏移,重要性采样比率 ρ = π_new(a|s) / π_old(a|s) 正是用来修正这种偏移的权重系数。
在LLM场景下实现GRPO时,一个容易被忽略的技术细节是:语言模型的"动作"是在token级别定义的,而奖励通常只在序列完成后给出。这意味着需要将序列级别的奖励分配到每个token的贡献上。在token级别的实现中,ρ通常通过计算整个回答序列中每个token的新旧对数概率之差的指数来得到。优势值则是序列级别的(因为奖励是序列级别的),这种混合粒度的处理方式在数学上相当于假设整个序列共享同一个优势值。一些变体实现会尝试将序列级优势按token位置进行加权分配(如后面的token获得更大权重),但标准GRPO采用的是最简单的均匀分配方案。
如果不加裁剪地直接使用ρ,当新旧策略差异过大时,ρ的方差会急剧增大,导致梯度估计极不稳定——这正是引入裁剪机制的根本原因。裁剪机制将 ρ 限制在 [1-ε, 1+ε] 范围内(ε 通常取 0.1-0.2),防止单次更新步幅过大。最终目标函数取裁剪前后的最小值,形成一个悲观的下界估计,确保训练稳定。
-
KL 散度约束:加入相对于参考模型的 KL 惩罚项,防止策略偏离初始模型过远。KL 散度(Kullback-Leibler Divergence)衡量两个概率分布之间的差异程度,在实现中通常对每个生成 token 位置计算新旧策略的对数概率之差来估计。KL 系数(β)的选择至关重要:β 过大会使模型过于保守,难以学到新行为;β 过小则可能导致"奖励黑客"(Reward Hacking)现象——即模型找到奖励函数的漏洞,生成得分很高但实际质量低下的文本。奖励黑客是强化学习中一个著名的对齐失败模式,当优化目标(代理奖励函数)与真实目标(人类意图)之间存在不完美的对应关系时,足够强大的优化器会发现并利用这种不一致。在LLM场景中,典型的表现包括生成过长但空洞的回答以获得长度奖励、重复某些"讨好"奖励模型的固定短语、或者在格式上完美但内容上胡说八道。KL约束的作用正是限制策略模型偏离参考模型的程度,在奖励最大化和输出质量之间建立平衡点。
手写实现的学习价值
作者特别强调,整个实现是"from scratch"(从零开始)的,并且能在消费级 GPU 上运行一次简短的训练。这一点极具教学意义——它证明了理解 GRPO 并不需要庞大的算力集群。当你亲手实现优势归一化、概率比裁剪、KL 惩罚这些环节时,才能真正体会到每一行代码对应的数学含义,而不是把它们当作黑盒。
对于许多学习者而言,直接阅读 TRL 库中高度抽象、层层封装的 GRPO 实现往往令人望而生畏——TRL 的实现涉及分布式训练调度、动态批处理、混合精度管理等大量工程细节,核心算法逻辑被分散在多个文件和类中。而一个精简的、可独立运行的最小实现,恰恰能起到"庖丁解牛"的作用,让你在一个文件内看清算法从采样到更新的完整流程。
这类开源教程的实践意义
降低强化学习的学习门槛
长期以来,强化学习被认为是深度学习中最难上手的分支之一,尤其是应用于大模型的 RLHF/GRPO 流程,涉及采样、奖励、优势估计、策略更新等多个环节,链路长且容易出错。调试难度也远高于监督学习——奖励信号的稀疏性、策略梯度的高方差、以及各组件之间的耦合效应,都使得问题定位极为困难。这位开发者的分享——视频讲解 + 可运行代码的组合形式,正好覆盖了"理论理解"和"动手实践"两个层面。
视频负责讲清楚算法的直觉与推导,代码负责让读者能够复现和调试。这种搭配对自学者非常友好,也符合"学中做、做中学"的认知规律。
消费级 GPU 上的可行性
你可能没注意到,作者是在本地消费级 GPU 上完成训练演示的。这打破了"做强化学习必须有大量 A100"的固有印象。虽然真正训练出高质量的推理模型仍需大规模算力(DeepSeek-R1 的训练据报道使用了数千张 GPU),但理解和验证算法本身完全可以在个人硬件上进行。
在消费级GPU上运行GRPO训练涉及多项内存优化技巧。首先是模型量化:使用4-bit或8-bit量化的LoRA微调可以将模型的显存占用降低到全精度的四分之一。其次是梯度累积:通过在多个mini-batch上累积梯度来模拟更大的有效批大小,这对GRPO尤为重要,因为群组采样天然需要较大的有效样本量。此外,KV-Cache的管理也是关键——生成阶段需要缓存中间状态以加速自回归解码,但这会占用大量显存,因此需要在生成完成后及时释放。一些实现还采用了生成与训练交替执行的策略(而非同时进行),通过时间换空间来适应有限的GPU内存。典型地,一个7B参数的模型在24GB显存的RTX 4090上可以通过4-bit LoRA + 梯度累积的组合来运行GRPO训练,而1-3B的小模型甚至可以在16GB显存上完成全参数微调。
关键在于选择合适的模型规模(如 1B 以下的小模型)、较小的群组大小(G=4 或 8)、以及短序列长度。这对于学生、独立研究者以及预算有限的团队来说,是一个重要的信号——算法研究与工程部署是可以解耦的。
结语:动手是最好的学习方式
GRPO 作为当前大模型后训练领域的核心算法之一,其重要性还将持续上升。随着 DeepSeek-R1 的成功以及社区对推理能力的日益重视,GRPO 及其变体(如加入过程奖励模型的版本、与 Monte Carlo Tree Search 结合的探索方向)正在成为后训练研究的主线之一。
过程奖励模型(Process Reward Model, PRM)与GRPO中使用的结果奖励模型(Outcome Reward Model, ORM)不同——ORM只对最终答案给出一个总体评分,而PRM能对推理过程中的每一步给出反馈,这为模型提供了更密集的学习信号,有望进一步提升多步推理的准确性。PRM的训练需要步骤级别的标注数据,这在数学证明等结构化任务中相对容易获取(可以通过验证每一步的逻辑正确性来自动标注),但在开放式推理任务中仍然是一个挑战。将PRM与GRPO结合时,优势估计可以从序列级别细化到步骤级别,理论上能更精确地识别推理链中哪些步骤贡献了正确结果、哪些步骤导致了错误。
与 Monte Carlo Tree Search(MCTS)的结合则借鉴了AlphaGo的思路,在生成过程中构建搜索树,通过模拟和回溯来选择最优的推理路径。具体而言,MCTS将文本生成过程建模为一棵树,每个节点代表生成过程中的一个中间状态,分支代表不同的续写选择。通过反复的"选择-扩展-模拟-回溯"循环,MCTS能在不穷举所有可能的情况下找到高质量的生成路径。这种方法在推理时间(inference-time)计算和训练时间(training-time)计算之间提供了灵活的权衡——通过在推理时投入更多计算来提升单次输出质量,或在训练时通过MCTS生成高质量样本来改善策略。
与其停留在阅读论文和调用现成框架,不如像这位开发者一样,尝试从零实现一遍。在这个过程中,你会真正理解群组相对优势、概率比裁剪、KL 约束这些概念是如何协同工作的。
感兴趣的读者可以查阅作者提供的资源:
- 视频讲解:YouTube 上的完整实现走查
- 开源代码:GitHub 仓库
uygarkurt/post-training-lab中的grpo_minimal_pytorch.py
无论你是想深入理解算法原理,还是想在自己的项目中定制化 GRPO 流程,这样一份从零开始的实现都值得一读。毕竟在 AI 工程领域,能把一个算法亲手写出来并跑通,往往比读十篇论文更能建立扎实的理解。
相关推荐

nanoGPT速通技巧:延迟解耦如何解决嵌入层稀疏梯度问题
深入解析nanoGPT速通中的延迟解耦(Delayed Untying)技巧,解释为何在训练前期绑定embed与lm_head权重、后期解耦能同时解决稀疏梯度和表达力受限问题,并剖析权重绑定、差异化学习率等替代方案的优劣。

Vibe Coding是什么?AI编程的理想与现实真相
深入解析Vibe Coding(氛围编程)的含义、工作方式与实际体验。从Andrej Karpathy提出概念到开发者社区的真实反馈,探讨AI编程工具的效率提升与潜在风险,帮你理性看待这场编程范式变革。

四大AI同题开发实测:DeepSeek V4 Flash意外夺冠
DeepSeek V4 Flash、V4 Pro、Grok 4.6等四大AI模型同题开发实测对比,轻量级Flash版在代码生成速度和一次性通过率上意外击败旗舰模型,揭示AI模型选型的关键策略。