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

资讯详情

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

过程数据与完成监督:构建大模型推理能力的训练实践

过程数据与完成监督:构建大模型推理能力的训练实践 过程数据是提升大模型推理能力的关键资源。传统指令微调只监督最终答案训练得到的模型往往在步骤稍长的数学题、逻辑题或代码推理问题上出现“结论对、过程错”的隐性错误。Reasoning Core 与 Completion-Supervised Reasoning Training 这一类思路正是为了改变这种监督粒度而设计的。本文从训练视角出发面向算法工程师、大模型微调实践者和数据构建人员说明如何设计一套覆盖面足够广的过程数据并以“完成监督”的方式训练推理模型。读完可以自己搭建一条最小数据流水线完成过程数据构造、训练、验证和基础排错。1. 理解 Reasoning Core 与 Completion-Supervised 的训练思路1.1 为什么普通指令微调不足以提升推理能力指令微调通常把“问题”作为指令把“标准答案”作为标签。模型学习的目标是给定输入输出与标签一致的文本。这个流程对事实性问答、摘要生成、情感分类等任务很有效但对多步推理任务有明显不足。推理任务的核心特征是中间步骤之间存在依赖关系。以一道包含三个运算步骤的应用题为例如果模型把第二步算错但最终答案恰好和标准答案一致普通指令微调会把这个错误路径也当作正向样本学习。反过来如果模型每一步都正确只是最终答案格式与标签不完全相同又会被当作负样本。这意味着监督信号里包含大量噪声。问题不在模型容量而在监督粒度。普通指令微调把“最终答案”当作唯一事实来源过程是否可解释、是否可检验并没有参与训练。这正是 Completion-Supervised Reasoning Training 想解决的痛点把一个完整推理过程的每一个中间结论都纳入损失计算。1.2 Completion-Supervised 的含义以完整推理过程为监督信号Completion-Supervised 可以理解为“完成监督”。在推理训练场景里监督对象不是 Question 后面的 Answer而是模型需要逐步补全的完整推理轨迹。一个典型样本可以拆成三段Instruction用户问题或任务描述。Response从思考开始到最终答案结束的完整文本。Completion在训练时真正参与损失计算的部分。实现上Instruction 部分通常参与计算但不反向传播或者通过 mask 机制把 Instruction 的 token 损失置零。Response 中每一个 token 都作为下一 token 的监督信号。这样模型学的是“如何一步一步继续写下去”而不是“如何记住一个孤立答案”。这种训练方式的优势在于推理过程中的中间状态被显式建模。模型不再只能估计 P(最终答案|问题)而是能估计 P(下一步推理|问题已有推理)。当模型遇到分布外问题时它更有可能按步骤推进而不是直接跳到一个似是而非的答案。1.3 Reasoning Core一个用于构造过程数据的数据设计框架Reasoning Core 这个名称可以理解为“推理核心数据”的设计思路。它强调过程数据不能只覆盖一类题目、一种解题路径、一种步骤粒度而是要尽量保持广度。广度体现在三个维度问题类型广度数学、逻辑、算法设计、常识推理、因果分析等都应有覆盖。解题路径广度同一道题可以有两种以上合理解法应当保留多路径而不是只留标准答案。步骤粒度广度既有少步数的快速推理也有十步以上的长链推理。把 Reasoning Core 看作数据规范而不是具体数据集更容易落地。你可以在自己的数据流水线里按这套规范生成、清洗、校验过程数据。下面表格给出了不同监督形式的对比。监督形式监督对象训练信号强度典型问题适用场景答案监督最终输出弱过程错误无法被发现分类、抽取、短问答步骤监督每一步中间结论中步骤边界需要人工定义数学题、逻辑题完成监督完整推理文本序列中强需要保证推理文本质量长链推理、生成式推理过程奖励监督每一步质量打分强需要标注模型或人工打分强化学习、偏好对齐需要说明的是Completion-Supervised 并不天然优于其他监督方式。它依赖一个前提训练数据里的推理轨迹必须是可信的。如果过程数据本身质量差模型学到的只是“写很长但错误的过程”。这正是 Reasoning Core 要解决的数据设计问题。2. 环境准备与训练基线搭建2.1 推荐硬件与开源工具链开始之前先确认环境。Completion-Supervised 训练本质上还是语言模型微调硬件要求与 LLM 微调一致。如果只做小规模实验单张 24GB 显存的显卡可以训练 7B 到 14B 量级模型使用 LoRA 或 QLoRA 方式。如果数据量较大建议准备多卡环境并用 DeepSpeed 或 FSDP 做分布式训练。常用工具链可以按下面组合基座模型常见的开源 Chat/Instruct 模型如 Qwen、Llama 系列或者 DeepSeek 等。数据加载HuggingFace Datasets。训练框架TRL、LLaMA-Factory、transformers peft 自写训练循环。日志与可视化wandb、tensorboard 二选一。推理验证vLLM 或 transformers text-generation pipeline。以下示例用于说明思路实际项目要结合自己的包名、路径和版本调整。尤其是 transformers、peft、accelerate 的版本兼容先确认官方文档再安装。2.2 数据格式设计Completion-Supervised 的数据格式没有统一标准但结构上必须能区分 instruction 与 response。推荐使用 messages 格式因为主流训练框架都支持。{ messages: [ { role: user, content: 小明有 3 个苹果小红给了 5 个小明又吃了 1 个现在有几个苹果 }, { role: assistant, content: 初始苹果数为 3。小红给了 5 个后总数变为 358。吃完 1 个后剩余 8-17。最终答案是 7。 } ] }在训练时assistant 部分会作为 completion 参与 loss。如果你的框架支持更细粒度控制可以在每个 assistant 消息上记录是否参与监督。还有一种常见格式是单轮指令加输出{ instruction: 计算35-1, output: 先算 358再算 8-17结果为 7。 }推荐使用 messages 格式。因为后续如果要扩展到对话、多轮推理、工具调用messages 结构不需要大改兼容性更好。2.3 配置示例使用 PEFT transformers 的最小训练配置这里给出一份 YAML 风格的训练配置用于说明参数关系。不同框架写法不同但核心参数一致。model: base_model: Qwen/Qwen2.5-7B-Instruct torch_dtype: bfloat16 attn_implementation: flash_attention_2 data: train_file: ./data/reasoning_train.jsonl validation_file: ./data/reasoning_valid.jsonl max_length: 2048 instruction_field: instruction output_field: output training: per_device_train_batch_size: 2 per_device_eval_batch_size: 2 gradient_accumulation_steps: 8 learning_rate: 2e-5 num_train_epochs: 3 logging_steps: 10 save_steps: 500 warmup_ratio: 0.03 lr_scheduler_type: cosine lora: r: 16 alpha: 32 dropout: 0.05 target_modules: - q_proj - k_proj - v_proj - o_proj - gate_proj - up_proj - down_proj其中 max_length 要结合数据长度。推理过程数据通常比普通对话长建议先统计数据集的 token 分位数再决定 max_length。如果设置过短大量长推理样本会被截断模型学不到长链推理设置过长会浪费显存降低训练速度。2.4 训练前环境检查清单在跑训练之前先执行下面这些检查可以省去大量排错时间。数据集中的 instruction、output 字段不为空。训练集与验证集没有重合且验证集覆盖不同问题类型。基础模型能够正常加载。随机抽取一条样本确认 tokenize 后 instruction 和 output 的分界位置正确。确认 loss mask 只作用于 output 部分而不是整条文本。确认 batch size、gradient_accumulation_steps 与总 batch size 的计算关系。确认模型输出长度上限可以覆盖最长推理样本。注意不要只验证程序能启动还要验证输入、输出、异常分支和日志是否符合预期。启动成功不等于训练信号正确。3. 构造 Broad Procedural Data 的方法3.1 广度来自哪里Reasoning Core 强调 Broad Procedural Data核心是避免过程数据“偏科”。很多团队只收集数学竞赛题结果模型数学推理变好但代码推理、逻辑推理没有明显进步。这不是模型能力不够而是训练数据的覆盖范围不够。构造数据时可以把问题类型分成几个大类算术与代数推理几何与空间推理逻辑命题与真值判断事件时序与因果推理算法设计与代码执行常识推断与反事实推理每一类都应当有独立的种子库。种子问题可以由人工编写也可以从公开题库整理。但要注意版权与合规问题不要直接搬运受版权保护的试题。3.2 数据生成流水线可以这样设计过程数据的来源主要有三种人工编写、大模型采样生成、人工与模型混合。推荐流水线如下。种子问题收集人工编写一批高质量种子问题。多路径采样使用强推理模型对每个种子问题采样多条推理路径。答案校验用规则、程序或强模型判断最终答案是否正确。步骤校验检查中间步骤是否自洽、是否可复现。清洗与去重删除重复样本平衡各问题类型的数据量。人工抽检随机抽 5% 到 10% 样本人工判断推理过程质量。这里的校验环节非常关键。如果只用最终答案是否一致来过滤样本可能保留“过程错误但答案碰巧正确”的坏样本。建议对数学题使用程序化校验对逻辑题使用规则校验对开放推理题使用强模型进行逐步评分。3.3 过程数据标注规则设计过程数据时每一步都应该尽量满足三个条件原子性一步只做一个操作不把多个推理动作压缩在一句话里。可验证性中间结论能够被前文步骤解释或计算出来。确定性中间变量名、计算公式、单位、符号前后一致。以下是一个好的推理过程示例问题一件商品原价 80 元打八折后再降价 5 元最后价格是多少 步骤 1. 打八折后价格为 80 * 0.8 64 元。 2. 再降价 5 元64 - 5 59 元。 3. 最终价格为 59 元。这个过程中每一条都可以单独验证。而下面的过程就不适合做训练数据打折后加上降价大概六十块钱左右。这种模糊表达会让模型学习到“推理不需要精确计算”的错误模式。3.4 数据模板与 JSON 示例建议把生成好的数据保存成 JSONL 文件每条样本一行。为了后续支持多路径和元信息可以扩展字段。{ id: math_001, category: arithmetic, difficulty: easy, question: 一件商品原价 80 元打八折后再降价 5 元最后价格是多少, gold_answer: 59, reasoning_paths: [ 打八折后价格为 80 * 0.8 64 元。再降价 5 元64 - 5 59 元。最终价格为 59 元。, 原价 80 元打八折相当于 80 * 0.8 64 元。加上后面的降价 5 元结果为 64 - 5 59 元。 ], validation: { executable: true, checker: programmatic } }如果训练框架只接受 instruction/output 格式可以在预处理阶段把 reasoning_paths 展开成多条训练样本或按策略选择其中一条。保留多路径不是为了训练时随机选而是为了后续做数据增强、偏好排序和强化学习。3.5 质量控制清单过程数据是否需要清洗通过下面清单判断。最终答案与问题要求一致。推理过程的每一步与上一步数值或逻辑一致。没有多余的无意义填充例如反复写“让我们慢慢思考”。没有隐含的捷径跳步。符号、单位、变量名前后一致。不同问题类型的数据量差距不超过设定的倍率阈值。每条推理路径长度分布合理既有短路径也有长路径。如果发现某一类问题全是同一种解题模板说明数据广度不足。建议加入更多发散性种子问题。4. 完成监督训练的实现细节4.1 损失计算为什么只拿 response 部分在语言模型训练中交叉熵损失会对每个 token 计算预测概率。如果 instruction 也参与 loss模型会学习预测“用户问的是什么”这没有任何意义。Completion-Supervised 的做法是把 instruction 部分 token 的 loss mask 置为 0只对 assistant response 部分的 token 计算损失。这样模型学习的目标就是给定前面的 instruction 和已经生成的部分 response正确预测下一个 token。这个目标和推理过程的自回归生成方式是一致的。可以用下面这段伪代码理解。def compute_loss(logits, labels, attention_mask, completion_mask): # logits: (batch, seq_len, vocab_size) # labels: (batch, seq_len) # completion_mask: (batch, seq_len)response 部分为 1instruction 部分为 0 shift_logits logits[..., :-1, :].contiguous() shift_labels labels[..., 1:].contiguous() shift_mask completion_mask[..., 1:].contiguous() loss_fct CrossEntropyLoss(reductionnone) losses loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) losses losses.view(shift_logits.size(0), shift_logits.size(1)) masked_losses losses * shift_mask return masked_losses.sum() / (shift_mask.sum() 1e-9)关键点在于 completion_mask 的构造。如果你的数据是 messages 格式首先要把 assistant 内容 token 对应的位置标记为 1。在拼接多轮对话时每个 assistant 轮次都应该参与监督。4.2 在训练循环中应用 completion mask在 HuggingFace transformers 中可以借助 DataCollator 处理 mask。核心思路是在 tokenize 之后记录每个 token 是否属于 assistant 部分。from transformers import AutoTokenizer tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen2.5-7B-Instruct, trust_remote_codeTrue) def tokenize_with_completion_mask(example): instruction example[instruction] output example[output] instruction_ids tokenizer.encode(instruction, add_special_tokensFalse) output_ids tokenizer.encode(output, add_special_tokensFalse) input_ids [tokenizer.bos_token_id] instruction_ids output_ids [tokenizer.eos_token_id] labels input_ids.copy() completion_mask [0] # bos token 不参与监督 completion_mask [0] * len(instruction_ids) # instruction 不参与监督 completion_mask [1] * len(output_ids) # output 参与监督 completion_mask [1] # eos token 参与监督 return { input_ids: input_ids, labels: labels, completion_mask: completion_mask, }这里的 add_special_tokensFalse 很重要。如果使用 tokenizer 的 apply_chat_template可能出现多个 special token位置对应关系会变复杂。建议先用上面的显式方式验证一次确认 mask 对齐后再切换到模板方法。4.3 参数设置建议训练推理模型时参数设置不能照搬对话微调。下面给出参考区间。参数常见设置调整影响learning_rate1e-5 到 3e-5过大导致灾难性遗忘过小导致收敛慢max_length2048 到 4096过短截断长推理过长显存压力大per_device_train_batch_size1 到 4根据显存调整通常不能太大gradient_accumulation_steps8 到 16控制实际 batch size与学习率联动num_train_epochs2 到 5数据质量高时不宜太多防止过拟合warmup_ratio0.03 到 0.1稳定训练前期 loss 震荡lr_scheduler_typecosine收敛稳定适合微调需要注意的是推理数据集中 token 长度较长常见的“global batch size 越大越好”并不绝对。过大的 global batch size 会让模型倾向于记住训练数据中的固定推理模板降低泛化能力。4.4 为什么要监督完整推理链如果只对最终答案计算 loss模型缺乏过程约束。比如数学题模型可能在第三步写出“359”后续又根据这个错误结果继续推算。最终答案如果正确那大概率是巧合如果错误模型并不知道错在哪一步。完成监督把每一步过程都变成监督信号模型会在训练中被迫学习“步骤之间的数值一致性”。这也会让模型生成过程中更容易出现中间检查。虽然这不是显式约束但数据中大量一致的步骤关系会让模型统计出“边算边核对”的文本模式。实际落地时可以比较同一模型在答案监督和完成监督下的输出差异。完成监督模型在推理过程中更容易出现类似“让我重新检查这一项”的自反馈文本。5. 训练验证与效果评估5.1 训练日志观察指标训练开始后不要只盯着 loss。要同时观察以下几个指标。language modeling loss是否稳定下降。validation loss与训练 loss 是否同步下降。梯度范数是否频繁爆表。学习率曲线是否符合 scheduler 预期。样本 token 长度是否有大量样本被截断。如果训练 loss 下降但验证 loss 不下降可能发生了过拟合。如果训练 loss 也不下降优先检查数据格式和 mask 是否正确。Epoch 0/3: 10/1000 [1%] loss: 1.8324, lr: 1.3e-5, grad_norm: 2.15 Epoch 0/3: 20/1000 [2%] loss: 1.6421, lr: 1.6e-5, grad_norm: 1.98loss 在 1.5 到 2.5 之间都是正常范围具体取决于基座模型和任务难度。如果 loss 从一开始就是 0.02大概率是 mask 写错模型只预测了 instruction 中大量重复的固定 token。5.2 用固定推理题目验证行为变化训练完成后用一组训练集外的推理题验证模型行为。验证不仅要看答案还要看过程。建议准备三类测试题训练集内同分布题目验证模型是否学会了训练数据中的推理模式。训练集外同类型题目验证泛化能力。类型迁移题目例如用数学推理题训练用逻辑推理题测试观察能力迁移。对每个测试题采样 3 到 5 次因为模型生成有随机性。记录答案正确率、单次生成中出现中间步骤错误的概率、完整推理过程的比例。5.3 过程质量评估指标答案准确率不能完全反映推理能力。可以增加一些过程维度的指标。步骤一致性抽取模型生成的中间结论检查相邻步骤间是否一致。步骤可验证性中间结论是否可以由前置步骤计算得到。冗余比例生成文本中无效检查、重复内容的字符占比。最终答案命中率答案完全正确的比例。对数学题可以写一个简单的解析器抽取“x value”形式的中间结论用数字比较判断一致性。对逻辑题可以人工评分用 0 到 3 分衡量过程质量。评分标准0过程混乱无法理解答案错误1答案正确但过程有明显跳步或错误2答案正确过程完整但存在小瑕疵3答案正确过程严谨步骤可验证5.4 预期现象与异常现象完成监督训练正常时会有以下现象模型更倾向于输出分步推理文本。训练后模型在短步数任务上的答案准确率不一定显著提升但长步数任务的稳定性会更好。模型对问题表述的鲁棒性增强改变数字或题干顺序后更容易重新按步骤计算。异常现象包括模型输出大量“第一步、第二步、第三步”等空壳但没有实质计算。模型在验证集上答案准确率降低因为基座模型原本能答对的简单题在微调后反而被强迫写过程出现更多 token 级错误。出现第二种情况时要检查训练数据中的简单题是否也要求了超长过程。并不需要每个样本都写 8 步以上。短推理和长推理应该混合保持步骤粒度广度。6. 常见问题与排查路径6.1 训练 loss 不下降现象训练初期 loss 保持不变或者长时间震荡。排查顺序确认 completion_mask 是否正确。随机打印一条样本的 mask检查 instruction 区域是否为 0。确认 labels 与 input_ids 是否对齐。常见错误是 labels 里没有把 pad token 设为 -100。确认学习率是否过小。如果学习率低于 1e-6训练可能几乎不动。确认基础模型是否正确加载为 bfloat16 或 float16混合精度设置是否生效。查看日志中 grad_norm。如果梯度范数长期为 0可能是模型被冻结或 mask 全部为 0。如果 mask 写错模型会在 instruction 区域也计算 loss。loss 初期很小但验证时不具备任何推理能力。建议在训练前写一个单元测试确保所有 output token 都参与 loss。6.2 模型输出截断或重复现象推理过程只生成开头几步后面变成重复文本。可能原因max_length 过短推理过程被截断。数据中长推理样本较少模型没有学会长文本续写。采样参数设置不合理temperature 过高或没有设置 repetition_penalty。检查方式统计训练数据中每个 output 的 token 长度。统计验证时模型生成文本的平均长度。把温度降到 0.1repetition_penalty 设为 1.1 到 1.3观察重复是否减少。解决建议增加长链推理样本的占比。显存允许时把 max_length 从 2048 提升到 3072 或 4096。对过短的推理样本做上采样对过长样本做智能截断保留关键中间步骤。6.3 数据格式错误导致训练崩现象训练在数据加载阶段报 KeyError、ValueError 或者 Loss 为 NaN。常见错误instruction/output 字段为空字符串。tokenizer encode 返回 None。数据集中混入了多模态字段导致 input_ids 类型不匹配。某些样本 output 只有一个 eos token导致参与监督的 token 过少。排查方式from datasets import load_dataset ds load_dataset(json, data_filestrain.jsonl, splittrain) for i in range(3): print(ds[i])先打印原始数据再打印 tokenize 后的字段。重点检查 output 长度是否为 0。预防措施清洗阶段过滤空样本和异常短样本。使用 dataset.map 时加 filter跳过无效行。数据流水线中加入 schema 校验例如字段类型为 str且非空。6.4 训练后推理能力提升不明显现象训练和验证 loss 都正常下降但测试集答案准确率没有提升甚至下降。排查方向训练集问题类型是否与测试集偏差过大。如果训练集全是简单算术题测试集是竞赛逻辑题提升不明显是正常的。过程数据是否太“整齐”。所有样本都使用同一模板模型学到的只是模板不是推理。基座模型本身能力是否足够。7B 模型在复杂推理上存在上限完成监督数据只能帮助释放已有推理能力不能凭空创造能力。数据量是否不足。过程监督需要比答案监督更多的有效样本。一个实用建议先做小规模数据实验用 500 到 1000 条高质量过程数据微调观察模型行为变化。如果模型开始学会分步输出再扩大到全量数据。这样能快速判断问题出在数据还是训练设置。7. 最佳实践与扩展方向7.1 数据质量优先于数据规模推理过程数据并不见得越多越好。数据中的错误推理路径会让模型学到错误的统计规律。建议采用“高信噪比”策略。优先使用可程序验证的数据类型例如数学计算、代码执行。开放性推理任务使用强模型生成后再让另一个模型评分。每条样本记录来源、校验方式、生成配置便于追踪问题。一个可复用的数据发布前检查清单问题类别覆盖是否达到预期广度。同一问题是否保留多条推理路径。中间步骤是否原子化、可验证。没有空样本、重复样本、超长异常样本。训练集、验证集、测试集分布基本一致但不重叠。最终答案与过程结论一致。推理文本中不存在明显的事实错误或逻辑断裂。7.2 从完成监督到过程奖励模型Completion-Supervised 只是推理训练的第一步。它适合作为早期阶段的预训练或监督微调。之后可以进一步引入过程奖励模型。完成监督给出的是“整段文本正确”的监督信号但每个步骤对最终答案的贡献大小并不相同。过程奖励模型可以对每一步打分然后用于强化学习或搜索。常见做法是先用完成监督训练出基础推理能力。再构造步骤级偏好对训练过程奖励模型。最后用 PPO 或 GRPO 等算法让模型根据过程奖励优化推理策略。这样做的目的是让模型不仅会写推理过程还能判断哪一步更可靠。前者解决能力问题后者解决策略问题。7.3 下一步学习路径建议如果你是刚接触这个方向建议按以下顺序实践。搭建最小训练脚本使用 100 条数学题过程数据跑通 loss。手动查看模型的推理输出理解 completion mask 是否生效。扩展数据到 1000 条覆盖 3 类以上问题观察泛化变化。加入验证集比较不同 max_length、学习率、数据量下的效果。尝试加入多路径样本使用随机选择或加权选择作为训练数据。最后再进入过程奖励模型和强化学习阶段。不要一步跨到复杂框架先把“过程数据如何构造、mask 如何生效”掌握好。大部分真实项目的问题都出在这两层。Reasoning Core 这类设计思路本质上是在提醒训练者推理能力不是靠堆答案样本就能获得的必须把推理过程拆开、验证、重组成可监督的结构。完成监督训练让模型在生成时更倾向于“边推理边校验”而广泛的过程数据则保证这种能力不会只在某一类题上生效。先把数据广度做好再把训练细节调稳推理模型的效果提升是可见、可评估的。
返回列表