强化学习训练PAPO方法
目录
先用“答对”保方向,再用“过程质量”做精修,并且两者分开处理,避免模型靠啰嗦作弊。
当然,三个缩写的全称如下:
- ORM = Outcome Reward Model
(结果奖励模型) - PRM = Process Reward Model
(过程奖励模型) - PAPO = Process-Aware Policy Optimization
(过程感知策略优化)
在训练推理模型时,常见有两种打分方式:
-
只看结果对不对(ORM)
- 好处:简单直接
- 问题:只要答案对,过程乱写也一样得高分。
- 结果:模型可能“蒙对”,但推理质量不提升。
- 另外,当一组回答都对了,模型就不知道该向谁学习(奖励信号变弱)。
-
看推理过程好不好(PRM)
- 好处:能区分“谁推理更清晰、更严谨”
- 问题:模型会“刷分作弊”,比如写很长很啰嗦的过程来骗高分(reward hacking),最后准确率反而掉了。
论文提出的 PAPO,核心思路是:
把“结果分”和“过程分”分开计算、分开归一化,再合起来训练。
你可以把它理解成老师评分:
- 结果分(A_out):先保证题做对(底线)
- 过程分(A_proc):只在“已经做对的人”里比较谁解题过程更好(拔高)
这就避免了两种极端:
- 只看结果 → 思路质量上不去
- 只看过程 → 容易啰嗦作弊
为什么“分开归一化”这么关键?
通俗讲:
如果把全班都混在一起按过程打分,错题但写超长的人可能分还挺高,训练方向就歪了。
PAPO 改成:先看对错,再在正确答案内部比过程质量,就不会让“错误但啰嗦”占便宜。
是的,这篇论文的实现核心可以用一条“训练流水线”讲清楚。你不用懂太多公式,也能明白它怎么做。
PAPO 训练怎么实现(通俗版)
它基于 GRPO 做了一个改造:
每轮采样一组回答,然后分两路打分,再合成一个训练信号。
第 1 步:对同一个题目,生成一组回答
比如同一个数学题,模型一次生成 8 个解答(一个 group)。
第 2 步:给每个回答打“结果分”(ORM)
- 看最终答案对不对(对=高,错=低)
- 这是 correctness 信号(底线)
第 3 步:给回答打“过程分”(PRM)
- 看推理步骤是否规范、清晰、符合 rubric(评分标准)
- 这是 reasoning quality 信号(上限)
第 4 步:关键改造——“分开归一化”
这是 PAPO 的核心,不是简单把两种分数加起来。
4.1 结果优势 (A_out)
- 用 ORM 分数算
- 在整组回答里做归一化(对+错都参与)
- 作用:保证训练方向始终锚定“答对”
伪代码
太好了,给你一个工程视角的 PAPO 伪代码(简化版),你能直接看懂它怎么接到 GRPO 里。
# 输入:
# q: 一个问题
# policy: 当前模型
# ORM: 结果打分器(只看答案对错)
# PRM: 过程打分器(看推理质量)
# K: 每题采样回答数(group size)
def papo_train_step(q, policy, ORM, PRM, K=8):
# 1) 采样一组回答
responses = [policy.generate(q) for _ in range(K)]
# 2) 打结果分(Outcome scores)
# 例如:答对=1,答错=0,或概率分
out_scores = [ORM.score(q, r) for r in responses]
# 3) 标记哪些是“正确回答”
correct_mask = [s > 0.5 for s in out_scores] # 示例阈值
# 4) 打过程分(Process scores)
# PRM可用rubric评分:步骤完整性、逻辑性、简洁性等
proc_scores = [PRM.score(q, r) for r in responses]
# 5) 计算 A_out:在全组上归一化(对+错都参与)
# 作用:锚定正确性
A_out = normalize_over_group(out_scores) # z-score或rank normalize
# 6) 计算 A_proc:只在“正确回答子集”中归一化
# 作用:比较“正确答案之间”的推理质量
A_proc = [0.0] * K
correct_idx = [i for i, ok in enumerate(correct_mask) if ok]
if len(correct_idx) >= 2:
corr_proc = [proc_scores[i] for i in correct_idx]
corr_proc_norm = normalize_over_subset(corr_proc)
for j, i in enumerate(correct_idx):
A_proc[i] = corr_proc_norm[j]
# 若正确样本太少,可退化为全0或小权重
# 7) 合成总优势(核心)
# alpha, beta 控制结果信号与过程信号权重
alpha, beta = 1.0, 0.5
A = [alpha * A_out[i] + beta * A_proc[i] for i in range(K)]
# 8) 用总优势A做 GRPO/PPO 风格更新
# (logprob ratio + clip + KL penalty 等)
loss = grpo_objective(policy, q, responses, advantages=A)
policy.optimize(loss)
return loss
这段代码的关键点(你记这3句就够)
A_out全组归一化:保证“答对”永远是主目标A_proc仅正确子集归一化:只在“答对的人里”比谁推理更好A = A_out + A_proc:先保底,再拔高
如果你要工程落地,最容易踩的坑
- PRM评分不稳:先做 rubric 规则,避免“越长分越高”
- 正确样本太少:
A_proc会稀疏,前期可降低beta - 权重设置:一般先高
alpha、低beta,后期再慢慢提高beta - 长度作弊:给 PRM 增加“冗长惩罚项”或长度归一化
如果你愿意,我下一步可以给你一个更贴近真实训练框架(TRL/GRPO)的版本,把 normalize 和 objective 也展开成可实现模块清单。
4.2 过程优势 (A_proc)
- 用 PRM 分数算
- 只在答对的回答子集里归一化
- 作用:只比较“正确答案之间谁过程更好”,避免错误答案靠啰嗦拿高分
第 5 步:合成总优势
把两部分组合成总训练信号:
- 一部分保“对错”
- 一部分提“过程质量”
然后按 GRPO/PPO 风格做策略更新(更新模型参数)。
为什么这样能避免“啰嗦刷分”
如果不分开,PRM 容易被钻空子:
模型可能写特别长、特别花哨,但答案错了,也拿到高过程分。
PAPO 的限制是:
- 错答案先在结果分上吃亏
- 过程分主要只在正确答案里比较
所以模型会学到:
- 先答对
- 再把过程写好
而不是“胡写长文骗分”。
你可以把它理解成“考试评分机制升级”
- ORM:只看最后答案
- PRM:看解题步骤
- PAPO:先卡答案正确,再在正确答案里比步骤质量
这就是它训练上比纯 ORM 更持续提升的原因。
如果你愿意,我可以下一步给你一个“伪代码版本”(10行左右),把 PAPO 在 GRPO 里怎么接进去写成工程视角流程。

浙公网安备 33010602011771号