尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

大模型后训练与可验证强化学习RLVR:从原理到工程实践指南

大模型后训练与可验证强化学习RLVR:从原理到工程实践指南 如果你最近在关注大模型训练链路可能会发现一个明显变化预训练已经不是讨论的焦点大家更关心“模型预训练之后到底怎么调”。无论是开源模型微调、领域模型定制还是推理模型Reasoning Model的打造后训练都是绕不开的核心环节。斯坦福大模型开发课 EP16 正好围绕这个主题展开重点讲解了后训练的整体框架以及近一年来非常火的可验证强化学习Reinforcement Learning with Verifiable Rewards简称 RLVR。这篇文章不是课程字幕的搬运而是结合工程实践经验把后训练和 RLVR 的原理、奖励设计、策略优化、训练代码、常见问题完整拆解一遍。适合三类读者一是想系统理解大模型后训练流程的算法工程师二是准备把开源模型微调成领域模型的开发同学三是对 RLHF、DPO、GRPO 这些概念有点了解但还没亲手跑过强化学习训练的人。读完这篇文章你会掌握以下内容后训练各阶段SFT、偏好对齐、RLVR分别解决什么问题RLVR 相比传统 RLHF 的核心优势是什么如何设计一个稳定、防 hack 的可验证奖励函数PPO 与 GRPO 的差异以及如何写一个最小的 RLVR 训练循环并排查训练中的常见问题。1. 背景与核心概念1.1 什么是大模型后训练预训练阶段模型在海量文本上学习语言规律目标是预测下一个 token。这个阶段结束后模型确实具备很强的语言能力但它并不天然知道“用户问一句模型应该怎么组织答案”也不擅长严格推理、格式输出、代码执行这类任务。后训练Post-training就是对预训练模型进行进一步监督和引导的过程。常见的后训练手段包括SFTSupervised Fine-Tuning监督微调用人工标注或强模型生成的数据教模型学会指令遵循和答案格式。偏好对齐Preference Alignment通过 DPO、RLHF 等方法让模型输出更符合人类偏好。RLVR可验证强化学习用外部可验证的奖励信号如代码是否通过测试、数学答案是否正确指导模型强化推理能力。为什么要后训练最直接的原因是预训练模型的语言概率分布不等于用户需要的任务分布。用户不会只让模型“接话”而是要求“回答问题”“写代码”“做数学题”“输出 JSON”。这些行为需要后训练来激发。最近很多团队发现开源模型能力差距的关键往往不在预训练而在后训练。尤其是推理模型的打磨几乎完全依赖后训练阶段的高质量数据和强化学习策略。1.2 从 RLHF 到 RLVR传统 RLHF基于人类反馈的强化学习通常需要三个模型Actor 策略模型、Critic 价值模型、Reward Model 奖励模型。奖励模型从人类偏好标注中学习“什么样的回答更好”然后给 Actor 提供奖励信号。这套框架在对话质量、内容安全性等主观任务上非常有效但它有一个明显问题奖励模型是学习出来的它并不完美。奖励模型可能会有以下缺陷过拟合奖励模型只见过训练分布内的数据对分布外样本的判断不可靠。容易被钻空子模型很快会发现哪些表达方式能拿到高分产生“奖励黑客”Reward Hacking现象。训练开销大训练一个可靠的奖励模型本身需要大量人工标注偏好数据。不适用于可验证任务在数学题、代码生成、SQL 执行这类任务中答案对错是确定的。用模型打分不但多余反而会引入模糊性和噪声。于是RLVR 出现了。1.3 RLVR 是什么RLVR 全称 Reinforcement Learning with Verifiable Rewards也就是“可验证奖励强化学习”。它的核心思想很简单如果任务的正确性可以被外部规则自动验证那就直接用验证结果作为奖励而不是训练一个奖励模型。典型的可验证任务包括任务类型验证方式示例数学解答答案比对模型输出与标准答案归一化后比较代码生成编译 单元测试生成的代码在沙箱中运行跑测试用例结构化输出格式解析JSON 是否合法、是否包含answer标签SQL 查询执行结果比对生成的 SQL 在测试库执行对比结果集逻辑推理规则校验推导步骤中的关键条件是否满足RLVR 的最大优势是奖励信号来自确定性规则而不是另一个模型的“主观判断”。这意味着奖励更稳定、更可解释也不容易被模型试探出漏洞。代表性案例是 DeepSeekMath 和 DeepSeek-R1。DeepSeekMath 使用 GRPO 算法配合规则奖励显著提升了数学推理能力DeepSeek-R1 则通过大规模 RLVR 训练让模型在推理任务上表现出极强的长链式思考Chain of Thought能力。可以说RLVR 已经成为当前推理模型训练的重要方向。2. 环境准备与工具链在动手写 RLVR 训练代码之前先把环境整理清楚。RLVR 训练和普通 SFT 不一样它需要在一个训练循环里同时做“采样生成”和“策略更新”对显存、采样速度、工程链路都有要求。2.1 硬件与算力如果你只是做概念验证可以用较小模型1B-3B 参数在单卡 A100/H100 80G 上运行。但要复现真实效果通常需要至少 4-8 张 A100/H100 80G 显卡。采样阶段建议配合 vLLM 加速推理否则生成会成为效率瓶颈。存储方面预留 checkpoint、采样缓存和日志空间。如果是个人开发机没有多卡集群也不要灰心。可以先做小规模实验比如用 1.5B 模型、减少生成条数、缩短最大生成长度在单卡上把训练循环跑通再迁移到大规模集群。2.2 软件依赖RLVR 训练主要依赖 PyTorch、Transformers、TRL 库。TRL 库在较新版本中已经内置了GRPOTrainer可以直接复用。除了这些还需要 vLLM 或类似推理加速工具来加速采样。下面是一个参考requirements.txttorch2.1 transformers4.38 trl0.12 datasets2.16 accelerate0.27 deepspeed0.14 vllm0.4 huggingface_hub0.20 safetensors0.4注意版本号需要根据你的项目实际情况调整。TRL 的 API 更新比较频繁不同版本的GRPOTrainer参数和 reward function 签名会有差异。如果后续代码报错优先检查 TRL 版本对应的官方文档。2.3 示例项目结构为了让整个流程更清晰建议按下面的目录结构组织项目rlvr-demo/ ├── config/ │ └── rlvr_config.yaml ├── data/ │ ├── train.jsonl │ └── eval.jsonl ├── rewards/ │ └── math_reward.py ├── scripts/ │ └── train_rlvr.py ├── outputs/ │ ├── checkpoints/ │ └── logs/ └── README.md这样拆分的好处是奖励函数、训练脚本、配置文件相互独立后期替换模型、更换数据集、调整奖励策略都很方便。3. RLVR 原理拆解这一节是文章的核心。只有理解了 RLVR 的完整训练循环、奖励设计原则和策略优化算法你才能在实际训练中定位问题。3.1 整体训练循环RLVR 的训练循环可以拆成四个阶段Sampling采样对每个 prompt 生成一组回答。Rewarding奖励计算用规则验证器给每组回答打分。Advantage Estimation优势估计计算每个回答相对组内平均水平的优势。Policy Update策略更新用强化学习目标更新 Actor 模型并约束 KL 散度。可以理解为prompt → 多条采样 → 规则验证 → 相对奖励 → 策略梯度更新 → 下一轮为什么每次要生成多条回答因为单个回答的奖励波动很大无法判断“这次提升”是策略变好还是运气因素。通过组内比较模型能学到“什么样的回答比当前平均更好”训练信号更稳定。3.2 可验证奖励设计奖励设计是 RLVR 的关键。奖励函数的好坏直接决定训练能否收敛。可验证奖励并不等于“简单判断对错”。实操中奖励通常拆成维度格式奖励回答是否包含指定标签如answer、boxed{...}。正确性奖励最终答案是否与标准答案一致。过程奖励推理步骤是否完整或者逐步校验关键结论。格式奖励不能单独使用否则模型会退化成“只写格式不写内容”。正确性奖励则需要配合好的验证器避免字符串比较带来的误判。来看一个数学答案奖励函数的示例# 文件路径rewards/math_reward.py import re def normalize_answer(text: str) - str: 对答案做归一化减少格式带来的误判。 text text.strip() # 去掉 boxed 标记 text re.sub(r\\boxed\{([^}]*)\}, r\1, text) # 去掉空格 text re.sub(r\s, , text) # 统一小数和分数格式这里仅做简化 return text def extract_answer(completion: str) - str: 从生成结果中提取 answer 标签内的内容。 pattern ranswer(.*?)/answer matches re.findall(pattern, completion, re.S) if matches: return matches[-1].strip() return def math_reward(prompts, completions, answers, **kwargs): rewards [] for completion, standard_answer in zip(completions, answers): extracted extract_answer(completion) if not extracted: rewards.append(0.0) continue if normalize_answer(extracted) normalize_answer(standard_answer): rewards.append(1.0) else: rewards.append(0.0) return rewards这段代码的要点用正则提取answer标签避免到处找答案。对答案做归一化去掉空格和\boxed{}标记。比较时用归一化后的结果而不是原始字符串。实际项目中你还需要处理分数和小数等价、正负号、百分号等边界情况。验证器越鲁棒奖励信号越干净模型就越不容易钻空子。3.3 策略优化从 PPO 到 GRPORLVR 常见的优化算法有两种PPO 和 GRPO。PPOProximal Policy Optimization是 RLHF 的经典选择。它同时维护 Actor 模型、Critic 价值模型和奖励模型用 GAE 计算优势。Critic 模型负责评估当前策略的状态价值帮助降低优势估计方差。但 Critic 模型需要额外显存和训练开销也让整个系统更复杂。GRPOGroup Relative Policy Optimization是 DeepSeekMath 中提出的一种策略优化方法。它的核心改变是不训练 Critic 模型而是对同一个 prompt 采样多个回答用回答奖励的组内相对值作为优势。对比项PPOGRPOCritic 价值模型需要不需要优势估计方式GAE广义优势估计组内奖励相对比较显存占用较高较低实现复杂度较高相对简单适用场景主观评估任务可验证奖励任务GRPO 的优势估计可以简单表示为advantage_i (reward_i - mean(rewards)) / std(rewards)其中mean和std是同一组样本内的统计量。这种设计在 RLVR 场景下非常合理因为奖励来自规则验证器不同 prompt 之间的难度差异很大直接比较绝对奖励值没有意义。组内相对比较能抹平题目难度差异让模型专注于“把当前题目解对”。3.4 KL 约束与策略稳定在强化学习训练中奖励提升可能以牺牲语言能力为代价。模型为了拿到高奖励会疯狂重复某些句式、插入大量无意义符号甚至完全偏离自然语言分布。为了防止策略崩坏训练时通常引入 KL 散度约束。简单理解我们希望模型在优化奖励的同时不要偏离参考策略通常是 SFT 后的模型太远。KL 惩罚项一般加在策略更新目标中loss -advantage * log_prob_ratio - beta * kl_divergence其中beta是 KL 惩罚系数。beta过小模型容易走偏beta过大模型学不到东西。这个参数需要反复实验。TRL 的GRPOTrainer中也提供了beta参数默认值通常在 0.02-0.1 之间。实际使用时要结合奖励变化和 KL 指标做调整。4. 完整实战案例一个最小可运行的 RLVR 训练循环通过原理讲解你已经知道 RLVR 大概长什么样。下面用一个最小的数学题训练案例把整个流程落实成代码。4.1 数据准备先准备一个小型训练集data/train.jsonl每行包含一个问题、一个标准答案、以及用于提示模型输出格式的样例说明。{prompt: 请解答以下数学题并将最终答案放在answer标签中。\\n题目3 5 ?, answer: 8} {prompt: 请解答以下数学题并将最终答案放在answer标签中。\\n题目12 * 4 ?, answer: 48} {prompt: 请解答以下数学题并将最终答案放在answer标签中。\\n题目100 - 37 ?, answer: 63}这是很小的玩具数据集用于验证训练链路。真实场景中数学题数据量至少要数万条且要按难度分层。4.2 奖励函数实现继续完善前面的奖励函数。我把它整理成一个独立文件方便后续单独测试。# 文件路径rewards/math_reward.py import re def normalize_answer(text: str) - str: text text.strip() text re.sub(r\\boxed\{([^}]*)\}, r\1, text) text re.sub(ranswer|/answer, , text) text re.sub(r\s, , text) return text def extract_answer(completion: str) - str: pattern ranswer(.*?)/answer matches re.findall(pattern, completion, re.S) if matches: return matches[-1].strip() return def math_reward(prompts, completions, answers, **kwargs): rewards [] for completion, standard_answer in zip(completions, answers): extracted extract_answer(completion) if not extracted: rewards.append(0.0) continue if normalize_answer(extracted) normalize_answer(str(standard_answer)): rewards.append(1.0) else: rewards.append(0.0) return rewards简单说明math_reward接收 prompt 列表、completion 列表和答案列表返回奖励分数列表。真实使用 TRL 时reward function 的签名需要和当前版本匹配通常是(prompts, completions, **kwargs)而答案字段会通过kwargs传入。4.3 使用 GRPOTrainer 训练如果你不想自己写强化学习算法TRL 库的GRPOTrainer是最高效的方案。# 文件路径scripts/train_grpo.py from datasets import load_dataset from transformers import AutoModelForCausalLM, AutoTokenizer from trl import GRPOConfig, GRPOTrainer import sys sys.path.append(..) from rewards.math_reward import math_reward dataset load_dataset(json, data_filesdata/train.jsonl, splittrain) model_name Qwen/Qwen2.5-1.5B-Instruct tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForCausalLM.from_pretrained(model_name) training_args GRPOConfig( output_diroutputs/checkpoints, learning_rate1e-6, per_device_train_batch_size2, gradient_accumulation_steps4, num_generations8, max_completion_length512, beta0.04, logging_steps1, save_steps10, max_steps50, ) trainer GRPOTrainer( modelmodel, argstraining_args, train_datasetdataset, reward_funcsmath_reward, tokenizertokenizer, ) trainer.train()这里重点解释几个关键参数num_generations每个 prompt 采样多少条回答。GRPO 依赖组内比较这个值不能太小建议 4-16。max_completion_length最大生成长度。推理类任务通常需要较长回答可以设 512-2048。betaKL 惩罚系数。太大学得慢太小容易崩。learning_rate强化学习训练学习率要设得比 SFT 更小通常 1e-7 到 1e-6 之间。per_device_train_batch_size这里的 batch size 是 per device 的 prompt 数量实际生成样本量是batch_size * num_generations需要估算显存。这段代码只是最小示例。如果显存不足可以调小per_device_train_batch_size和max_completion_length。4.4 自定义训练循环如果你希望深入理解强化学习过程或者需要对采样、奖励、更新做高度自定义可以写一个简化版训练循环。# 文件路径scripts/train_custom.py # 简化伪代码仅用于理解 RLVR 训练流程 import torch from transformers import AutoModelForCausalLM, AutoTokenizer model_name Qwen/Qwen2.5-1.5B-Instruct tokenizer AutoTokenizer.from_pretrained(model_name) policy_model AutoModelForCausalLM.from_pretrained(model_name) ref_model AutoModelForCausalLM.from_pretrained(model_name) # 1. 构造 prompt prompts [3 5 ?, 12 * 4 ?] inputs tokenizer(prompts, return_tensorspt, paddingTrue) # 2. 采样多条回复 with torch.no_grad(): outputs policy_model.generate( **inputs, max_new_tokens128, num_return_sequences4, do_sampleTrue, temperature0.8, ) # 3. 计算奖励略去完整解析逻辑 def compute_reward(completions): rewards [] for c in completions: text tokenizer.decode(c, skip_special_tokensTrue) if answer8/answer in text: rewards.append(1.0) else: rewards.append(0.0) return torch.tensor(rewards) rewards compute_reward(outputs) # 4. 按组计算优势 rewards rewards.view(2, 4) mean_rewards rewards.mean(dim-1, keepdimTrue) std_rewards rewards.std(dim-1, keepdimTrue) 1e-4 advantages (rewards - mean_rewards) / std_rewards # 5. 策略更新需要计算 logprob这里仅展示思路 # 真实实现中还需要组合 KL 惩罚、PPO 裁剪目标并用参考模型计算 KL。 print(advantages:, advantages)这个示例省略了最重要的 logprob 计算和损失更新部分但它能帮你理解整个流程采样、奖励、优势、更新。生产级实现请参考 TRL 库源码或成熟开源框架。4.5 运行与验证在命令行中运行训练脚本cd scripts python train_grpo.py如果使用多卡训练可以用 accelerateaccelerate launch --num_processes8 train_grpo.py训练过程中日志会输出 reward 均值、KL 散度、学习率等信息。示例输出大致长这样Step 10: reward_mean0.32, kl0.021, loss-0.014 Step 20: reward_mean0.51, kl0.029, loss-0.018 Step 30: reward_mean0.68, kl0.035, loss-0.022如果 reward_mean 持续上升且 KL 没有爆炸说明训练方向正确。4.6 结果说明训练结束后可以写一个简单的评估脚本让模型回答测试集问题并检查正确率。from transformers import AutoModelForCausalLM, AutoTokenizer model AutoModelForCausalLM.from_pretrained(outputs/checkpoints/final) tokenizer AutoTokenizer.from_pretrained(outputs/checkpoints/final) prompt 请解答以下数学题并将最终答案放在answer标签中。\n题目7 * 8 ? inputs tokenizer(prompt, return_tensorspt) output model.generate(**inputs, max_new_tokens128) response tokenizer.decode(output[0], skip_special_tokensTrue) print(response)如果模型学会了输出answer56/answer说明 RLVR 训练成功输出了符合格式的答案。但如果格式正确、最终答案不对就需要检查奖励函数和训练数据质量。5. 常见问题与排查思路RLVR 训练比普通微调更容易出问题。训练不收敛、reward hacking、采样慢是三个最常遇到的坑。问题现象常见原因解决思路训练 loss 不下降reward 不上升奖励信号太稀疏或奖励函数有 bug单独测试奖励函数打印每条数据的奖励值奖励快速上升但输出变成无意义内容Reward Hacking检查是否只用了格式奖励增加真实正确性验证KL 散度快速上升模型输出崩坏beta 系数太小调大 beta或减轻学习率采样速度极慢生成阶段未做加速使用 vLLM 或减少 num_generations模型只会输出answer内部却是乱写格式奖励权重过高限制格式奖励上限正确性奖励必须占主导显存 OOM生成样本数过多或最大长度过长减小 batch size、num_generations、max_completion_length验证器经常误判字符串比较太严格增加归一化处理统一小数、分数、百分号reward 震荡剧烈学习率过大或采样组数不足降低学习率适当增大 num_generations下面展开几个关键问题的排查思路。第一个是 Reward Hacking。这是 RLVR 最容易踩的坑。模型会尝试利用奖励函数的漏洞而不是真正提升能力。比如你只检查answer标签是否存在模型很快学会只输出标签不写内容。解决办法是奖励函数尽量“正交”格式分和正确性分分开算并且正确性分占比要高。第二个是验证器误判。数学答案比较时0.5和1/2应该是相等的5%和0.05也应该是相等的。如果验证器不支持这些归一化模型学到的东西会被判定为“错误”导致训练混乱。所以在设计验证器时要提前考虑同义表达。第三个是训练振荡。强化学习本身就比监督学习不稳定。如果你的 reward 曲线像过山车先降低学习率再检查 KL 惩罚系数。很多时候模型在某一步突然生成了一种新的答题模板导致奖励突变经过 KL 约束后又会回退。还有一个容易被忽略的问题数据分布不一致。RLVR 训练数据如果全是简单加减法模型只会在简单题上提升换到复杂题立刻失效。建议训练数据按难度分层并且定期加入随机抽样评估集。6. 最佳实践与工程建议基于前面这些内容这里整理一套可落地的工程建议帮你少走弯路。6.1 从高质量 SFT 模型开始RLVR 不是万能药。如果模型本身连基本的指令遵循能力都没有直接做强化学习会非常困难。最佳实践是先做高质量 SFT让模型稳定输出需要格式再进入 RLVR 阶段。这样强化学习只需要优化“推理正确性”而不是同时学“怎么组织语言”。6.2 奖励函数优先于训练策略在训练前务必对奖励函数做独立测试。准备 100 条样本人工检查奖励函数的判定结果是否符合预期。奖励函数如果有 5% 的错误率训练效果就会受到明显影响。不要急着调beta和learning_rate先确认奖励信号是可信的。6.3 建议用一套多维奖励体系奖励不一定要非 0 即 1。在数学题中可以拆成格式奖励是否包含answer标签。答案正确奖励最终结果是否一致。步骤完整性奖励关键公式或推理步骤是否出现。多个维度分数可加权组合。但要注意维度越多权重越难调试。我的建议是先做简单 0/1 正确性奖励跑通流程后再逐步增加维度。6.4 控制生成长度治理长思维链推理类模型在强化学习后往往倾向于生成很长的思考过程这对显存和推理性能都是挑战。训练时不要一开始就把max_completion_length设置得太大。可以先设 512观察训练稳定后再逐步增加。上线时也要对部署时的最大生成长度做限制避免成本失控。6.5 做好监控指标而不是只看 lossRLVR 训练时至少要监控以下指标reward mean / reward variance。格式通过率。答案正确率。平均生成长度。KL 散度。策略模型的困惑度变化。这些指标可以帮助你快速定位是“模型没学会”还是“奖励信号出问题”。6.6 定期保存 checkpoint随时回滚强化学习训练过程可能随时“跑飞”。建议每 N 步保存一次 checkpoint并记录当时的关键指标。一旦发现模型输出质量下降立即回滚到之前的 checkpoint而不是继续硬训练。这个习惯在对话模型、推理模型训练中都很重要。6.7 注意数据合规和模型安全训练数据中不要包含敏感内容或有害 prompt。RLVR 过程中模型生成的回答可能带有诱导性内容建议在训练数据构造阶段做好过滤。模型上线前也要结合评测集对模型进行安全性和稳定性评估而不是只看训练 reward。7. 总结与学习路线关于大模型后训练和可验证强化学习这次先讲到这里。我们系统梳理了几个关键点后训练是连接预训练模型和任务应用的核心环节SFT、偏好对齐、RLVR 各有分工。RLVR 用外部可验证奖励替代奖励模型在数学、代码、结构化输出等任务上更稳定、更可靠。GRPO 是当前 RLVR 最常用的策略优化方法通过组内相对优势估计降低训练复杂度。奖励函数设计直接影响训练成败验证器要简单、鲁棒、防 hack。训练过程中要重点关注 KL 散度、reward hacking、验证器误判和采样效率。如果你想深入学习这个方向可以按下面的路线推进先跑通一个 SFT 微调流程熟悉 Transformers 和数据集处理。再跑一个 DPO 偏好对齐实验理解参考模型和策略模型的关系。复现一个最小 RLVR 实验用 GRPOTrainer 的示例代码换一个自己的小型数据集。阅读 DeepSeekMath 和 DeepSeek-R1 的技术报告重点关注它们的奖励函数设计和训练曲线。把 RLVR 迁移到你的领域数学、代码生成、SQL 查询、结构化抽取等。训练 RLVR 模型最大的感受是强化学习并不神秘但非常考验“信号设计”和“工程耐心”。奖励函数是你的模型行为边界正则化是你的安全网。先把玩具实验跑通再逐步扩展数据规模和模型规模这个方向你一定会拿到不错的结果。如果这篇文章对你有帮助建议收藏备用。后续我会继续整理后训练相关的实践笔记欢迎关注。
返回列表