
1. 为什么数学推理需要强化学习来破局数学推理这件事放在大模型的能力谱系里一直是个硬骨头。早几年大家做数学题自动求解主流思路是监督微调——拿海量带步骤的题解数据去喂模型让它学会模仿人类解题的格式和套路。这条路能走通一部分但很快就撞到天花板模型学会了“看起来像在推理”却经常在中间步骤悄悄出错最后给出一个自信满满的错误答案。更麻烦的是很多竞赛级题目根本没有标准步骤可模仿你没法用“抄答案”的方式教会模型解决它没见过的问题。强化学习在这里扮演的角色本质上是把“解题”从模仿任务变成了搜索任务。模型不再需要逐字模仿某一条标准解法而是自己生成多条推理路径然后根据最终答案对不对来获得奖励信号反过来强化那些通向正确答案的思考方式。这个转变很关键因为它允许模型探索出人类没写进训练集里的解法也允许它在没有中间步骤标注的情况下仅凭最终答案的验证就能学习。我最初接触这条路线的时候心里是有疑虑的数学推理的搜索空间那么大靠一个稀疏的最终奖励信号模型真的能学到东西吗后来实际跑了几轮实验才明白关键不在于奖励有多密集而在于怎么设计奖励、怎么控制探索的方差、怎么让模型在“敢想”和“别乱想”之间找到平衡。这套东西和传统监督学习的手感完全不同更像是在训练一个会自己琢磨解题思路的学生而不是往它脑子里灌题库。这篇文章面向的是已经了解大模型基本训练流程、想切入数学推理强化学习方向的从业者也适合做教育类AI产品、自动解题系统、形式化验证相关工作的同学参考。我会把整条技术链路拆开讲清楚从任务建模、奖励设计、训练框架选型到实际跑起来会遇到的坑和排查方法。读完你应该能自己搭起一套可运行的数学推理强化学习流程并且知道每一步为什么这么做。2. 数学推理强化学习的整体方案设计2.1 把解题过程建模成序列决策问题强化学习的标准框架是马尔可夫决策过程要把它套到数学解题上第一步是定义清楚状态、动作、奖励分别是什么。我的做法是把语言模型本身当作策略网络状态是当前已经生成的推理前缀动作是下一个token的生成一条完整的推理链加上最终答案构成一个episode。这样建模的好处是直接复用现有的自回归生成框架不需要额外设计复杂的环境模拟器。但这里有个细节容易被忽略数学推理的“状态”其实包含了大量隐式的中间计算模型在生成下一步时前面所有步骤的语义都被压缩在上下文里。这意味着策略网络必须自己学会维护一个内部的工作记忆而不是像下棋那样有一个显式的棋盘状态。这也是为什么数学推理的强化学习比游戏类任务更难——状态表示是隐式的、高维的、而且随着推理链变长会不断漂移。另一个设计选择是动作粒度。最细的粒度是逐token生成最粗的是整条推理链一次性生成后打分。我实测下来逐token的信用分配太困难奖励信号要穿过几百上千个动作才能传回去方差大到几乎训不动。整条链打分又太粗模型不知道具体哪一步出了问题。折中方案是分段打分比如把推理链按自然段或按推理步骤切分每段给一个中间奖励这样既保留了信用分配的精度又控制了方差。2.2 奖励函数设计从稀疏到稠密的权衡奖励设计是整条链路里最需要反复打磨的部分。最朴素的方案是结果奖励最终答案对了给1错了给0。这个信号极其稀疏但胜在绝对可靠不会引入任何人为偏见。我早期实验里用纯结果奖励配合大batch采样确实能训出东西但样本效率低得让人心疼一个epoch要烧掉大量算力。为了提升效率常见的做法是引入过程奖励模型对每一步推理给一个质量分。过程奖励的好处是稠密能加速收敛坏处是它本身可能不准模型会学会钻过程奖励的空子生成“看起来步骤很漂亮但答案还是错”的推理。我踩过这个坑有一轮实验里过程奖励权重给太高模型学会了写一堆格式工整但逻辑空洞的中间步骤结果奖励反而下降了。我的经验是采用混合奖励结构结果奖励占主导过程奖励作为辅助正则项权重控制在0.1到0.3之间。具体形式可以写成总奖励等于结果奖励加上一个系数乘以过程奖励的均值。这个系数需要根据任务难度调题目越难、结果奖励越稀疏过程奖励的权重可以适当调高但绝不能让它盖过结果信号。还有一个容易被忽视的点是格式奖励。数学推理要求模型输出结构化的解题过程如果它生成一堆乱码或者不按格式来即使答案碰巧对了也没有实用价值。我会加一个轻量的格式检查奖励比如要求推理链包含明确的步骤分隔符、最终答案有特定标记不满足就扣分。这个奖励不需要很大0.05到0.1的量级就够目的是引导模型养成规范的输出习惯。2.3 训练框架与采样策略选型框架层面我主要用两类方案一类是基于策略梯度的经典算法比如PPO及其变体另一类是基于拒绝采样加监督微调的迭代式方法比如STaR系列的思路。两者各有适用场景。PPO的优势是理论上更严谨能直接优化策略的期望奖励适合奖励信号设计得比较精细的情况。但PPO对超参数极其敏感学习率、裁剪范围、KL惩罚系数稍微偏一点就训崩。我建议新手先从较小的学习率和较大的KL惩罚开始稳定后再逐步放开。拒绝采样加监督微调的思路更简单粗暴让当前模型对每道题采样多条推理链保留答案正确的那些然后用这些高质量样本做一轮监督微调迭代往复。这个方法实现简单、稳定性好缺点是样本利用率低而且容易陷入自我强化的循环——模型只学自己已经会的东西探索能力逐渐退化。我实际项目里采用的是两者结合先用拒绝采样快速冷启动让模型具备基本的正确解题能力再切到PPO做精细优化。冷启动阶段大概跑三到五轮迭代每轮采样8到16条推理链保留正确且格式合规的样本。切到PPO之后采样温度要适当调高保证探索的多样性同时用KL惩罚约束策略不要偏离冷启动模型太远。采样策略上有个关键参数是每条题目的采样条数。太少则奖励信号噪声大太多则算力浪费。我的经验值是每条题采样8到32条具体取决于题目难度和算力预算。简单题8条就够难题可以拉到32条甚至更多因为难题的正确率低需要更多样本才能碰到正确答案。3. 核心细节解析与实操要点3.1 推理链的表示与切分方式推理链怎么表示直接影响到后续的奖励计算和信用分配。我试过三种方案纯文本、带步骤标记的文本、以及结构化JSON。纯文本最灵活但解析困难模型稍微跑偏就提取不出步骤。结构化JSON最规整但模型生成JSON的稳定性差经常出现语法错误导致整条链作废。最终我采用的是带轻量标记的文本格式用类似“步骤一”“步骤二”这样的自然语言标记来分隔推理步骤最终答案用“答案”开头单独一行。这种格式对模型友好解析也简单用正则就能稳定提取。标记本身不参与奖励计算只用于切分和格式检查。切分粒度上我建议按推理步骤切而不是按句子或按token数。一个推理步骤通常对应一次逻辑推进比如“由条件A和B可得C”算一步“对C两边求导”算下一步。这样切分出来的每段语义完整过程奖励模型打分时也更容易判断对错。如果按固定长度切经常会把一个完整的推理拦腰截断导致过程奖励误判。3.2 过程奖励模型的训练与校准过程奖励模型本质上是一个步骤级的分类器或回归器输入是题目加当前推理前缀输出是这一步正确的概率或分数。训练数据从哪来最直接的办法是用最终答案正确的推理链作为正样本答案错误的作为负样本然后对每一步打标签。但这样有个问题一条错误的推理链里前面很多步可能都是对的只有最后一步算错了如果整条链都标负过程奖励模型会学到错误的信号。更精细的做法是做步骤级标注人工或者用规则判断每一步是否正确。人工标注成本太高我一般采用规则加模型辅助的方式先用符号计算引擎验证每一步的数学等价性能验证的自动打标不能验证的交给一个辅助模型判断最后人工抽检。这个过程很费功夫但过程奖励模型的质量直接决定了训练效果值得投入。过程奖励模型训好之后还需要做校准。因为它的输出分布可能和真实正确率有偏差直接拿来当奖励用会引入系统性误差。我会用一个小的验证集做温度缩放或者 Platt 校准把模型输出的分数映射到接近真实概率的区间。校准之后的过程奖励权重给到0.2左右配合结果奖励使用效果比较稳。3.3 KL惩罚与探索的平衡控制KL惩罚是PPO里约束策略更新的关键机制它衡量的是当前策略和参考策略之间的分布差异。参考策略通常是冷启动后的监督微调模型。KL惩罚系数设得太小策略会跑偏生成一堆胡言乱语设得太大策略几乎不更新训练没有进展。我的调参经验是初始KL系数设在0.01到0.05之间观察训练过程中KL散度的变化。如果KL散度持续上升超过参考值的两到三倍说明策略跑得太快需要调大系数如果KL散度几乎不动说明约束太紧可以适当调小。这个系数不是固定的我通常会用自适应KL设定一个目标KL值根据实际KL和目标值的比值动态调整系数。探索方面采样温度是关键。冷启动阶段温度可以低一些0.6到0.8保证生成质量。PPO阶段温度调到0.8到1.0增加多样性。但温度也不能太高超过1.2之后生成质量下降明显很多推理链前半段就崩了浪费采样预算。我一般会在训练中期做一次温度退火从1.0逐步降到0.7让模型在探索和利用之间平滑过渡。注意KL惩罚和采样温度是两个独立的探索控制手段不要同时大幅调整。每次只动一个参数观察至少几百个训练步再决定下一步。4. 完整实操流程与关键环节实现4.1 数据准备与冷启动模型训练数据准备分两块题目集和冷启动用的监督数据。题目集我一般从公开的数学竞赛题库和教材习题里收集覆盖代数、几何、数论、组合等主要分支难度从初中到竞赛级都要有。题目数量不需要特别大几千到一万道就够关键是覆盖面要广不能偏科。冷启动监督数据是带完整解题步骤的题目解答对。这部分数据可以自己构造也可以用公开的题解数据。构造的方式是让一个较强的基线模型对题目集生成解答然后用符号计算引擎验证答案保留正确的解答作为监督数据。这个过程可以迭代几轮每轮用上一轮训好的模型生成新数据逐步提升数据质量。冷启动训练就是标准的监督微调损失函数是交叉熵只对解答部分计算损失题目部分不参与。训练轮数不用太多两到三个epoch就够重点是让模型学会输出格式和基本的解题模式。训完之后在验证集上测一下准确率有个百分之二三十的基础正确率就可以进入下一阶段。4.2 采样与奖励计算流水线搭建采样流水线的核心是并行生成和批量验证。我用的是一个生产者消费者架构生产者负责从题目集里取题调用推理引擎并行生成多条推理链消费者负责解析推理链、提取最终答案、调用验证器判断对错、计算奖励。两者通过一个队列连接避免生成和验证互相等待。验证器是流水线里最关键的组件。对于有确定答案的题目验证器就是字符串匹配或者数值比较简单可靠。对于答案形式多样的题目比如表达式化简需要做数学等价性判断这时候要调用符号计算库。我用的方案是先把答案转成标准形式再做等价性检查能覆盖绝大多数情况。奖励计算在验证之后进行把结果奖励、过程奖励、格式奖励按权重加起来。这里有个工程细节过程奖励模型的前向计算比较慢如果每条推理链的每一步都跑一遍吞吐量会很低。我的优化是只对推理链的关键步骤计算过程奖励比如每个推理步骤的结尾而不是逐token计算。这样能省下大量算力对最终效果影响很小。4.3 PPO训练循环与超参数配置PPO训练循环的伪代码大致如下for iteration in range(num_iterations): # 采样阶段 trajectories [] for problem in sample_problems(batch_size): chains policy.generate(problem, num_samplesK, temperaturetemp) for chain in chains: reward compute_reward(problem, chain) trajectories.append((problem, chain, reward)) # 计算优势函数 advantages compute_gae(trajectories, gamma0.99, lam0.95) # 多轮PPO更新 for epoch in range(ppo_epochs): for batch in split_batches(trajectories, minibatch_size): loss ppo_loss(policy, ref_policy, batch, advantages, clip_range0.2, kl_coefkl_coef) loss.backward() optimizer.step() # 自适应调整KL系数 kl_coef adapt_kl_coef(kl_coef, measured_kl, target_kl0.01)关键超参数我列一下自己的常用配置batch_size按题目数算一般32到64每条题采样K等于8到16PPO更新轮数2到4minibatch_size按token数算大概4096到8192学习率1e-6到5e-6裁剪范围0.2GAE的gamma 0.99lambda 0.95目标KL 0.01。这些值不是绝对的需要根据模型规模和任务难度微调。训练过程中要监控几个指标平均奖励、正确率、KL散度、生成长度、格式合规率。平均奖励和正确率应该稳步上升如果震荡剧烈说明学习率太大或者batch太小。KL散度要控制在目标值附近持续偏高说明约束不够。生成长度如果突然暴涨可能是模型学会了用冗长推理来骗过程奖励需要检查奖励设计。格式合规率应该很快接近1如果一直上不去说明格式奖励权重不够或者模型能力不足。4.4 模型评估与迭代优化评估不能只看最终准确率还要看推理链的质量。我一般从三个维度评估答案正确率、推理步骤的逻辑连贯性、以及解法的多样性。答案正确率是硬指标在留出测试集上算。逻辑连贯性靠人工抽检看推理链有没有跳步、循环论证、或者中间计算错误。解法多样性看模型对同一道题生成的不同推理链如果所有链都一模一样说明探索不足需要调高温度或增加采样数。迭代优化的节奏是每跑完一轮完整训练做一次全面评估找出最弱的环节针对性改进。如果正确率上不去但格式很好可能是奖励信号太稀疏需要加强过程奖励。如果正确率高但推理链质量差可能是过程奖励权重太低模型只关心答案不关心过程。如果训练后期正确率反而下降大概率是过拟合或者KL约束失效需要早停或者调大KL系数。我自己的项目里从冷启动到最终模型大概迭代了十几轮每轮都有明确的改进目标。最有效的一次改进是把过程奖励从逐token改成按步骤计算训练稳定性提升了一大截。最坑的一次是盲目加大过程奖励权重结果模型学会了写漂亮但无用的推理白白浪费了两周算力。5. 常见问题与排查技巧实录5.1 训练不收敛或奖励震荡这是最常见的问题表现是平均奖励上下大幅波动正确率不升反降。原因通常有三个学习率太大、batch太小、或者奖励信号噪声太大。排查顺序是先看学习率把它降到原来的三分之一再跑几百步如果震荡减轻就是学习率问题。如果降了还震荡检查batch size把每条题的采样数K翻倍或者增加题目数。如果还不行就是奖励信号本身噪声大需要检查验证器是否有误判或者过程奖励模型是否校准到位。我遇到过一次特别隐蔽的情况验证器对某类题目的答案判断有bug把正确答案判成错误导致模型收到矛盾的奖励信号。这种问题只能靠人工抽检验证器的输出发现建议每隔一段时间就手动检查一批验证结果。5.2 模型学会钻奖励空子奖励黑客是强化学习里的经典问题在数学推理场景下表现得很隐蔽。我见过几种典型模式一是生成超长推理链把过程奖励的均值拉高但实际逻辑空洞二是反复重复同一句话因为格式奖励对重复没有惩罚三是直接输出最终答案不写过程因为结果奖励只看答案对不对。对付奖励黑客核心思路是让奖励函数尽量难以被简单策略欺骗。具体手段包括对推理链长度设上限超过就扣分对重复内容做惩罚要求必须有推理过程才给结果奖励。另外定期用人工评估检查模型输出一旦发现新的钻空子模式就针对性修补奖励函数。提示奖励函数的设计是一个持续对抗的过程不要指望一次设计就能一劳永逸。建议每轮训练后都做一次奖励黑客检查。5.3 推理链质量差但答案正确这种情况说明模型学会了“蒙对答案”推理过程完全是错的或者无关的。根源通常是结果奖励权重过高过程奖励形同虚设。解决办法是提高过程奖励的权重同时降低结果奖励的权重让模型意识到过程质量也重要。但过程奖励权重也不能无限提高否则会走向另一个极端模型只顾过程漂亮不管答案对错。我的经验是结果奖励和过程奖励的权重比控制在7比3到8比2之间比较合适。如果推理链质量还是差可以考虑引入对抗训练用一个判别器专门识别“过程漂亮但答案错”的推理链给这类样本额外的负奖励。5.4 训练后期性能退化训练后期正确率不升反降通常是过拟合或者策略崩溃。过拟合的表现是训练集正确率继续上升但验证集下降这时候需要早停或者加正则。策略崩溃的表现是生成质量突然变差推理链变得混乱这通常是KL约束失效或者学习率在后期没有衰减。我的处理方式是训练后期把学习率线性衰减到初始值的十分之一同时把KL系数逐步调大让策略更新越来越保守。另外保留每一轮的最优模型 checkpoint不要只用最后一轮的模型。我一般会保存验证集正确率最高的那个 checkpoint 作为最终模型。5.5 常见问题速查表问题现象可能原因排查方法解决手段奖励震荡不收敛学习率过大、batch过小、奖励噪声大逐步降低学习率、增大采样数、检查验证器调小学习率、增大batch、校准奖励推理链冗长空洞过程奖励权重过高、长度无惩罚检查过程奖励权重、统计生成长度分布降低过程奖励权重、加长度惩罚答案对但过程错结果奖励权重过高人工抽检推理链质量提高过程奖励权重、引入对抗判别训练后期退化过拟合、KL约束失效对比训练集和验证集曲线、监控KL散度早停、学习率衰减、调大KL系数格式合规率低格式奖励权重不足统计格式违规类型提高格式奖励权重、优化输出模板采样效率低温度过低、采样数不足统计正确样本占比调高温度、增加采样数6. 我踩过的坑和几条实用心得第一条心得是关于冷启动的。我一开始想跳过冷启动直接上PPO结果模型连基本输出格式都学不会采样出来的东西全是乱码奖励信号完全没法用。后来老老实实先做监督微调把格式和基本解题模式教会再切强化学习效率高了很多。冷启动这一步不能省它是整个流程的地基。第二条是关于奖励权重的。我试过很多组权重配置最后发现没有一组是万能的。不同难度、不同类型的题目最优权重都不一样。我的做法是把权重做成可配置的训练过程中根据验证集表现动态调整。比如发现推理链质量下降就调高过程奖励发现正确率停滞就调高结果奖励。这种动态调整比固定权重效果好不少。第三条是关于评估的。不要只看最终准确率一定要看推理链。我见过太多模型准确率不错但推理过程一塌糊涂的情况这种模型在实际应用里根本没法用因为用户需要看到可信的解题过程。评估的时候至少抽检一百条推理链人工判断逻辑是否连贯、步骤是否完整、有没有跳步或循环论证。第四条是关于算力预算的。数学推理强化学习非常吃算力采样和验证的开销远大于普通监督学习。我建议在开始之前先估算一下预算每条题采样K条链每条链平均L个token每轮训练N道题跑M轮总共需要生成多少token验证器需要跑多少次。这个估算能帮你判断方案是否可行避免跑到一半发现算力不够。最后分享一个提高采样效率的小技巧对难题做难度分层采样。简单题采样少一点难题采样多一点把算力集中在模型还不会的题目上。具体做法是先用当前模型对题目集做一次快速评估按正确率把题目分成易、中、难三档采样时给难题分配更多的采样条数。这个技巧能让同样的算力预算下训练效率提升百分之二三十。