Skip to content

输入关键词开始搜索

Grounding 视觉定位任务中的 GRPO 单步训练流程

本文记录我学习 PR1 项目、Grounding 视觉定位任务与 GRPO 训练流程 的过程。

这次学习最想弄清楚的不是 GRPO 的抽象定义,而是一条训练样本进入系统之后,究竟发生了什么:

同一张图片和同一个文本 Prompt
生成 56 个不同候选框
计算格式奖励和 IoU² 奖励
按组计算相对优势
把优势分配到回答 token
通过策略梯度更新模型参数

为了把整个过程落到具体数值上,本文始终使用同一个例子:

图片中有一只猫和一只狗
任务要求模型标出猫的位置
GT 坐标为 [0.20, 0.30, 0.60, 0.70]

这份笔记主要解决几个容易混淆的问题:

  • 一个训练 Step 中到底有几个不同 Prompt?
  • 为什么相同 Prompt 能生成 56 个不同回答?
  • GT 已经存在,为什么这种训练仍然属于强化学习?
  • 奖励和优势有什么区别?
  • 为什么奖励较高的回答可能得到负优势?
  • completion_mask、KL 和 ratio 分别有什么作用?
  • PR1 的思路能给多模态心理支持项目带来什么启发?

Grounding 可以先理解为:

模型不仅要理解文字要求,还要在图片中找到文字所指向的具体目标,并输出目标所在的视觉区域。

例如,输入图片中同时包含猫和狗,文本要求是:

请用 <box>x1,y1,x2,y2</box> 的格式,标注出图中猫的位置。

模型不能只回答:

猫在图片左侧。

它必须输出一个结构化的边界框:

<box>0.21,0.31,0.59,0.69</box>

四个数字分别表示:

x1:左边界
y1:上边界
x2:右边界
y2:下边界

这里使用的是归一化坐标,因此所有数字都位于 0~1 之间,不依赖图片的实际像素尺寸。


本文中的数值例子采用以下配置:

项目数值或含义
输入包含一只猫和一只狗的室内图片
任务定位图片中的猫
GT 坐标[0.20, 0.30, 0.60, 0.70]
GPU 数量7 张
单卡 batch8
全局生成数7 × 8 = 56
示例分组大小每组 8 个回答
KL 系数β = 0.01
格式错误奖励0
格式正确奖励IoU²

最重要的一点是:

在这个示例里,一个训练 Step 只处理一个唯一 Prompt,而不是 56 个不同问题。

56 条输入在语义上完全相同,只是为了让模型针对同一道题采样出多个不同回答。

PR1 Grounding 单步训练完整流程

需要注意,本文中的“7 组、每组 8 个回答”是这份示例配置下的并行与分组方式。不同代码库对全局 batch、生成数量和 group size 的组织方式可能不同,但 GRPO 的核心仍然是:

同一输入生成多个候选回答
在候选回答之间进行相对比较

IoU 全称为:

Intersection over Union

中文一般称为:

交并比

它衡量模型预测框与人工标准框的重合程度:

IoU = 预测框与 GT 的交集面积 / 预测框与 GT 的并集面积

取值范围为:

0 ≤ IoU ≤ 1

其中:

IoU含义
0两个框完全没有重合
接近 0.5有一定重合,但定位仍然比较粗糙
接近 1预测框与 GT 高度重合
1两个框完全一致

GT 为:

[0.20, 0.30, 0.60, 0.70]

一个高质量预测为:

[0.21, 0.31, 0.59, 0.69]

GT 的宽和高分别为:

0.60 - 0.20 = 0.40
0.70 - 0.30 = 0.40

因此 GT 面积为:

0.40 × 0.40 = 0.16

预测框位于 GT 内部,其面积为:

(0.59 - 0.21) × (0.69 - 0.31)
= 0.38 × 0.38
= 0.1444

交集面积为 0.1444,并集面积为 0.16,因此:

IoU = 0.1444 / 0.16 ≈ 0.9025

如果奖励使用 IoU²

reward = 0.9025² ≈ 0.8145

这和 PPT 中高质量候选获得约 0.8 奖励的数量级是一致的。

这里没有直接把 IoU 当作奖励,而是使用:

reward = IoU²

平方会进一步压低不够准确的候选框:

IoUIoU²
0.90.81
0.70.49
0.50.25
0.30.09

这样设计后,模型不能只满足于“大致框到猫”,而会得到更强的动力去缩小预测框与 GT 之间的偏差。

不过,奖励函数的形状也会直接决定模型偏好的行为。使用平方意味着对中低质量候选的惩罚更明显,因此它是一种任务设计选择,而不是唯一正确的写法。


单个 Prompt 的训练流程可以整理为:

Step 0:采样同一条训练样本,并复制为多份
Step 1:模型随机生成 56 个候选回答
Step 2:计算训练模型和参考模型的逐 token 对数概率
Step 3:计算每个回答的格式奖励与 IoU² 奖励
Step 4:在每组内部进行标准化,得到相对优势
Step 5:把优势转化为 token 级损失并反向传播

GRPO Step0 到 Step5 总览

这条主线可以压缩成一句话:

采样负责制造同题多答案,奖励负责评价绝对质量,组内归一化负责得到相对优势,策略损失负责提高好回答的生成概率并降低差回答的生成概率。


5. Step 0:同一 Prompt 的 56 份拷贝

Section titled “5. Step 0:同一 Prompt 的 56 份拷贝”

假设训练集一共有 5000 条数据,打乱之后当前取到的样本编号是:

idx = 123

RepeatRandomSampler 将这个索引连续重复 8 次:

[123, 123, 123, 123, 123, 123, 123, 123, ...]

在这份示例中,7 张 GPU 使用相同的采样顺序,每张卡当前都拿到 8 份编号为 123 的样本:

GPU0:8 份 idx=123
GPU1:8 份 idx=123
GPU2:8 份 idx=123
GPU3:8 份 idx=123
GPU4:8 份 idx=123
GPU5:8 份 idx=123
GPU6:8 份 idx=123

全局合计:

7 张 GPU × 每卡 8 份 = 56 份相同 Prompt

Step 0 数据采样

打乱数据的目的不是产生 56 个不同回答,而是打乱训练样本出现的顺序,避免模型长期按照固定排列学习。

真正让同一道题产生不同回答的步骤发生在 Step 1 的随机生成阶段。

这里的 batch 看起来有 56 条数据,但从“唯一问题”的角度看只有 1 条:

唯一 Prompt 数量 = 1
Prompt 副本数量 = 56
候选回答数量 = 56

下一个训练 Step 才会切换到另一个样本,例如 idx=287


6. Step 1:一个 Prompt 生成 56 个不同回答

Section titled “6. Step 1:一个 Prompt 生成 56 个不同回答”

56 份输入虽然完全相同,但模型生成时使用随机采样,因此输出不会完全一致。

例如:

质量模型输出
高质量<box>0.21,0.31,0.59,0.69</box>
中等质量<box>0.15,0.25,0.50,0.65</box>
低质量<box>0.70,0.40,0.90,0.80</box>,框到了狗
格式错误猫在图片的左侧位置

Step 1 vLLM 批量生成

同一个 Prompt 能生成不同回答,主要来自:

temperature
随机采样
不同 token 路径

可以把这一阶段理解为:

模型针对同一道题提交了 56 份不同答卷,后续奖励函数负责批改这些答卷。

重复 Prompt 还可以复用相同的输入前缀计算。在支持前缀缓存的推理框架中,相同图文输入不必被完整重复计算,从而降低批量生成的开销。


7. Step 2:逐 token 对数概率与 KL 散度

Section titled “7. Step 2:逐 token 对数概率与 KL 散度”

生成完回答后,系统将 Prompt 和回答拼接起来,再分别送入:

当前训练模型
参考模型

训练模型输出:

per_token_logps

参考模型输出:

ref_per_token_logps

Step 2 对数概率与 KL

假设回答被分词为:

<box>
0.21
,
0.31
,
0.59
,
0.69
</box>

模型会给每个实际生成 token 一个概率,例如:

P("<box>")
P("0.21" | 前面的内容)
P("," | 前面的内容)
...

程序通常使用对数概率:

log P(token_t | previous tokens)

因为多个 token 的概率连乘容易变得非常小,而取对数后可以把乘法转化为加法,计算更稳定。

参考模型可以理解为训练开始时策略模型的一份冻结副本。

它不参与参数更新,主要作用是判断:

当前训练模型是否已经偏离原始模型太远

如果训练模型为了追求奖励而发生剧烈变化,KL 正则会对这种偏离施加惩罚。

7.3 completion_mask 为什么只保留回答部分

Section titled “7.3 completion_mask 为什么只保留回答部分”

整个序列包含:

Prompt + Completion + EOS + Padding

但策略梯度真正需要优化的是模型自己生成的回答,因此 mask 通常为:

部分mask是否进入策略损失
Prompt0
回答 token1
EOS 后的 padding0

也就是说:

Prompt 只是条件,不是当前这次采样要奖励或惩罚的动作;真正的动作是模型生成的回答 token。


每个回答首先进行格式检查。

规则为:

格式错误 → reward = 0
格式正确 → reward = IoU²

Step 3 奖励计算

Grounding 不仅要求模型“知道猫在哪里”,还要求它按系统可解析的方式输出:

<box>x1,y1,x2,y2</box>

如果模型回答:

猫在左边。

即使语义上大致正确,程序也无法把它稳定转换成可验证的预测框,因此直接给 0 分。

这体现了 PR1 的一个重要思想:

奖励不仅评价内容是否正确,也评价结果是否结构化、可解析和可验证。

假设 GPU0 的 8 个回答奖励为:

[0.85, 0.72, 0.49, 0.36, 0.16, 0.04, 0, 0]

7 张 GPU 各自计算本地奖励后,通过通信汇总得到 56 个标量奖励。

此时的 reward 表示:

回答本身的绝对质量

下一步的 advantage 表示:

回答在自己这一组中的相对质量

这两者不能混为一谈。


9. Step 4:组内归一化得到相对优势

Section titled “9. Step 4:组内归一化得到相对优势”

GRPO 的核心之一,是用同组回答的统计量代替单独训练一个价值模型。

示例中的优势计算为:

advantage = (reward - mean(group)) / (std(group) + 1e-4)

其中:

mean(group):本组平均奖励
std(group):本组奖励标准差
1e-4:防止标准差接近 0 时发生除零

Step 4 组内优势估计

奖励为:

[0, 0, 0.04, 0.16, 0.36, 0.49, 0.72, 0.85]

其均值约为:

mean ≈ 0.328

因此:

rewardadvantage解释
0.85+1.63远高于本组平均
0.72+1.22明显高于本组平均
0.36+0.10只略高于平均
0-1.02低于平均

奖励为:

[0.64, 0.68, 0.72, 0.76, 0.79, 0.81, 0.84, 0.88]

虽然 0.64 的绝对奖励不低,但它是本组最差回答,因此可能得到:

advantage = -1.64

模型会降低未来生成这类回答的相对概率,因为在这批优秀候选中,它仍然属于较差选项。

奖励为:

[0, 0, 0.01, 0.04, 0.09, 0.12, 0.16, 0.20]

0.20 的绝对质量并不高,但它是本组最优回答,因此可能获得:

advantage = +1.58

这并不表示模型认为 0.20 已经足够好,而是表示:

在当前这一组失败或低质量探索中,这个方向最值得保留。


10. 为什么同一奖励在不同组里含义不同

Section titled “10. 为什么同一奖励在不同组里含义不同”

同一奖励在不同组中的相对含义

示例中出现了三个看起来反直觉的结果:

所在组reward组内位置advantage
整体高质量组0.64本组最差-1.64
好坏参半组0.36略高于平均+0.10
整体低质量组0.20本组最好+1.58

因此:

高 reward 不保证正 advantage
低 reward 也不保证负 advantage

优势回答的问题不是:

这个答案绝对好不好?

而是:

这个答案和同组其他候选相比好不好?

如果完全按照绝对奖励进行更新,已经能生成高质量回答的简单样本可能长期占据较强梯度,而困难样本中的局部改进不容易得到足够信号。

组内归一化可以让不同质量区间都产生:

正优势回答
负优势回答
接近零的回答

这样即使一组整体较差,也能告诉模型:

在这些失败尝试中,哪一种失败相对更好

模型可以逐步改善:

IoU 0.1
IoU 0.3
IoU 0.5
IoU 0.8

而不是必须一次从完全错误跳到完美答案。

为什么采用组内相对优势

相对优势也意味着结果会受到组内样本构成影响。

同一个回答被放到不同组中,优势可能改变。因此训练时需要关注:

group size
采样多样性
奖励方差
全组奖励是否相同

如果一组回答几乎完全一样,标准差接近 0,这一组能够提供的区分信号就会很弱。


11. Step 5:优势如何变成模型参数更新

Section titled “11. Step 5:优势如何变成模型参数更新”

得到 advantage 后,系统需要把回答级别的好坏信号分配到回答中的 token。

PPT 中使用了一个简化示例:

ratio = exp(logp_new - stopgrad(logp_old))
= 新概率 / 旧概率
= 1.15

对于一个优势为 +1.63 的回答:

policy term = -ratio × advantage
= -1.15 × 1.63
≈ -1.87

KL 项为:

KL term = β × KL
= 0.01 × 0.02
= 0.0002

总的 token loss 近似为:

token loss ≈ -1.87 + 0.0002
≈ -1.87

Step 5 损失计算与反向传播

advantage更新方向
正数提高生成该回答 token 的概率
负数降低生成该回答 token 的概率
接近 0更新幅度很小

因为只对 completion_mask=1 的 token 求平均,所以 Prompt 和 padding 不会直接承担这次奖励信号。

stopgrad(logp_old) 表示:

把旧策略的 log probability 当成固定常数
不允许梯度通过它反向传播

训练只更新当前策略模型,而不会把“旧概率”也一起改掉。

奖励会推动模型朝更高分回答移动,但如果只有奖励,模型可能为了钻奖励函数漏洞而迅速偏离原始语言能力。

KL 正则限制:

当前策略模型不要离参考模型太远

因此可以把两部分理解为:

奖励项:油门
KL 项:刹车

这里的 1.15 是为了演示损失方向而设定的数值。

在某些实现中,如果刚生成完回答便立即用完全相同的策略计算 logp_oldlogp_new,首次计算时 ratio 会非常接近 1;经过后续优化内循环或参数变化后,ratio 才会偏离 1

实际 GRPO/PPO 风格实现还可能加入 clipping:

min(ratio × A, clip(ratio) × A)

用于避免单次策略更新幅度过大。本文保留 PPT 中的简化公式,是为了先看清 advantage 如何控制概率增减。


12. 梯度累积决定真正的参数更新粒度

Section titled “12. 梯度累积决定真正的参数更新粒度”

示例中设置:

gradient_accumulation_steps = 2

因此:

第 1 个 Prompt:只执行 loss.backward()
第 2 个 Prompt:再次 backward,然后 optimizer.step()

一次真正的参数更新共看过:

2 个唯一 Prompt
2 × 56 = 112 个候选回答

所以需要区分三个概念:

概念本例数量
单 Step 的唯一 Prompt1
单 Step 的候选回答56
一次 optimizer 更新覆盖的 Prompt2
一次 optimizer 更新覆盖的回答112

训练模型更新后,还需要把最新权重同步到负责生成的推理侧,保证下一轮候选回答来自较新的策略。


13. 有 GT,为什么仍然属于强化学习

Section titled “13. 有 GT,为什么仍然属于强化学习”

这是我学习过程中最容易困惑的问题。

Grounding 数据中明明存在正确框:

GT = [0.20, 0.30, 0.60, 0.70]

为什么不把它直接称为监督学习?

关键不在于“有没有标准答案”,而在于:

标准答案以什么方式参与参数更新

监督学习与强化学习的区别

监督学习会把 GT 直接作为目标,让模型模仿标准答案:

输入图片和 Prompt
教师直接给出标准输出框
计算预测与标准答案之间的监督损失
让模型逐渐逼近标准答案

例如可以直接回归四个坐标,或者把标准框序列作为 teacher forcing 的目标 token。

GRPO 训练中,模型先自己采样多个回答:

模型自由生成 56 个候选框
GT 只用于计算每个候选回答的奖励
将奖励转换成组内相对优势
根据优势提高或降低候选回答的概率

模型并没有逐 token 查看标准答案然后照着抄,而是只得到类似:

这个回答得了多少分
这个回答比同组其他回答好多少

因此,GT 在这里扮演的是:

奖励计算依据

而不是:

直接监督目标

可以类比为:

监督学习:老师展示标准答案,让学生照着学习
强化学习:学生先独立作答,老师只根据标准答案打分

两种方式都可以有标准答案,但学习机制不同。


14. GRPO 与传统强化学习有什么不同

Section titled “14. GRPO 与传统强化学习有什么不同”

经典强化学习常见于游戏或机器人控制:

状态
动作
环境变化
新的状态
长期累计奖励

而本文的 Grounding 生成更接近一个单轮决策任务:

图文 Prompt
生成完整回答
计算可验证奖励
结束当前 episode

它与传统强化学习相比有几个特点:

Grounding 的奖励来自:

格式是否合法
坐标是否可解析
预测框与 GT 的 IoU

不一定需要额外训练一个人工偏好奖励模型。

PPO 常用价值模型估计 baseline,而 GRPO 使用同一 Prompt 下多个候选回答的组内平均值与标准差构造相对优势。

因此它减少了单独价值模型带来的训练与显存开销。

14.3 强化学习对象是整段生成序列

Section titled “14.3 强化学习对象是整段生成序列”

模型的动作不是一个离散按钮,而是一串 token:

<box>0.21,0.31,0.59,0.69</box>

回答得到一个整体奖励,再通过策略梯度影响其中的生成 token。


PR1 的价值不只是把 Grounding 准确率提高,而是展示了一条比较清晰的训练路线:

多模态理解
+
结构化输出
+
机器可验证奖励
+
组内相对优化

PR1 的核心价值

普通多模态模型可能能够描述图片,但描述结果通常比较自由:

猫大概在图片左侧。

PR1 更强调把理解落实为可检查的结果:

<box>0.21,0.31,0.59,0.69</box>

只要输出能够结构化,就可以设计规则自动评价:

格式是否正确
目标是否定位正确
定位精度有多高
多个候选之间谁更好
策略是否偏离参考模型太远

这让强化学习不再依赖模糊的“感觉不错”,而是依赖机器可以重复计算的反馈。


在涉及人的多模态系统中,一个重要风险是:

模型把可观察到的外观或动作
直接解释成不可直接观察的心理结论

例如,仅根据一张图片就输出:

来访者处于某种心理状态。

这种推断可能缺乏充分依据。

借鉴 Grounding 的思路,可以先让视觉模块只报告可观察事实:

{
"observable_evidence": [
{
"region": [0.18, 0.12, 0.47, 0.54],
"type": "face_region",
"description": "面部区域持续朝下",
"confidence": 0.82
},
{
"region": [0.10, 0.20, 0.72, 0.95],
"type": "body_posture",
"description": "身体姿态变化较少",
"confidence": 0.74
}
],
"mental_state_conclusion": null
}

PR1 对多模态理解模块的启示

整个系统可以拆成:

图片或视频
视觉证据定位
结构化描述可观察事实
结合文本、语音和历史上下文
生成谨慎、有限度的解释与支持性回答

这里最关键的边界是:

视觉模块负责说明“看到了什么”,上层模块才负责结合更多信息进行有限推断,且不能把单一视觉信号直接等同于医学或心理诊断。


PR1 最值得借鉴的地方,是把一个模糊的“回答好不好”拆成多个可计算维度。

PR1 对评估模块的启示

面向多模态系统,可以考虑建立如下奖励:

奖励维度示例
格式奖励是否输出合法 JSON 或规定标签
证据定位奖励是否指出与描述对应的图像区域
Grounding 奖励预测框与标注框的 IoU
事实一致性奖励描述是否与图像证据一致
谨慎性奖励是否承认信息不足,避免过度推断
支持性奖励表达是否非评判、清晰、温和
KL 约束是否偏离参考模型过远

最终奖励可以写成加权组合:

R_total = w1 × R_format
+ w2 × R_grounding
+ w3 × R_evidence
+ w4 × R_safety
+ w5 × R_support

真正困难的地方不是写出这个公式,而是让每个子奖励:

可计算
不冲突
不容易被模型钻漏洞
与最终目标一致

18. 我对这套训练流程的阶段性理解

Section titled “18. 我对这套训练流程的阶段性理解”

完成这次拆解之后,我对 GRPO 的理解不再只是:

一种不需要 Critic 的强化学习算法

而是形成了更具体的流程:

同一道题生成多个答案
用可验证规则评价每个答案
不直接使用绝对分数,而是在组内比较
把相对优势分配给回答 token
提高相对好回答的概率
降低相对差回答的概率
用 KL 防止模型变化过猛

其中最关键的概念区别是:

概念回答的问题
GT正确答案是什么
reward当前回答本身有多好
advantage当前回答相对同组回答有多好
log probability模型生成这些 token 的概率有多大
ratio新旧策略对这些 token 的概率改变了多少
KL当前模型与参考模型相差多远
loss参数应该朝什么方向更新

这套方法虽然清晰,但仍有一些需要继续思考的问题。

同一 Prompt 需要生成 56 个回答,能够提供丰富的相对比较信号,但推理和显存成本也明显增加。

一个回答的 advantage 不只取决于它自己,还取决于同组其他回答。分组方式和采样质量会影响训练信号。

如果奖励只检查格式和 IoU,模型可能学习到一些并不符合真实需求、但容易拿高分的输出模式。因此奖励设计需要持续做鲁棒性检查。

IoU 很适合边界框定位,但对计数、OCR、关系理解、复杂推理等任务,需要设计不同的可验证奖励。

19.5 单步奖励不代表长期交互质量

Section titled “19.5 单步奖励不代表长期交互质量”

Grounding 是相对清晰的单轮任务,而多轮对话系统还涉及上下文一致性、长期安全性和用户体验,不能只依赖单轮分数。


接下来我准备继续补充几个方向:

  1. 阅读 PR1 的训练代码,核对 sampler、group size 与多卡通信的真实实现。
  2. 对照 GRPO 论文理解 clipping、KL estimator 和 loss 的完整公式。
  3. 进一步区分 old policy、reference policy 和 current policy。
  4. 尝试用少量候选框手算完整的 mean、std、advantage 与 loss。
  5. 分析当组内奖励全部相同时,训练信号如何处理。
  6. 研究 format reward、IoU reward 与其他视觉奖励的权重组合。
  7. 把“视觉证据定位—结构化事实—上层解释”的思路加入多模态项目设计。

这次学习可以用下面这条主线概括:

一个唯一 Grounding Prompt
复制为 56 份相同输入
随机生成 56 个不同候选框
格式检查 + IoU² 得到绝对奖励
每组内部标准化得到相对优势
正优势提高回答 token 概率
负优势降低回答 token 概率
KL 限制模型偏离参考策略
梯度累积后更新模型参数

我目前最核心的理解是:

GRPO 并不是让模型直接模仿 GT,而是让模型先探索多个回答,再用 GT 构造可验证奖励,通过组内比较学习哪些生成路径相对更好。

PR1 对我的最大启发也不只是“把 GRPO 用到视觉任务”,而是:

先把复杂能力转化为结构化、可定位、可验证的输出,再设计机器能够稳定计算的奖励,让强化学习围绕明确规则进行优化。