Rethinking Token-Level Policy Optimization for Multimodal Chain-of-Thought

Authors: Yunheng Li*, Hangyi Kuang*, Hengrui Zhang, Jiangxia Cao, Zhaojie Liu, Qibin Hou†, Ming-Ming Cheng Affiliations:

  1. VCIP, School of Computer Science, Nankai University
  2. Kuaishou Technology Notes: * Equal Contribution; † Corresponding author arXiv: 2603.22847 GitHub: xzxxntxdy/PEPO

1. Motivation(研究动机)

这篇论文关注的是 LVLM 在 Multimodal Chain-of-Thought(CoT)中的 token-level 强化学习优化。作者认为,现有 Reinforcement Learning with Verifiable Rewards(RLVR)方法虽然已经可以提升多模态推理性能,但大多仍把整条 reasoning trajectory 当成一个整体来优化:只给整条回答一个 sequence-level advantage,再把同一个 advantage 平均地施加到所有 token 上。

问题在于,多模态 CoT 里不同 token 的作用明显不一样:

  • 有些 token 直接锚定视觉证据,比如几何图中的 angle、segment、parallel、intersection 等;
  • 有些 token 则更像 reasoning transition,例如 “therefore / check / alternatively / suppose”等,承担探索、修正和转折作用;
  • 还有不少 token 对最终正确性贡献很小,如果给它们与关键 token 相同的优化强度,会稀释实际有效的学习信号。

作者进一步指出,两类已有细粒度方法都有局限:

  1. 纯 entropy-based token weighting 可以鼓励探索,但它相关反映 textual uncertainty,对视觉语义的感知很弱;
  2. perception-aware RL 虽然尝试引入视觉信息,但常依赖额外 masking branch 或 attention-based 模块,推理/训练开销更大,也不够容易嫁接到现有高效 RL 框架里。

因此,这篇论文关注的重点问题是:能否在不引入额外监督、额外分支和明显额外开销的前提下,把 sequence-level RL 信号改造成适合 LVLM 的 token-level 优化信号?

这个问题关系到多模态 RL 是否能从“整句级别的粗粒度奖励”走向“与视觉 grounding 和 reasoning dynamics 对齐的细粒度 credit assignment”。如果这一点做不好,模型会继续出现两类常见失败:

  • reasoning token 很长,但实际和图像相关的关键 token 没有被突出优化;
  • entropy 被过度利用或过度压缩,导致训练要么塌缩、要么过于随机。

2. Idea(重点思想)

论文的重点思想可以概括为一句话:把多模态推理中的 token-level 优化分成 perception 与 exploration 两条信号,再通过平滑门控把二者融合成 token weight,用来重分配 sequence-level advantage。

更具体地说,作者先通过 token-level 分析证明:

  • 正确回答通常依赖一小部分 high visual similarity tokens,这些 token 的 hidden state 与 vision tokens 更接近,说明它们承担了视觉 grounding;
  • 同时,高 entropy token 往往出现在 reasoning 的转折、验证、修正、选择阶段,反映探索与不确定性;
  • 因而多模态 CoT 的关键,不是只看 perception,也不是只看 entropy,而是要同时建模二者的互补性。

在此基础上,作者提出 Perception-Exploration Policy Optimization(PEPO)

  • 用 response token 与 vision token hidden states 的相似度构造 perception prior
  • 用输出 logits 的 token entropy 构造 exploration signal
  • 对二者做 per-response min-max normalization,再通过一个 smooth gate 融合;
  • 把融合得到的 token weight 乘到原本的 sequence-level advantage 上,形成 token-level advantage;
  • 最终把这个机制插入 DAPO - An Open-Source LLM Reinforcement Learning System at Scale / GRPO 风格的 RLVR 训练里,得到 PEPO_GPEPO_D

与已有方法相比,一个区别在于:PEPO 不直接把视觉信息当 reward,也不额外学一个 token mask 分支,而是利用 policy model 自身 hidden states 中已经存在的视觉对齐结构来构造 perception prior。 这一设计保留了视觉信息,并保持了相对轻量的实现形式。

3. Method(方法)

3.1 整体框架

Figure 1 解读:这是论文的总览图(paper Figure 1)。左侧说明作者的判断:有效的 multimodal reasoning 不是单独依赖 perception,也不是单独依赖 exploration,而是两者的乘积关系。中间对比了传统 sequence-level optimization 与 PEPO:传统做法把同一个 advantage 均匀施加到所有 token;PEPO 则先计算 visual similarity 和 entropy,再生成 token-level reweighting。右侧给出结论性结果:无论接到 GRPO 还是 DAPO 上,PEPO 都能带来一致增益。Figure 1 的组织方式对应论文的方法主线:先分析 token dynamics,再把分析结果转成训练算法。

PEPO 的完整流程可以概括为四步:

  1. 先按 GRPO/DAPO 的方式,对每个 query 采样一组回答并计算 sequence-level reward / advantage;
  2. 对每个 response token,计算它与 vision tokens 的 hidden-state visual similarity;
  3. 再计算对应 token 的 entropy,并和 perception prior 通过 smooth gate 融合,得到 token weight;
  4. 用这个 token weight 去重分配原本均匀的 advantage,使 policy gradient 更聚焦于“视觉锚定 + 推理探索”兼具的 token。

从公开代码看,作者并不是单独实现一套新 RL 框架,而是把这个机制嵌进现有 Swift RLHF runtime:

  • src/pepo/train/rlhf.py 通过 install_pepo_runtime()grpo trainer 映射到 pepo.train.grpo_trainer.PepoGRPOTrainer
  • src/pepo/train/args.py 增加了 gate_alphagate_temperatureimg_tokenuse_vision_weightsvision_score_type 等参数;
  • 实际的 token reweighting 逻辑集中在 src/pepo/train/grpo_trainer.py

3.2 Token-level 分析:为什么 perception 与 entropy 是互补的?

3.2.1 Visual similarity 分布分析

Figure 2 解读:这是论文 Figure 2(a),展示按问题聚合后的全局 visual similarity 分布 。正确回答对应的分布整体向右偏移,说明正确回答的 token 整体上与视觉 token 更接近。也就是说,正确推理并不是“纯语言链条”,而是更强依赖视觉证据支持的语言链条。

Figure 2 解读:这是论文 Figure 2(b),只看每个回答里 top-K visual similarity tokens 的分布 。正确回答相较错误回答的右移更明显,表明与推理正确性关系更强的并不是“所有 token 都更视觉相关”,而是一小簇 highly grounded tokens

Figure 2 解读:这是论文 Figure 2(c),只看 bottom-K visual similarity tokens 的分布 。正确与错误回答之间几乎没有明显分离,这进一步支持作者的结论:实际重要的是高 visual similarity 的那部分 token,而不是整条响应中所有 token 都要同等重视。

论文把 response token 的 visual similarity 定义为:

其中:

  • 是 transformer 层数;
  • 是 vision tokens 数;
  • 是第 层第 个 response token 的 hidden state;
  • 是第 层第 个 vision token 的 hidden state。

这个定义有两个特点:

  1. 完全不需要额外 supervision;
  2. 直接复用模型内部已有的跨模态表示结构。

公开代码中,对应实现就是 src/pepo/train/grpo_trainer.py 里的:

  • _compute_vision_scores_cosine()
  • _compute_vision_scores_l2()
  • _compute_vision_scores_l1()
  • _compute_vision_scores_dot()

公开代码默认使用 cosine similarity,这也与论文附录 Table 4 的结果一致;在该表中,cosine 的表现高于 L1/L2。

3.2.2 Hidden-state shift 与 word cloud 分析

Figure 3 解读:这是论文 Figure 3。左侧柱状图比较了“去掉图像输入”前后 token hidden states 的变化幅度,发现 high visual similarity token 的 representation shift 更大,说明它们依赖图像内容,而不是偶然和视觉 token 相似。中间和右侧的词云则进一步解释了两类 token 的语义角色:高 entropy token 更多是 verification、analysis、correction 之类的推理转折词;高 visual similarity token 更多是 angle、line、triangle、parallel 等带几何/空间含义的 perceptual terms。因此,Figure 3 把作者的经验结论变成了可视化证据:entropy 管探索,visual similarity 管 grounding。

论文附录里把 hidden-state shift 定义为:

这表明作者除了比较回答正确性外,还引入了更细粒度的 counterfactual probe:在相同问题与回答下移除图像输入时,高 visual similarity token 的 hidden-state shift 更明显。

3.3 PEPO 的重点机制

Figure 4 解读:这是论文 Figure 4,也是 PEPO 的详细算法框架图。上半部分显示 policy model 会输出 response tokens、vision tokens 对应的 layer-wise hidden states,以及 logits;中间部分计算 visual similarity 与 entropy;右侧通过 smooth gate 生成 token-wise weight;下半部分再把这个 weight 乘到 verifiable reward 诱导出的 advantage 上,形成最终 token-level update。Figure 4 相比 Figure 1 更偏“工程实现图”,它与公开代码里的 PepoGRPOTrainer 逻辑关系较为接近。

3.3.1 Background:GRPO 的 sequence-level advantage

PEPO 不是凭空构造一个新 RL objective,而是在 GRPO 上继续细化。GRPO 的 advantage 是:

这里 是第 个 response 的 group-relative advantage。传统 GRPO 会把这个 同样施加到该 response 的所有 token 上,这正是论文要改进的粗粒度 credit assignment。

3.3.2 Exploration modeling

token entropy 定义为:

其中 是词表, 是第 个 response 在 token 位置 的预测分布。高 entropy 往往对应模型还在犹豫、分支选择、验证或修正的位置。

公开代码里 entropy 由 swift_grpo.entropy_from_logits(logits) 直接计算,然后在 _get_pepo_per_token_outputs_single() 中与 visual similarity 一起送入后续门控。

3.3.3 Perception-exploration fusion

论文先在每个 response 内分别对 visual similarity 和 entropy 做 min-max normalization,得到 。接着构造 centered joint score:

再通过平滑门控生成 token weight:

其中:

  • 控制 gate strength;
  • 用来把 softmax 权重重新缩放到 unit-mean,使权重平均值为 1;
  • 这种设计保证了 entropy 只是在 visual grounding 的基础上做 modulation,而不是无差别放大所有高 entropy token。

公开代码里的实现更接近以下形式:

  • 先得到 v_normh_norm
  • 再令 mixed = v_norm + h_norm
  • gate = 1 + gate_alpha * tanh(mixed_centered)
  • gated_logits = vision_scores * gate / gate_temperature
  • 最后 softmax 后乘上 valid_counts,得到均值约为 1 的 vision_weights

这部分对应 src/pepo/train/grpo_trainer.py_get_pepo_per_token_outputs_single()。从公式与代码对照来看,公开实现与论文在这一点上的主线是一致的:softmax 前都使用了 perception score 与 gate 的组合作为权重构造依据;代码中再通过 gate_temperature、mask 处理和张量实现细节完成具体计算。

3.3.4 Token-level advantage 与 progressive scheduling

论文将 token-level advantage 写成:

其中 会从 0 线性增大到 1。这个设计的含义是:

  • 训练初期更接近原始 GRPO,先保持稳定;
  • 训练后期逐渐让 token weight 充分主导 credit assignment。

公开代码没有直接显式构造 A_t,而是采用等价的 loss reweighting 方式:

  • 先按 GRPO / BNPO 的方式得到 per_token_loss
  • 再根据训练进度 progress = global_step / max_steps,乘上 1 - progress + progress * vision_weights
  • 这样就在 loss 层完成了从 uniform weighting 到 PEPO weighting 的平滑过渡。

对应代码位置是 src/pepo/train/grpo_trainer.py:436-453

3.4 Pseudocode(基于公开代码整理的说明性伪代码)

下面的伪代码是根据公开仓库 https://github.com/xzxxntxdy/PEPO 已发布实现整理出的说明性伪代码,相关对应 src/pepo/train/grpo_trainer.pysrc/pepo/train/args.py 和训练脚本。它保留了公开实现的重点数据流与模块关系,但为了可读性做了适度简化,因此不应被理解为源码逐行转写。

组件 A:计算 perception prior(对应 _compute_vision_scores_*

import torch
import torch.nn.functional as F
 
 
def compute_visual_similarity(hidden_states, input_ids, img_token_id, logits_to_keep, score_type="cosine"):
    token_ranges = []
    for ids in input_ids:
        idxs = (ids == img_token_id).nonzero(as_tuple=True)[0]
        if idxs.numel() == 0:
            idxs = torch.arange(1, ids.numel(), device=ids.device)
        token_ranges.append(idxs)
 
    batch_size = input_ids.shape[0]
    device = hidden_states[0].device
    dtype = hidden_states[0].dtype
    scores = [torch.zeros(logits_to_keep, device=device, dtype=dtype) for _ in range(batch_size)]
 
    for layer_hidden in hidden_states:
        for row_idx, idxs in enumerate(token_ranges):
            vision_hidden = layer_hidden[row_idx].index_select(0, idxs)
            gen_hidden = layer_hidden[row_idx, -logits_to_keep:]
 
            if score_type == "cosine":
                gen_hidden = F.normalize(gen_hidden, dim=-1)
                vision_hidden = F.normalize(vision_hidden, dim=-1)
                sim_matrix = gen_hidden @ vision_hidden.T
                scores[row_idx] += sim_matrix.mean(dim=1)
            elif score_type == "dot":
                sim_matrix = gen_hidden @ vision_hidden.T
                scores[row_idx] += sim_matrix.mean(dim=1)
            elif score_type == "l2":
                dist = torch.cdist(gen_hidden, vision_hidden, p=2)
                scores[row_idx] += -dist.mean(dim=1)
            elif score_type == "l1":
                dist = torch.cdist(gen_hidden.float(), vision_hidden.float(), p=1)
                scores[row_idx] += -dist.mean(dim=1).to(dtype)
            else:
                raise ValueError(score_type)
 
    return torch.stack(scores, dim=0) / max(1, len(hidden_states))

组件 B:融合 perception 与 exploration,生成 token weights(对应 _get_pepo_per_token_outputs_single

import torch
import torch.nn.functional as F
 
 
def build_pepo_weights(model, inputs, temperature, gate_alpha, gate_temperature, img_token_id):
    logits_to_keep = inputs["logits_to_keep"]
    outputs = model(return_dict=True, output_hidden_states=True, **inputs)
    logits = outputs.logits[:, -(logits_to_keep + 1):-1, :] / temperature
    hidden_states = outputs.hidden_states
    input_ids = inputs["input_ids"]
    completion_mask = inputs["completion_mask"].bool()
 
    token_logps = F.log_softmax(logits, dim=-1).gather(
        dim=-1,
        index=input_ids[:, -logits_to_keep:].unsqueeze(-1),
    ).squeeze(-1)
    entropies = -(F.softmax(logits, dim=-1) * F.log_softmax(logits, dim=-1)).sum(dim=-1)
 
    vision_scores = compute_visual_similarity(
        hidden_states=hidden_states,
        input_ids=input_ids,
        img_token_id=img_token_id,
        logits_to_keep=logits_to_keep,
        score_type="cosine",
    )
 
    eps = 1e-6
    valid_counts = completion_mask.sum(dim=1, keepdim=True).clamp(min=1)
 
    v_min = vision_scores.masked_fill(~completion_mask, float("inf")).min(dim=1, keepdim=True).values
    v_max = vision_scores.masked_fill(~completion_mask, float("-inf")).max(dim=1, keepdim=True).values
    v_norm = (vision_scores - v_min) / (v_max - v_min).clamp(min=eps)
    v_norm = torch.where(completion_mask, v_norm, torch.zeros_like(v_norm))
 
    h_min = entropies.masked_fill(~completion_mask, float("inf")).min(dim=1, keepdim=True).values
    h_max = entropies.masked_fill(~completion_mask, float("-inf")).max(dim=1, keepdim=True).values
    h_norm = (entropies - h_min) / (h_max - h_min).clamp(min=eps)
    h_norm = torch.where(completion_mask, h_norm, torch.zeros_like(h_norm))
 
    mixed = v_norm + h_norm
    mixed_mean = (mixed * completion_mask).sum(dim=1, keepdim=True) / valid_counts
    mixed_centered = mixed - mixed_mean
    gate = 1.0 + gate_alpha * torch.tanh(mixed_centered)
 
    gated_logits = vision_scores * gate / gate_temperature
    masked_logits = torch.where(completion_mask, gated_logits, torch.full_like(gated_logits, -float("inf")))
    weights = torch.softmax(masked_logits, dim=1)
    vision_weights = weights * valid_counts.to(weights.dtype)
    return token_logps, entropies, vision_weights

组件 C:把 token weights 注入 policy loss(对应 _compute_loss_and_metrics

import torch
 
 
def compute_pepo_loss(
    per_token_logps,
    old_per_token_logps,
    advantages,
    completion_mask,
    vision_weights,
    epsilon_low,
    epsilon_high,
    beta,
    progress,
    ref_per_token_logps=None,
    loss_type="grpo",
):
    log_ratio = per_token_logps - old_per_token_logps
    coef_1 = torch.exp(log_ratio)
    coef_2 = torch.clamp(coef_1, 1 - epsilon_low, 1 + epsilon_high)
 
    per_token_loss1 = coef_1 * advantages.unsqueeze(1)
    per_token_loss2 = coef_2 * advantages.unsqueeze(1)
    per_token_loss = -torch.min(per_token_loss1, per_token_loss2)
 
    # PEPO scheduling: gradually move from uniform weighting to token weighting
    per_token_loss = per_token_loss * (1 - progress + progress * vision_weights)
 
    if beta != 0.0 and ref_per_token_logps is not None:
        per_token_kl = torch.exp(ref_per_token_logps - per_token_logps) - (ref_per_token_logps - per_token_logps) - 1
        per_token_loss = per_token_loss + beta * per_token_kl
 
    if loss_type == "grpo":
        loss = ((per_token_loss * completion_mask).sum(-1) / completion_mask.sum(-1).clamp(min=1.0)).mean()
    elif loss_type == "bnpo":
        loss = (per_token_loss * completion_mask).sum() / completion_mask.sum().clamp(min=1.0)
    else:
        raise ValueError(loss_type)
 
    return loss

组件 D:训练入口与 recipe 注册(对应 rlhf.py + scripts/train/*.sh

import os
import subprocess
import sys
from swift.trainers.trainer_factory import TrainerFactory
from swift.llm.train.rlhf import SwiftRLHF
 
 
def install_pepo_runtime():
    TrainerFactory.TRAINER_MAPPING["grpo"] = "pepo.train.grpo_trainer.PepoGRPOTrainer"
    TrainerFactory.TRAINING_ARGS_MAPPING["grpo"] = "pepo.train.args.PepoGRPOConfig"
 
 
class PepoSwiftRLHF(SwiftRLHF):
    args_class = PepoRLHFArguments
 
 
def _maybe_launch_with_torchrun(argv):
    nproc_per_node = os.getenv("NPROC_PER_NODE")
    if nproc_per_node is None:
        return
    cmd = [
        sys.executable,
        "-m",
        "torch.distributed.run",
        "--nproc_per_node",
        nproc_per_node,
        "--module",
        "pepo.train.rlhf",
        *argv,
    ]
    subprocess.run(cmd, check=True)
    raise SystemExit(0)
 
 
def main(argv):
    _maybe_launch_with_torchrun(argv)
    install_pepo_runtime()
    PepoSwiftRLHF(argv).main()

从公开 recipe 看,Qwen 的 Geometry3K 训练脚本 scripts/train/train_pepo_geometry3k_qwen25vl_3b.sh 里明确设置了:

  • --num_generations 8
  • --temperature 1.0
  • --top_p 1.0
  • --deepspeed zero2
  • --per_device_train_batch_size 2
  • --gradient_accumulation_steps 4
  • --img_token '<|image_pad|>'
  • --gate_alpha 0.10
  • --gate_temperature 1.8
  • --use_vision_weights true

这表明公开代码不只是概念性示例,而是给出了可直接运行的 release recipe。

3.5 Code-to-paper mapping table

Paper ConceptSource FileKey Class / Function说明
PEPO runtime 注入 Swift RLHFsrc/pepo/train/rlhf.pyinstall_pepo_runtime, PepoSwiftRLHF, _maybe_launch_with_torchrun把公开实现注册为 grpo trainer,并兼容 torchrun
PEPO 专属参数src/pepo/train/args.pyPepoRLHFArguments, PepoGRPOConfig增加 gate_alphagate_temperatureimg_tokenuse_vision_weightsvision_score_type
Perception prior 计算src/pepo/train/grpo_trainer.py_compute_vision_scores_cosine, _compute_vision_scores_l2, _compute_vision_scores_l1, _compute_vision_scores_dot对应论文里的 visual similarity / perception prior
Perception + exploration 融合src/pepo/train/grpo_trainer.py_get_pepo_per_token_outputs_single, _get_pepo_per_token_outputs_chunked对应论文里的 Eq. (4)-(6) 和 smooth gate
Token-level loss 重加权src/pepo/train/grpo_trainer.py_compute_loss_and_metrics用训练进度 progress 把 uniform weighting 平滑过渡到 PEPO weighting
Format / accuracy rewardsrc/pepo/rewards/plugin.pyFormat, QA_AccuracyGeometry3K 公开训练依赖的 verifiable rewards
Geometry3K 数据路径重写src/pepo/data/resolve_image_paths.pyresolve_path, rewrite_record把 JSONL 中相对图像路径重写为绝对路径
Geometry3K avg@N 评估src/pepo/evaluation/evaluate_geometry3k.pybatched_generate, majority_vote, qa_accuracy对应论文中的 avg@8 评估逻辑
MathVista / MathVerse / LogicVista 评估src/pepo/evaluation/*.pyevaluate_mathvista.py, evaluate_mathverse.py, evaluate_logicvista.py公开 release 覆盖了跨域 reasoning benchmark
公开训练 recipescripts/train/*.shtrain_pepo_geometry3k_*, train_pepo_d_geometry3k_*给出 Qwen / InternVL 的具体超参与入口;但 train_pepo_d_geometry3k_internvl3_2b.sh 实际设置了 --use_vision_weights false,需与论文中的完整 PEPO_D 设定区分
Visual grounding / few-shot / puzzle / ViRL39K 全训练管线代码搜索未找到开源实现代码搜索未找到开源实现当前公开仓库未完整包含 RefCOCO、FGVC Aircraft、Flower102、PuzzleVQA、AlgoPuzzleVQA、ViRL39K 的训练脚本与完整 pipeline
Hidden-state shift 分析与词云生成脚本代码搜索未找到开源实现代码搜索未找到开源实现论文展示了 Figure 3 与相关分析,但当前公开仓库未提供对应分析脚本

4. Experimental Setup(实验设置)

4.1 模型与基线

作者使用两种开源 LVLM 作为 backbone:

  • Qwen2.5-VL-3B-Instruct
  • InternVL3-2B-Instruct

对比方法包括:

  • Base (zero-shot)
  • High-Entropy RL
  • GRPO
  • DAPO
  • PEPO_G(把 PEPO 接到 GRPO 上)
  • PEPO_D(把 PEPO 接到 DAPO 上)

4.2 数据集与任务设置

论文覆盖五类任务:

  1. Geometry / logic reasoning
    • 训练:Geometry3K
    • 测试:Geometry3K val/test,MathVista-mini,MathVerse-mini,LogicVista
  2. Visual grounding
    • 训练:RefCOCO 2K samples
    • 测试:RefCOCO val/testA/testB + LISA-Grounding
  3. Few-shot classification
    • FGVC Aircraft 与 Flower102 的 1-shot / 2-shot / 4-shot
  4. Visual puzzle reasoning
    • 训练:PuzzleVQA 1.5K
    • 测试:PuzzleVQA 0.5K + AlgoPuzzleVQA OOD
  5. Scalability
    • 训练:ViRL39K
    • 测试:Geometry3Ktest、MathVista、We-Math、MathVerse、LogicVista、SuperClevr Counting、MMMU-Pro

4.3 评估指标

  • Geometry / math / logic reasoning:avg@8 accuracy
  • Visual grounding:IoU@50
  • Few-shot classification:classification accuracy
  • Puzzle reasoning:top-1 accuracy
  • 训练效率:迭代吞吐、平均 response length、额外权重计算开销比

4.4 训练配置

论文附录给出的共享 RLVR 配置包括:

  • Optimizer:AdamW
  • Precision:bfloat16
  • Train type:full fine-tuning
  • Gradient checkpointing:开启
  • Responses per question:8
  • Temperature:1.0
  • Top-p:1.0
  • DeepSpeed:ZeRO-2
  • Attention:FlashAttention2
  • 训练硬件:8 × NVIDIA A40 GPUs

部分任务特定超参:

  • Learning rate:Task 1/4/5 用 ;Task 2/3 用
  • Max completion length:Task 1/5 为 1024;Task 2/3/4 为 512
  • KL coefficient :Task 1-4 为 0.001;Task 5 为 0.01

4.5 公开代码 release 与论文实验的对应关系

这一部分需要单独说明,因为公开代码并不完全等同于论文的全部实验范围

  • README.md 明确写了当前 release 相关聚焦 Geometry3K-centered training/evaluation pipeline
  • 公开仓库包含 Geometry3K 训练脚本,以及 MathVista / MathVerse / LogicVista 评估脚本;
  • 论文中 visual grounding、few-shot classification、PuzzleVQA、ViRL39K scaling 的完整训练/eval pipeline 并未在当前公开仓库里完全展开;
  • 这意味着:当前公开仓库提供了部分可运行实现,但 release scope 比论文中的 full experiment suite 更窄。

另外,论文正文、附录与公开脚本在 gate_alpha 上并不完全一致。

  • 附录 A 的文字说明写成:Task 1/4/5 使用 0.1;Task 2 使用 0.05;Task 3 使用 0.02
  • 但 Appendix Table 1 写成了:Task 4/5 使用 0.1;Task 1/2 使用 0.05;Task 3 使用 0.02
  • 附录关于 geometry 的 gate-strength 消融里,又把 0.05 标为 default;
  • 公开 Qwen Geometry3K recipe 用的是 0.10
  • 公开 InternVL Geometry3K recipe 用的是 0.18
  • 另外,公开 train_pepo_d_geometry3k_internvl3_2b.sh 还设置了 --use_vision_weights false,说明 release 中某些 PEPO_D recipe 与论文中完整启用 perception-exploration weighting 的设定并不完全一致。

因此对复现实验来说,alpha 的“默认值”以及是否实际启用 vision-based weighting,在论文与公开 release 之间都存在不一致,需要特别注意。

5. Experimental Results(实验结果)

5.1 主结果:Geometry / math / logic reasoning

BackboneMethodGeometry3K valGeometry3K testMathVista-miniMathVerse-miniLogicVistaAvg
Qwen2.5-VL-3BBase11.5814.2550.1937.6632.2229.18
Qwen2.5-VL-3BHigh-Entropy RL15.5818.2650.6939.8432.5931.39
Qwen2.5-VL-3BGRPO19.0023.7951.5640.5428.3032.64
Qwen2.5-VL-3BPEPO_G21.9127.2754.4545.4234.4536.70 (+4.06 vs Table 1 GRPO; 引言另写为 +3.67,论文未详细说明差异原因)
Qwen2.5-VL-3BDAPO22.6327.0053.6844.4433.1336.18
Qwen2.5-VL-3BPEPO_D22.3827.8954.7544.2333.8936.63 (+0.45)
InternVL3-2BBase7.889.0323.0023.3628.3618.33
InternVL3-2BHigh-Entropy RL10.898.3035.2420.7017.1818.46
InternVL3-2BGRPO22.0826.3349.3642.0928.8433.74
InternVL3-2BPEPO_G25.8431.2852.3644.8931.8837.25 (+3.51)
InternVL3-2BDAPO20.9421.5750.4041.1128.5232.51
InternVL3-2BPEPO_D28.1231.1851.4945.2432.2537.66 (+5.15)

关键信息:

  • 结果显示,PEPO 在两个 backbone 上的平均结果都高于 GRPO;
  • 对 Qwen 来说,PEPO_G 与 PEPO_D 都有效,且 PEPO_DDAPO 还高 +0.45
  • 对 InternVL 来说,PEPO_D 的增益达到 +5.15
  • 相对增幅较大的任务包括 MathVerse / LogicVista 这类需要视觉和符号推理联合发挥的 benchmark。

5.2 Visual grounding 与 few-shot classification

Visual grounding(IoU@50)

MethodRefCOCO valtestAtestBLISAAvg
Base89.1091.7084.0056.5180.33
High-Entropy RLmodel collapsedmodel collapsedmodel collapsedmodel collapsed-
GRPO90.1292.2985.5562.4282.60
PEPO_G90.4492.4085.7565.2683.46 (+0.86)
DAPO90.1092.4085.0862.4882.52
PEPO_D90.0392.7285.4264.2383.10 (+0.58)

这里一个现象是:High-Entropy RL 在 grounding 上直接 collapse,而 PEPO 保持了稳定结果。按论文的解释,这说明仅依赖 entropy 的 token-level weighting 不足以支撑 multimodal RL,视觉 grounding prior 是必要补充。

Few-shot classification

DatasetMethod1-shot2-shot4-shotAvg
FGVC AircraftSFT36.2440.8655.4844.19
FGVC AircraftGRPO48.7255.6063.9456.09
FGVC AircraftPEPO_G51.1357.3175.7961.41 (+5.32)
Flower102SFT33.9844.5052.3343.60
Flower102GRPO53.2357.9466.2259.13
Flower102PEPO_G54.8159.4467.5260.59 (+1.46)

结果也表明,PEPO 不只在 chain-of-thought benchmark 上有效,在少样本视觉分类这类更偏 perception 的任务上也有收益。

5.3 Visual puzzle 与 scalability

PuzzleVQA / AlgoPuzzleVQA

BackboneMethodPuzzleVQAAlgoPuzzleVQAAvg
Qwen2.5-VL-3BBase31.8021.7226.76
Qwen2.5-VL-3BHigh-Entropy RL35.0024.6129.81
Qwen2.5-VL-3BGRPO43.2025.4434.32
Qwen2.5-VL-3BPEPO_G45.0026.9435.97 (+1.65)
Qwen2.5-VL-3BDAPO44.6025.3334.97
Qwen2.5-VL-3BPEPO_D46.8026.5636.68 (+1.71)
InternVL3-2BBase31.8023.0027.40
InternVL3-2BHigh-Entropy RL32.6025.2228.91
InternVL3-2BGRPO43.2026.1734.69
InternVL3-2BPEPO_G45.2027.2236.21 (+1.52)
InternVL3-2BDAPO44.8027.7236.26
InternVL3-2BPEPO_D45.2028.6136.91 (+0.65)

ViRL39K scalability

MethodGeometry3K testMathVistaWe-MathMathVerseLogicVistaCountingMMMU-ProAvg
GRPO28.7259.3458.9055.2538.1455.8125.6645.97
PAPO_G30.9561.3860.0957.1438.6762.5627.1148.27
PEPO_G29.8563.4860.9856.4939.8570.7527.4749.84 (+3.87 vs GRPO)

PEPO 在大规模训练数据上仍有增益,而且在 Counting 这类 perception-intensive benchmark 上提升幅度也较大。

5.4 训练效率与额外开销

MetricMethodGeometry3KPuzzleVQARefCOCOFGVC Aircraft
Iter/sGRPO0.0220.0660.0800.071
Iter/sPEPO_G0.0220.0740.0840.083
Mean lengthGRPO2731047792
Mean lengthPEPO_G270856477
PEPO_G0.00390.00650.00610.0048

作者定义的额外开销比:

实验表明 。这意味着:PEPO 的额外计算相关是 hidden-state similarity、entropy 和权重归一化,对总训练开销的影响较小。

5.5 消融实验

组件消融(paper Table 7)

VariantGeometry3K valPuzzleVQA
GRPO19.0043.20
Exploration-only20.1841.60
Perception-only21.0743.20
PEPO_G22.8045.00

这张表说明:

  • 只用 entropy 会不稳定,甚至在 PuzzleVQA 上比 GRPO 差;
  • 只用 perception 也能提高 Geometry3K;
  • 在这组消融结果中,perception + exploration 的结合对应最高结果。

Gate strength 敏感性(paper Appendix Table 3)

Geometry3K valGeometry3K testMathVista-miniMathVerse-miniLogicVistaAvg
0.00 (Perception-only)21.0726.7352.8145.3134.9336.17
0.0220.6025.8753.8844.9934.7336.01
0.05 (Default in this ablation table)21.9127.2754.4545.4234.4536.70
0.1022.8026.8153.5844.1234.2636.31
0.1521.4526.5253.5443.9934.6236.02

从该表可以看到,小到中等强度的 gate 对应的结果相对更高,entropy 更适合作为补充调制信号,而不是主导信号。

Perception prior 度量方式(paper Appendix Table 4)

MeasureGeometry3K valGeometry3K testFGVC Aircraft (4-shot)
L1 distance19.0024.5060.85
L2 distance20.9026.0867.33
Cosine similarity22.8026.8175.79

这也是公开代码默认 vision_score_type="cosine" 的直接依据。

5.6 定性结果与训练动态

Figure 5 解读:这是论文 Figure 5。它给了 Geometry3K、MathVerse、LISA 三类案例。图中示例显示,GRPO 在“看图”与“推理”之间会出现脱节:例如读错几何关系、在中间推导里出现不一致,或者 bounding box 指向错误目标。相对地,PEPO 生成的中间 reasoning step 与视觉证据一致性更高,并给出正确答案。Figure 5 同时展示了最终答案差异和 reasoning trajectory 内部结构的变化。

Figure 6 解读:这是论文 Figure 6,对比 GRPO 与 PEPO_G 在 FGVC Aircraft 4-shot 上的训练曲线。图中显示 PEPO_G 对应较高的训练 reward、较平滑的 response length 下降趋势、持续上升的 mean visual similarity,以及较温和的 mean token entropy 下降。按论文的解释,这反映了 PEPO 在保持 exploration 的同时提升了视觉对齐度。

5.7 局限性

论文明确承认了几项限制:

  1. 只在 2B / 3B 级别 LVLM 上验证,没有扩展到 7B+;
  2. 没系统测试更长 context setting;
  3. 评测任务虽然多,但依然是 curated benchmark 集合;
  4. 更广泛的视频理解、tool-augmented reasoning 尚未验证。

结合公开仓库,还可以再补一条“release 级别”的现实限制:

  • 开源代码已经公开,但当前 release 相关覆盖 Geometry3K 为中心的训练/评估路径,和论文 full experiment suite 不是完全一一对应。

5.8 总结

综合论文与当前公开代码,可以整理出几个结论:

  • PEPO 的重点贡献是把 visual groundingreasoning exploration 同时纳入 token-level credit assignment;
  • 在论文报告的 geometry reasoning、visual grounding、few-shot classification、visual puzzle 与 scalability 实验中,PEPO 相比 GRPO / DAPO 都表现出一致增益;
  • 训练效率实验表明,这种 token-level reweighting 的额外计算开销较低,论文报告的 始终低于
  • 当前公开仓库已经提供了可运行的 Geometry3K-centered release,但并未完整覆盖论文中的全部训练与分析 pipeline,因此“论文结果”和“当前 release 范围”需要分开理解。

论文最后给出的后续方向相关包括:在更大规模 backbone 上验证该方法,以及把类似的 token-level multimodal RL 机制扩展到更广的视觉理解与推理任务。