Monet: Reasoning in Latent Visual Space Beyond Images and Language
Paper: arXiv:2511.21395 Code: NOVAglow646/Monet Code reference:
main@08939998(2026-03-19)
1. Motivation (研究动机)
现有 MLLM 的 visual reasoning 已经从纯文本 CoT 走向 “thinking with images”:中间步骤可以裁剪关键区域、画框/高亮、调用 grounding/depth/tool,甚至用代码或生成模型创建辅助图像。这个方向的核心收益是把视觉证据显式注入推理链,缓解纯语言 CoT 对空间关系、细粒度 OCR、图表和几何变换的表达瓶颈。但论文指出,这类方法的“视觉思考”仍然依赖外部工具或显式图像,因此能力边界被工具集合绑定:模型只能调用已经定义好的 crop、box、depth、code execution 等操作,遇到需要抽象空间变换、全局几何想象或非标准视觉操作的任务时,无法像人一样在内部感知空间里自由组合和变形。
更具体地说,已有 latent visual reasoning 方法也没有真正解决这个问题。它们通常把模型生成的 latent embeddings 对齐到辅助图像 embeddings,同时只对后续文本 token 做 next-token prediction;如果进一步做 RL,则直接套用 GRPO。这里有两个瓶颈:第一,辅助图像本身包含上百到上千个 image tokens,逐 token 对齐的计算和显存成本很高,而 mean pooling 又会破坏细粒度视觉信息;第二,SFT 的文本 NTP loss 容易让模型记住后续文本,而不是学习有效 latent 表征,GRPO 又只能对离散文本 token 计算概率比,无法直接优化连续 latent embeddings。
Monet 要解决的问题是:让 MLLM 在不显式生成/调用中间图像的情况下,直接生成连续 latent embeddings 作为“抽象视觉想法”,并让这些 embeddings 在 SFT 和 RL 中都获得足够强、足够直接的监督。这个问题值得研究,因为如果 latent 视觉空间可以成为推理载体,模型就不再需要把每一步视觉思考渲染成图片或翻译成语言;它可以用更接近内部表征的方式进行空间、图表、OCR、几何和抽象视觉逻辑推理,同时避免 tool-call latency、多轮异步执行和工具格式错误。
2. Idea (核心思想)
Monet 的核心 insight 是:视觉推理的中间状态不一定要落在“可见图片”或“可读文字”上,也可以落在 MLLM decoder 自己生成的连续 hidden embeddings 上;关键不在于把 latent 强行对齐到整张辅助图像,而在于让 latent 捕获那些对后续答案有用的 observation token 语义,并在 RL 阶段把 outcome reward 直接反传到 latent action。
方法上,Monet 把训练拆成三阶段 distillation SFT 加一个 VLPO RL 阶段:先用 image-text interleaved CoT warm up 模型理解“中间视觉证据”,再用 teacher/student 和 controlled attention 生成高质量 target latent,最后让模型在没有辅助图像的情况下生成这些 latent;RL 阶段则把连续 latent embeddings 建模成 Gaussian action,用近似概率比把 policy gradient 扩展到 latent token。
它和 Deepeyes、Visual-CoT、ReFocus 等 “think with images/tool” 方法的根本差异是:后者在中间步骤显式产生或消费辅助图像,视觉操作类型由外部工具决定;Monet 则让 Qwen2.5-VL-7B 在 <abs_vis_token> / latent 段里生成不可读但可优化的连续表示。它也不同于 LVR 这类 latent-align 方法:Monet 不做昂贵的 full-image-token 对齐,而是用 observation-token representation alignment、controlled attention、latent-only backpropagation 和 VLPO 让 latent 本身承担推理职责。
3. Method (方法)
3.1 Overall framework:文本-潜在视觉交错推理
Figure 1 解读:左侧展示 inference 形态:输入 question + image 后,Monet-7B 可以先生成普通文本 token,再输出 latent start token 进入 latent thinking mode;此时 decoder 最后一层 hidden representation 被反馈成下一步 input embedding,连续生成固定长度 个 latent embeddings,随后插入 stop token 回到语言推理并输出答案。右侧展示训练形态:SFT Stage 1 让模型习惯 image-text interleaved CoT;Stage 2 通过 teacher/student 和辅助图像获得 target latent;Stage 3 在没有辅助图像的情况下 distill 出 latent 生成能力;最后用 VLPO 继续优化 latent reasoning。
直觉上,Monet 把 latent 段当作一种“不可读的视觉草稿”。人类做几何题时不一定会把脑内图像完整画出来,而是保留若干空间关系、形状变换和注意焦点;Monet 试图让 MLLM 用 hidden embedding 承载类似信息。这样做的风险是 latent 可能变成没有语义的占位符,所以论文用三类机制防止 shortcut:先让模型真的依赖辅助图像,再把关键 observation 的 teacher representation 对齐给 latent,最后在 RL 中把 latent action 本身纳入 policy gradient。
Released code 中的实现命名与论文叙述略有差异:论文用 <latent> / </latent> 描述 latent mode;代码实际在 src/main.py、src/precompute_teacher_reps.py、src/precompute_teacher_latents.py 和 vLLM patch 中注册/使用 <abs_vis_token>、</abs_vis_token>、<abs_vis_token_pad>,并在 inference 说明中把输出后处理为 <latent> 占位符。这是命名差异,不改变方法语义。
3.2 Monet-SFT-125K:只保留“辅助图像确实必要且正确”的 interleaved CoT
Figure 2 解读:数据构造不是简单汇总已有 image-text CoT,而是三次过滤。Stage 1 用 Qwen2.5-VL-7B 只看原图和问题作答,只保留答错样本,确保辅助图像不是冗余的;Stage 2 用 Qwen2.5-VL-72B 只看辅助图像作答,只保留能答对样本,确保辅助图像本身包含正确证据;Stage 3 用 DeepSeek-V3.1 和 Gemini 2.5 Pro 标注哪些文本 token 对应关键视觉 observation,为后续 representation alignment 提供 token-level 监督。
Monet-SFT-125K 来自 ReFocus、CogCoM、Visual-CoT 和 Zebra-CoT,覆盖 real-world、documents、chart、geometry、3D object counting 等任务。论文给出的统计为:ReFocus 0.4K(chart,box/highlight),CogCoM 0.5K(real-world/chart,crop + auxiliary lines/boxes),Visual-CoT 118.6K(real-world/documents/chart,crop/box),Zebra-CoT visual search 2.7K(crop/box),Zebra-CoT geometry 0.1K(auxiliary lines / geometric sketchpads),Zebra-CoT count 2.9K(3D objects removed/added)。这些数据的共同点是中间图像不是装饰,而是被过滤为“原图答不出、辅助图能答出”的必要视觉证据。
3.3 SFT Stage 1:warm-up,让模型学会用中间图像
Figure 4 解读:横轴是 warm-up 训练过程,纵轴是 observation token prediction accuracy。未适配的 Qwen2.5-VL-7B 即使看到辅助图像,预测 observation token 的准确率也几乎没有增益,说明它并不会自然利用中间视觉证据;随着 Stage 1 在 image-text interleaved CoT 上训练,带辅助图像的 accuracy gain 逐步上升,说明模型开始把辅助图像中的关键信息编码进 observation token representation。
Stage 1 直接对 Monet-SFT-125K 做 vanilla SFT,目标是得到 。Released script script_examples/sft_stage1.sh 以 Qwen2.5-VL-7B-Instruct 为 base,--epochs 4、--bsz 1、--grad_accum_steps 16、--stage "sft_stage1"、--ce_emphasize_factor 2.0,8 卡 torchrun + ZeRO-2。论文 supplementary Table 7 同时报告 SFT Stage 1 steps 为 3885(3 epochs),因此这里存在一个小的 paper/table/script 不一致:主文实验设置写 4 epochs,supplementary 表写 3 epochs,而 released launch script 使用 --epochs 4。本笔记的可复现实验配置以 released script 为准,同时保留论文表格中的 reported steps。
3.4 SFT Stage 2:teacher/student + observation alignment + controlled attention
Figure 3 解读:Stage 2 是整套 SFT 的关键。Teacher 看到辅助图像并产生 key observation token 的 hidden representations;Student 在 latent 段生成 embeddings,同时通过受控 attention 让 latent 能直接 attend 到辅助图像 embeddings,再让后续 observation token 的表示对齐 teacher。这样 latent 不需要逐个对齐数千个 image tokens,而是通过“后续文本中真正描述关键视觉事实的 token”获得监督。
形式上,对第 个样本、第 个关键 observation token,teacher representation 记为 oldsymbol{h}^{*(i,l)}_{ ext{obs}},student representation 记为 oldsymbol{ ilde h}^{(i,l)}_{ ext{obs}}。Stage 2 的 observation alignment loss 是:
同时保留普通文本 next-token prediction:
总 loss 为:
这里最重要的工程细节是 latent-only backpropagation:alignment loss 只允许更新 latent embeddings 相关路径,非 latent representations 被 stop-gradient / proxy-gradient 处理,防止模型通过改变 observation token 或普通语言路径来“作弊”降低 loss。Released code 对应 src/trainer.py::compute_latents_only_loss,会把 loss 对 latent 的梯度抽出并构造 proxy loss;Stage 2 trainer 再加载 teacher_reps_dir 中离线预计算的 teacher observation representations。
Released script script_examples/sft_stage2.sh 的关键配置是:LATENT_SIZE=8,CE_EMPHASIZE_FACTOR=4.0,ALIGNMENT_WEIGHT=2.0,EMPHASIZE_LATENT_WEIGHT=2.0,--epochs 2,--bsz 1,--grad_accum_steps 16,--teacher_reps_dir path_to_your_model/Monet_checkpoints/monet_precomputed_observation_token_teacher_reps/${TEACHER},--alignment_layer all_layers。论文 supplementary Table 7 报告 Stage 2 为 1000 steps(1.03 epoch),alignment weight 2.0,max total pixels 1500 × 28 × 28。
Stage 2 ablation 证明两个监督信号都必要:Monet-SFT 在 V*/HR4K/HR8K/MME/VisualPuzzles 上为 82.20/68.50/66.00/52.68/30.48;去掉 latent-only BP 变成 46.07/40.13/39.00/38.67/33.65;去掉 auxiliary image attention 变成 73.30/63.88/57.63/39.66/28.60。也就是说,如果 latent 看不到辅助图,或者 alignment loss 能通过非 latent shortcut 被消化,latent 表征就不会稳定地学到视觉信息。
3.5 SFT Stage 3:无辅助图像地生成 target latent
Stage 2 仍然在训练时让 student latent attend 到辅助图像;真正 inference 时没有这些辅助图像。因此 Stage 3 的目标是把 Stage 2 得到的高质量 target latent oldsymbol{h^*}_{\text{latent}} 蒸馏给一个只看原始 question + image 的模型。它从 初始化,在数据中插入 latent 段,让模型生成 latent embeddings,并用 cosine alignment 对齐 Stage 2 离线预计算的 target latent:
Stage 3 总 loss 为:
Released code 把 Stage 2 teacher latent 的生成放在 src/precompute_teacher_latents.py,然后 script_examples/sft_stage3.sh 用 --teacher_latent_dir 读入;关键配置仍然是 LATENT_SIZE=8、ALIGNMENT_WEIGHT=2.0、CE_EMPHASIZE_FACTOR=4.0、--alignment_layer all_layers。论文表格报告 Stage 3 为 1000 steps(1.03 epoch),max total pixels 2000 × 28 × 28。
3.6 RL Stage:VLPO 把 policy gradient 扩展到连续 latent action
标准 GRPO 的 objective 对第 个 rollout、第 个 token 使用概率比 和 advantage :
问题是 latent embeddings 不是离散 token,没有显式 softmax probability,所以 GRPO 的 只能对文本 token 计算。VLPO 的做法是把旧 policy rollout 得到的 latent oldsymbol{h}^{\text{old}}_{i,t} 看作从 Gaussian action distribution 中采样,当前 policy 在同一上下文下生成的 latent oldsymbol{h}^{\theta}_{i,t} 是 mean,于是:
latent step 的概率比写成:
当 时,最大化 VLPO objective 等价于拉近当前 policy latent 和旧 rollout 中产生好结果的 latent;当 reward 不好时则避免重复这些 latent action。Released RL script RL/examples/vlpo_train.sh 基于 EasyR1,关键配置包括:LATENT_SIZE=10,ROLLOUT_N=8,TEMPERATURE=0.5,SELECT_ACC_THRESHOLD=0.6,KL_COEF=0.01,ORI_BSZ=64,MONET_RL_SIGMA=10.0,MAX_PROMPT_LENGTH=4096,MAX_RESPONSE_LENGTH=4096,worker.rollout.sampling_strategy=monet,worker.rollout.online_difficulty_sampling=true,以及 worker.reward.repetition_penalty=true。奖励由 accuracy reward(正确为 1,否则 0)和 format reward(鼓励最终答案放进 \boxed{})组成;论文强调不直接奖励“用了 latent”,否则模型可能学会无意义地插入 latent 段。论文与 released code 实现差异:论文正文把 reward 概括为 accuracy + format,但 RL/examples/reward_function/monet_reward_function.py::compute_score_w_prev_correctness 实际计算 overall = 0.9 * accuracy + 0.1 * format - 0.001 * length_penalty,并可通过 repetition penalty 让错误答案 accuracy 变成 -1。
3.7 Pseudocode:按 released implementation 抽象出的关键组件
import torch
import torch.nn.functional as F
def latent_interleaved_decode(model, tokenizer, prompt, image, latent_size: int = 10):
"""Inference path implemented by Monet's modified Qwen/vLLM runner."""
state = model.encode_multimodal(prompt, image)
output_tokens = []
while not model.done(output_tokens):
token, last_hidden = model.decode_one_step(state)
output_tokens.append(token)
if token == tokenizer.convert_tokens_to_ids("<abs_vis_token>"):
latent_embeds = []
for _ in range(latent_size):
# The last-layer hidden representation becomes the next input embedding.
state = model.feed_embedding(last_hidden)
_, last_hidden = model.decode_one_step(state, force_embedding_mode=True)
latent_embeds.append(last_hidden)
output_tokens.append(tokenizer.convert_tokens_to_ids("</abs_vis_token>"))
state = model.exit_embedding_mode(latent_embeds)
return tokenizer.decode(output_tokens)def stage2_observation_alignment(student, teacher_obs_reps, batch, alpha: float = 2.0):
"""Stage 2: align observation-token representations while updating only latent paths."""
out = student(
**batch,
output_hidden_states=True,
controlled_attention="image_to_latent_to_observation",
)
ntp_loss = F.cross_entropy(out.logits[:, :-1].reshape(-1, out.logits.size(-1)),
batch["labels"][:, 1:].reshape(-1),
ignore_index=-100)
student_obs_reps = gather_positions(out.hidden_states, batch["observation_positions"])
align_loss = 1.0 - F.cosine_similarity(
teacher_obs_reps.detach(), student_obs_reps, dim=-1
).mean()
latent_only_align = backprop_only_through_latents(out.latent_embeddings, align_loss)
return ntp_loss + alpha * latent_only_aligndef stage3_target_latent_distillation(model, teacher_latents, batch, alignment_weight: float = 2.0):
"""Stage 3 mirrors src/trainer.py: first collect latent patches, then run CE+alignment."""
latent_inputs = {
**batch["student_inputs"],
"latent_mode": True,
"labels": None,
"alignment_poss": batch["student_alignment_poss"],
"teacher_hidden_states_for_alignment": teacher_latents,
"loss_type": [],
"output_hidden_states": False,
}
model.gradient_checkpointing_disable()
latent_out = model(**latent_inputs) # returns ce_patch_pos / ce_patch_vec
ce_inputs = {
**batch["student_inputs"],
"latent_mode": False,
"labels": batch["student_labels"],
"ce_patch_pos": latent_out.ce_patch_pos,
"ce_patch_vec": latent_out.ce_patch_vec,
"ce_emphasize_poss": batch["observation_poss"],
"loss_type": ["ce", "alignment"],
}
model.gradient_checkpointing_enable(gradient_checkpointing_kwargs={"use_reentrant": False})
ce_loss, outputs = model.compute_loss(**ce_inputs)
alignment_loss = outputs.loss_dict["alignment"]
return ce_loss + alignment_weight * alignment_lossdef vlpo_latent_ratio(old_latent, current_latent, sigma: float = 10.0):
"""VLPO ratio for a continuous latent action."""
sq_dist = (old_latent.detach() - current_latent).pow(2).sum(dim=-1)
return torch.exp(-sq_dist / (2 * sigma**2))
def dual_clip_policy_loss(ratios, advantages,
clip_ratio_low: float = 0.2,
clip_ratio_high: float = 0.3,
clip_ratio_dual: float = 3.0):
"""Mirror RL/verl/trainer/core_algos.py: high clip first, dual clip only for negative A."""
neg_approx_kl = torch.log(ratios).clamp(min=-10.0, max=10.0)
clipped = torch.exp(
neg_approx_kl.clamp(
min=torch.log(torch.tensor(1.0 - clip_ratio_low)),
max=torch.log(torch.tensor(1.0 + clip_ratio_high)),
)
)
pg_loss = -advantages * ratios
pg_loss2 = -advantages * clipped
pg_loss3 = -advantages * clip_ratio_dual
clipped_pg_loss_higher = torch.max(pg_loss, pg_loss2)
clipped_pg_loss_lower = torch.min(clipped_pg_loss_higher, pg_loss3)
final_pg_loss = torch.where(advantages < 0, clipped_pg_loss_lower, clipped_pg_loss_higher)
return final_pg_loss.mean()
def vlpo_loss(text_ratios, old_latents, current_latents, advantages):
latent_ratios = vlpo_latent_ratio(old_latents, current_latents, sigma=10.0)
ratios = torch.cat([text_ratios, latent_ratios], dim=-1)
return dual_clip_policy_loss(ratios, advantages)Code reference:
main@08939998(2026-03-19) — pseudocode and mapping based on this commit
| Paper Concept | Source File | Key Class/Function |
|---|---|---|
Qwen2.5-VL latent-token forward / <abs_vis_token> handling | monet_qwen_model/modeling_qwen2_5_vl_monet.py | Qwen2_5_VLModel.forward, Qwen2_5_VLForConditionalGeneration.forward |
| SFT tokenizer special tokens and model config | src/main.py | adds <abs_vis_token>, </abs_vis_token>, <observation>, </observation>; dispatches stage trainers |
| Stage 1 warm-up launch | script_examples/sft_stage1.sh | torchrun -m src.main --stage "sft_stage1" |
| Teacher observation representation cache | src/precompute_teacher_reps.py | precomputes observation-token teacher reps for Stage 2 |
| Stage 2 observation alignment / latent-only BP | src/trainer.py, script_examples/sft_stage2.sh | compute_latents_only_loss, Stage 2 trainer, --teacher_reps_dir |
| Teacher target latent cache | src/precompute_teacher_latents.py | precomputes target latent embeddings for Stage 3 |
| Stage 3 latent distillation | src/trainer.py, script_examples/sft_stage3.sh | Stage 3 trainer, --teacher_latent_dir, --alignment_layer all_layers |
| VLPO rollout/inference latent recording | RL/monet_models/vllm/monet_gpu_model_runner.py, RL/monet_models/vllm/latent_recorder.py | modified vLLM runner and latent recorder |
| VLPO actor loss | RL/verl/workers/actor/dp_actor.py, RL/verl/trainer/core_algos.py | latent probability ratio / policy objective hooks |
| RL launch and reward | RL/examples/vlpo_train.sh, RL/examples/reward_function/monet_reward_function.py | sampling_strategy=monet, monet_rl_sigma=10.0, accuracy/format/repetition rewards |
4. Experimental Setup (实验设置)
4.1 Datasets
SFT 使用 Monet-SFT-125K,共 125K image-text interleaved CoTs,来源和规模如下:Visual-CoT 118.6K、Zebra-CoT count 2.9K、Zebra-CoT visual search 2.7K、CogCoM 0.5K、ReFocus 0.4K、Zebra-CoT geometry 0.1K。RL 使用 Thyme-RL 的 3.2K subset 训练 1 epoch。评测使用 VLMEvalKit,覆盖 V*、HRBench4K、HRBench8K、MME-RealWorld-Lite,以及 OOD 的 VisualPuzzles。
4.2 Baselines
论文比较了 Qwen2.5-VL-7B、Vanilla SFT、Vanilla SFT + GRPO、Deepeyes、LVR、GPT-4o、Gemini 2.5 Pro、Pangea-7B、LLaVA-OneVision-72B。这里的核心对照不是只看绝对 SOTA,而是区分三件事:相同数据上普通 SFT 是否足够;GRPO 是否能提升 latent reasoning;显式 crop/tool 方法 Deepeyes 和已有 latent-align 方法 LVR 是否能覆盖 Monet 的能力。
4.3 Metrics and evaluation
V* 报 Overall / Attribute / Spatial;HRBench4K 和 HRBench8K 报 Overall / FSP / FCP;MME-RealWorld-Lite 报 Overall / Reasoning / Perception,并在 supplementary 中细分 MO、AD、OCR、DT、RS;VisualPuzzles 报 Overall / Algorithmic / Analogical / Deductive / Inductive / Spatial。论文说明评测先用 exact-match rule-based judge,再用 DeepSeek-V3.1 或 Gemini-2.5-Pro 作 secondary judge,以提升答案判定可靠性。
4.4 Training config
- Base model:Qwen2.5-VL-7B-Instruct;SFT 代码基于 TRL,RL 基于 EasyR1。
- SFT Stage 1 released script:
script_examples/sft_stage1.sh,8 GPUtorchrun,--epochs 4,batch size 1,gradient accumulation 16,ce_emphasize_factor=2.0,ZeRO-2 configdeepspeed/ds_zero2_gpu.json。 - SFT Stage 2 released script:
script_examples/sft_stage2.sh,latent size 8,batch size 1,gradient accumulation 16,alignment_weight=2.0,ce_emphasize_factor=4.0,emphasize_latent_weight=2.0,alignment_layer=all_layers,teacher reps frommonet_precomputed_observation_token_teacher_reps。 - SFT Stage 3 released script:
script_examples/sft_stage3.sh,latent size 8,batch size 1,gradient accumulation 16,alignment_weight=2.0,ce_emphasize_factor=4.0,teacher latents frommonet_precomputed_target_latent。 - RL released script / config:
RL/examples/vlpo_train.sh+RL/verl/workers/actor/config.py,latent size 10,batch size 64,rollout size 8,temperature 0.5,learning rate 1e-6,weight decay 0.01,max prompt/response length 4096,VLPO ,select accuracy threshold 0.6,KL coefficient 0.01;PPO clipping 使用clip_ratio_low=0.2、clip_ratio_high=0.3、clip_ratio_dual=3.0。 - Pixel/token constraints from paper tables:SFT Stage 1 max total pixels 2000 × 28 × 28;Stage 2 max total pixels 1500 × 28 × 28;Stage 3 max total pixels 2000 × 28 × 28;inference max visual tokens 8192 × 28 × 28。
5. Experimental Results (实验结果)
5.1 Main benchmark results
在 real-world perception/reasoning 上,Monet-7B(Monet-SFT + VLPO)相对 Qwen2.5-VL-7B 一致提升:V* Overall 从 76.44 到 83.25(+6.81),HRBench4K 从 68.00 到 71.00(+3.00),HRBench8K 从 63.75 到 68.00(+4.25),MME-RealWorld-Lite 从 45.75 到 55.50(+9.75)。具体子项上,V* Attribute/Spatial 为 83.48/82.89,HRBench4K FSP/FCP 为 85.25/56.75,HRBench8K FSP/FCP 为 79.75/56.25,MME Reasoning/Perception 为 51.07/58.34。
和其他开源 baseline 比,Monet-7B 在多数 benchmark 上优于 Deepeyes 和 LVR。比如 Deepeyes 在 V* Overall 也是 83.25,但 Monet 的 V* Spatial 更高(82.89 vs 81.58),HRBench8K Overall 更高(68.00 vs 65.13),MME-RealWorld-Lite Overall 更高(55.50 vs 54.28)。与相同数据上的 Vanilla SFT / SFT+GRPO 相比,Monet 的提升说明“数据本身”不是全部原因:Vanilla SFT 在 V*/HR4K/HR8K/MME 上为 81.68/68.38/61.63/51.28,SFT+GRPO 为 78.53/70.00/66.75/52.42,均低于 Monet-7B 的 83.25/71.00/68.00/55.50。
OOD VisualPuzzles 上,Monet-7B Overall 为 35.02,高于 Qwen2.5-VL-7B 的 32.71、Vanilla SFT 的 33.99、SFT+GRPO 的 30.99、Deepeyes 的 32.96、Pangea-7B 的 31.3 和 LLaVA-OneVision-72B 的 30.8。子项上,Monet 在 Algorithmic/Analogical/Deductive/Inductive/Spatial 为 45.80/30.81/47.50/26.79/25.52;相对 Qwen2.5-VL-7B 的改进是 +2.31 Overall、+6.09 Algorithmic、+8.78 Analogical、+9.01 Deductive、+0.47 Inductive、+3.72 Spatial。这是论文证明 latent reasoning 不是只在训练分布上记住 CoT 模式的关键证据。
5.2 Ablations:Monet 的组件各自贡献什么
Table 5 的组件消融最能说明论文主张。Full Monet-7B 在 V*/HRBench4K/HRBench8K/MME/VisualPuzzles 上为 83.25/71.00/68.00/55.50/35.02。去掉 VLPO 后,Monet-SFT 为 82.20/68.50/66.00/52.68/30.48;在 Monet-SFT 上直接加 GRPO 只有 80.10/69.00/64.75/54.19/31.51,说明 GRPO 对文本答案可能有帮助,但不会稳定强化 latent reasoning,甚至会损伤部分视觉 benchmark。去掉 latent-only BP 后,V*/HR4K/HR8K/MME 降到 46.07/40.13/39.00/38.67,说明如果 alignment loss 可以更新普通路径,模型会走 shortcut,而不是让 latent 承担视觉信息。去掉 auxiliary image attention 后为 73.30/63.88/57.63/39.66/28.60;去掉 observation-token alignment 后为 75.39/67.25/63.50/46.90/27.48,说明 controlled attention 和 observation supervision 都不可替代。
Figure 5 解读:横向比较 training latent size 和 test latent size 。在 V*、HRBench、MME-RealWorld 等 in-distribution benchmark 上, 通常最差,增加 latent embeddings 会提升到某个峰值,说明模型确实在使用 abstract visual embeddings;但在 OOD VisualPuzzles 上,只有 VLPO-enhanced model 能稳定从 受益,说明 SFT 只学到了分布内 latent 模式,而 VLPO 才把 reward 信号真正绑定到 latent action 上。
5.3 Dataset and inference case studies
Figure 6 解读:这个 Monet-SFT-125K 例子展示了 crop crucial region 的训练形态:原始 infographic 中问题要求 Varicella vaccine 的延迟比例,辅助图像裁出具体表格位置,文本中 <observation>Varicella vaccine</observation> 等关键 token 被标注出来。它说明 Stage 2 对齐的不是任意文本,而是被辅助视觉证据支撑的 observation token。
Figure 7 解读:这个例子来自 3D object counting,辅助图像不是简单 crop,而是根据移除规则创建新的视觉状态。它对应 Monet 想解决的核心场景:许多视觉推理需要“在脑内改变图像状态”,而不仅是看清原图局部。
Figure 8 解读:这个例子展示 drawing auxiliary lines / bounding boxes。对几何或空间问题,关键不是识别单个物体,而是构造辅助线、边界和相对位置;Monet 用这类数据把显式辅助图像中的结构蒸馏到 latent embeddings。

Figure 9 解读:3D spatial reasoning 案例中,Monet 不用语言逐步描述椅子之间的角度关系,而是在 latent 段中编码几何理解后给出答案。这是“latent visual thought”最直观的 qualitative evidence。

Figure 10 解读:2D transformation 案例强调 latent 对翻转、旋转或图形变换规则的承载能力。它和 crop-based 方法不同:模型不是定位一个局部区域,而是要在内部表示里维护变换关系。

Figure 11 解读:complex diagram reasoning 展示了层级化推理:先用 latent 聚焦局部结构,再把局部发现整合成答案。论文用它说明 latent embeddings 可以不仅是“压缩图像”,还可以是中间视觉推理状态。

Figure 12 解读:commonsense QA 案例中,Monet 需要把 “Origin” 和 “Analogy” 的视觉/语义连接关系放进 latent reasoning,再输出最终结论;这类任务体现了 latent 表征与语言概念之间的互补。

Figure 13 解读:fine-grained OCR 案例显示 Monet 能在复杂图像中定位中间区域的关键信息并回答问题。这里 latent 的作用更像内部 attention sketch:它帮助模型保留细粒度文字证据,而不是把所有 OCR 细节都写进文本 CoT。
5.4 Limitations and takeaways
作者明确给出两个 limitation。第一,Monet 依赖多阶段 SFT pipeline:需要构造 Monet-SFT-125K、预计算 teacher observation reps、训练 Stage 2、预计算 target latents、再训练 Stage 3,整体复杂度和训练开销高于普通 SFT。第二,论文还没有系统研究不同 reward design 对 latent visual reasoning 的影响;当前 reward 主要是 answer accuracy + format,不奖励 latent 行为本身,但更细粒度的视觉 reward、过程 reward 或 latent consistency reward 仍然是开放问题。
总体结论是:Monet 的收益不是来自单一技巧,而是来自一组约束共同逼迫 latent embeddings 变成有效视觉推理动作。数据过滤保证辅助图像必要且正确;Stage 1 让模型利用中间视觉证据;Stage 2 用 observation alignment 和 controlled attention 生成 target latent;Stage 3 去掉辅助图像后仍能生成 latent;VLPO 再把 outcome reward 直接作用到 latent。实验上,Monet-7B 同时提升 real-world perception/reasoning 和 OOD VisualPuzzles,说明 latent visual space 是一个值得继续扩展的 MLLM 推理接口。