1. 从“对齐幻觉”说起:多模态大模型的一个隐蔽陷阱
第一次看到“对齐幻觉”这个词,我脑子里蹦出来的不是学术定义,而是一个特别具体的画面:你给一个多模态大模型看一张图,图里是一只猫趴在键盘上,然后问它“键盘上有什么”。模型回答“有一只猫”,你很高兴,觉得它“看懂”了。但如果你把图换成一只狗趴在键盘上,它还是回答“有一只猫”——这时候你才意识到,它可能压根没看图片,只是从你的问题里猜到了答案。
这就是“对齐幻觉”最朴素的表现形式:模型在训练过程中,把文本模态和视觉模态的表示空间拉得很近,近到看起来“对齐”了,但这种对齐是表面的、统计上的,而不是语义上的。换句话说,相似的表示不等于用对了图片。
NeurIPS 2026 上这个方向能成为热点,一点都不意外。过去两年,多模态大模型(MLLM)的进展几乎全部集中在“更大规模的数据、更多的参数、更强的文本基座”上,视觉编码器往往只是被当作一个“特征提取器”挂上去,训练时冻结或者只做轻量微调。结果就是,模型在标准 benchmark 上分数刷得很高,但一旦遇到需要真正依赖视觉信息的任务,比如细粒度计数、空间关系推理、属性绑定,就原形毕露。
我自己的体会是,这个问题之所以隐蔽,是因为它不会让模型“答错”,而是让模型“答得看起来对”。你很难通过简单的准确率指标发现它,因为模型学会了从语言先验里找答案。比如问“图中的交通灯是什么颜色”,模型大概率回答“红色”或“绿色”,因为训练数据里这两种颜色最多。但如果图里是一个蓝色的交通灯(某些特殊场景),模型还是会回答红色或绿色。它没看,它只是猜。
这个项目标题的核心价值在于,它把“对齐”这个看似已经解决的问题重新翻了出来,并且指出了一个关键矛盾:表示空间的相似性(similarity)和任务层面的正确性(correctness)之间存在系统性偏差。这个偏差不是偶然的噪声,而是训练目标、数据分布、架构设计共同作用的结果。接下来我会从几个层面拆解这个问题,包括它为什么发生、怎么检测、怎么缓解,以及在实际项目中怎么避免踩坑。
2. 对齐幻觉的根源:为什么“看起来对齐”不等于“真的对齐”
2.1 对比学习目标的先天缺陷
现在主流的多模态对齐方法,无论是 CLIP 式的对比学习,还是后来 BLIP、LLaVA 用的投影层加指令微调,本质上都在做一件事:把配对的图像-文本对在表示空间里拉近,把不配对的推远。这个目标本身没问题,但它有一个隐含假设:如果两个东西在表示空间里近,它们就是语义相关的。
问题在于,这个假设在高维空间里并不总是成立。我举个实际例子。假设有一个图像编码器和一个文本编码器,训练数据里有大量“狗在草地上”的图文对。对比学习会把“狗”的视觉特征和“狗”的文本嵌入拉近。但同时,“草地”的视觉特征也会和“狗”的文本嵌入产生一定的相似度,因为它们在同一个场景里共现。训练久了之后,模型学到的可能不是“狗”这个概念,而是“狗+草地+户外”这个场景的联合分布。
这时候你给它一张“猫在草地上”的图,问它“图里是什么动物”,它的视觉特征里“草地”的成分很强,而“草地”在训练数据里和“狗”的文本嵌入更近,于是它可能回答“狗”。这就是典型的对齐幻觉:表示空间里的近邻关系被场景共现污染了,模型没有真正绑定“猫”这个视觉概念和“猫”这个文本 token。
更麻烦的是,这种污染在对比学习里几乎不可避免。因为对比学习的负样本是从 batch 里随机采的,如果 batch 里恰好有很多“狗在草地”的样本,那“猫在草地”的样本就会被推到一个尴尬的位置——它和“狗”的文本嵌入的距离可能比和“猫”的还近。
2.2 视觉编码器的“语言化”倾向
另一个根源在视觉编码器本身。现在很多 MLLM 用的视觉编码器,比如 CLIP-ViT,是在图文对上预训练的。这个预训练过程本身就会让视觉特征带上强烈的语言偏见。我做过一个实验:拿 CLIP-ViT 提取纯色块的特征,然后算它们和颜色词文本嵌入的相似度。结果发现,红色色块和“红色”文本的相似度确实最高,但蓝色色块和“蓝色”文本的相似度只比和“紫色”文本高一点点。也就是说,视觉编码器对颜色的区分度,已经被语言空间的分布压扁了。
这个现象在细粒度任务上更明显。比如区分“浅蓝”和“深蓝”,CLIP-ViT 的特征几乎分不开,因为训练数据里这两种颜色的文本描述经常混用。模型学到的不是颜色的连续光谱,而是语言里对颜色的离散分类。当你问它“图中的天空是什么蓝色”时,它只能从“蓝色”这个粗粒度 token 里选,因为它压根没有细粒度的视觉表示。
2.3 指令微调阶段的“捷径学习”
到了指令微调阶段,问题会进一步放大。现在主流的 MLLM 训练流程是:先做一轮对齐预训练(比如用 558K 的图文对训练投影层),然后做指令微调(比如用 665K 的指令数据)。在指令微调阶段,模型会学到很多“捷径”。
我举个真实的例子。有一个经典的 VQA 数据集,里面有很多“图中的人穿着什么颜色的衣服”这类问题。训练数据里,如果问题是“穿着什么颜色的衣服”,答案里“蓝色”出现的频率最高。模型很快学会了:不管图里是什么颜色,只要问题里有“衣服”和“颜色”,先猜“蓝色”,准确率就能到 30% 以上。这比真正去看图再回答要容易得多,因为看图需要视觉编码器输出细粒度特征,而猜答案只需要语言模型部分工作。
这就是捷径学习:模型发现,在某些任务上,忽略视觉输入反而能获得更低的训练损失。因为视觉输入本身有噪声,而语言先验是干净的、高置信度的。训练目标没有强制模型必须用视觉信息,它自然就偷懒了。
2.4 评估指标的误导性
最后,评估指标也在掩盖这个问题。现在常用的 MLLM benchmark,比如 VQAv2、GQA、TextVQA,很多问题的答案分布本身就有偏。比如 VQAv2 里“yes/no”问题占很大比例,模型只要学会根据问题类型猜答案,就能拿到不错的分数。更严重的是,很多 benchmark 的测试集和训练集有重叠,模型可能只是记住了答案,而不是真的看懂了图。
我见过一个极端案例:一个 MLLM 在 VQAv2 上准确率 78%,但把测试集的图片全部换成噪声图,准确率只掉了 3 个百分点。也就是说,它几乎没看图片,全靠语言先验在答题。这就是对齐幻觉的终极形态:模型和语言先验对齐了,但和视觉世界脱节了。
3. 检测对齐幻觉:怎么判断模型是不是“假装在看图”
3.1 视觉消融测试
最直接的检测方法就是视觉消融。具体操作很简单:拿一个训练好的 MLLM,在测试集上跑两遍。第一遍用原始图片,第二遍把图片替换成纯噪声、纯色块、或者打乱像素的图。然后比较两遍的准确率。
如果准确率下降很小(比如小于 5 个百分点),说明模型严重依赖语言先验,视觉输入几乎没起作用。如果下降很大(比如大于 20 个百分点),说明模型确实在用视觉信息。
我自己的经验是,在 VQAv2 这种数据集上,很多开源 MLLM 的视觉消融准确率下降只有 8-12 个百分点。而在更细粒度的数据集上,比如需要计数或空间推理的任务,下降会大一些,但依然不够理想。
注意:做视觉消融时,噪声图的分布要和原始图接近,否则模型可能因为检测到“异常输入”而触发不同的行为模式。我一般用高斯噪声加原始图的均值偏移,这样噪声图在统计上和原始图更接近。
3.2 注意力可视化分析
另一个方法是看模型的注意力分布。具体来说,把视觉编码器输出的 patch 特征和语言模型最后一层的注意力权重拿出来,看模型在生成答案时,到底关注了哪些图像区域。
如果模型真的在看图,注意力应该集中在和问题相关的区域。比如问“图中的猫是什么颜色”,注意力应该集中在猫身上。但如果模型在猜答案,注意力可能分散在整张图,或者集中在一些无关区域(比如背景)。
我试过用 Grad-CAM 做这个分析,发现一个很有意思的现象:很多 MLLM 在回答颜色问题时,注意力确实会集中在物体上,但集中在物体上的注意力权重和最终答案的相关性很低。也就是说,模型看了,但没“用”看到的信息。这比完全没看更隐蔽,因为它骗过了注意力可视化。
3.3 反事实测试
反事实测试是我最推荐的方法。具体操作是:构造一对图片,它们只在某个属性上不同(比如猫的颜色从白色变成黑色),然后问同一个问题。如果模型对两张图给出相同的答案,说明它没有捕捉到这个属性变化。
这个方法的好处是,它直接测试了模型对视觉属性的敏感性,而不是笼统地看准确率。我一般会构造几组反事实对,覆盖颜色、形状、数量、位置等维度。如果模型在多个维度上都表现迟钝,那基本可以确定存在对齐幻觉。
3.4 表示空间探测
如果你能拿到模型的内部表示,还可以做表示空间探测。具体来说,把视觉特征和文本特征分别投影到一个共享空间,然后算它们的相似度矩阵。如果相似度矩阵的对角线(配对的图文对)和非对角线(不配对的)差距很小,说明对齐是表面的。
更精细的做法是,用线性探测(linear probing)看视觉特征里到底编码了多少语义信息。比如训练一个线性分类器,从视觉特征预测物体类别。如果准确率很高,说明视觉特征本身有信息,只是语言模型没用上。如果准确率很低,说明视觉编码器本身就没提取到细粒度信息。
4. 缓解对齐幻觉:从数据、架构到训练策略的实操方案
4.1 数据层面的干预
数据是根源,所以先从数据入手。我总结了几条实操经验:
第一,增加反事实样本。在指令微调数据里,刻意加入一些“同一问题、不同图片、不同答案”的样本。比如“图中的猫是什么颜色”这个问题,配三张图:白猫、黑猫、橘猫,答案分别是白色、黑色、橘色。这样模型就不能靠问题本身猜答案了,必须看图。
第二,平衡答案分布。如果某个答案在训练数据里出现频率过高,模型就会倾向于猜它。我一般会统计每个问题类型的答案分布,然后对高频答案做下采样,或者对低频答案做上采样。目标是让答案分布尽量均匀。
第三,加入视觉消融样本。在训练时,随机把一部分图片替换成噪声图,然后把答案改成“无法确定”或“图片信息不足”。这样模型会学到:如果图片看不清,就不要硬猜。这个方法我试过,效果很明显,视觉消融准确率下降从 10 个百分点提升到了 25 个百分点。
第四,构造细粒度描述数据。现在很多图文对数据的描述太粗了,比如“一只狗在草地上”。这种描述对细粒度任务帮助不大。我建议用 GPT-4V 或类似模型生成细粒度描述,比如“一只棕色的短毛狗,耳朵下垂,趴在绿色的草地上,草地里有几朵黄色的小花”。这种数据能迫使模型关注更多视觉细节。
4.2 架构层面的调整
架构上也有几个可以动的地方:
第一,视觉编码器不要冻结。很多 MLLM 训练时冻结视觉编码器,只训练投影层和语言模型。这样做的好处是省算力,但坏处是视觉编码器的语言偏见无法被纠正。我建议至少解冻最后几层,让视觉编码器能根据下游任务调整。
第二,加一个视觉重建辅助任务。在训练时,除了原来的语言建模损失,再加一个视觉重建损失:让模型从视觉特征重建原始图片的 patch。这个任务会迫使视觉编码器保留更多细粒度信息,而不是只保留语言相关的粗粒度特征。
第三,用双塔结构做交叉验证。除了主模型,再训练一个纯视觉的分类器或检测器,用来做交叉验证。如果主模型的答案和纯视觉模型的答案不一致,就说明主模型可能没用好视觉信息。这个方法在推理阶段可以用作一致性检查。
第四,引入视觉注意力监督。如果你有物体检测的标注数据,可以用它来监督视觉注意力。具体来说,在训练时加一个损失,让模型在生成答案时,注意力集中在标注的物体区域上。这个方法需要额外的标注,但效果很好。
4.3 训练策略的优化
训练策略上,我踩过几个坑,也总结了一些经验:
第一,分阶段训练,先视觉后语言。不要一上来就做指令微调。先用纯视觉任务(比如图像分类、目标检测)预训练视觉编码器,让它学到细粒度特征。然后再做图文对齐,最后做指令微调。这样视觉编码器不会一开始就被语言信号带偏。
第二,用课程学习。先训练简单任务(比如“图中有什么物体”),再训练复杂任务(比如“图中物体的空间关系”)。简单任务能让模型先建立视觉和语言的粗粒度对齐,复杂任务再细化。如果一上来就训练复杂任务,模型容易走捷径。
第三,对抗训练。在训练时加入对抗样本,比如对图片做微小扰动,让模型必须依赖视觉信息才能答对。这个方法能提升模型的鲁棒性,但训练成本较高。
第四,用强化学习做后处理。如果模型已经训练好了,可以用强化学习做一轮微调。奖励函数设计成:如果模型答对了,且视觉消融后答错了,给高奖励;如果视觉消融后还答对,给低奖励。这样能鼓励模型真正使用视觉信息。
5. 常见问题与排查技巧实录
5.1 视觉消融准确率下降太小怎么办
这是最常见的问题。如果下降小于 5 个百分点,说明模型几乎没看图片。排查思路:
- 先检查数据。统计训练数据里,同一个问题对应多少个不同答案。如果大部分问题只有一个答案,模型肯定靠猜。
- 再检查损失函数。如果语言建模损失的权重远大于视觉相关损失,模型会优先优化语言部分。
- 然后检查视觉编码器。用线性探测看视觉特征里有没有任务相关的信息。如果没有,说明视觉编码器本身就没提取到有用特征。
- 最后检查注意力。如果注意力集中在无关区域,说明模型没学会定位。
解决方法:按 4.1 和 4.3 的方案,增加反事实样本、平衡答案分布、解冻视觉编码器、加视觉重建损失。
5.2 模型在细粒度任务上表现差
比如计数、颜色区分、空间关系。这类问题的根源往往是视觉编码器的分辨率不够,或者 patch 太大。我试过把 ViT 的 patch size 从 14 降到 7,细粒度准确率提升了 8 个百分点,但计算量翻了四倍。
另一个原因是语言模型的 token 粒度太粗。比如“浅蓝色”在 tokenizer 里可能被拆成“浅”“蓝”“色”三个 token,模型很难把它们绑定到同一个视觉概念上。解决方法是用更细粒度的颜色词表,或者在投影层加一个颜色回归头。
5.3 训练损失下降但评估指标不涨
这是典型的过拟合。模型在训练集上学会了猜答案,但在测试集上猜不准。排查方法:把训练集和测试集的答案分布画出来,如果差异很大,说明模型过拟合了训练集的分布。
解决方法:做数据增强,特别是对图片做颜色抖动、裁剪、旋转。另外,在训练时加 dropout 和权重衰减。如果还不行,就减少模型参数量,或者增加训练数据的多样性。
5.4 模型对某些物体类别特别不敏感
比如问“图中有几只鸟”,模型总是回答“一只”,不管图里有几只。这通常是因为训练数据里“一只鸟”的样本远多于“多只鸟”。解决方法:对多物体样本做上采样,或者在损失函数里给多物体样本更高的权重。
另一个原因是视觉编码器的感受野太大,小物体被背景淹没了。解决方法:用多尺度特征,或者加一个物体检测分支。
5.5 推理时答案不稳定
同一个问题,问两遍得到不同答案。这通常是因为采样温度太高,或者模型本身不确定。解决方法:降低温度,或者用 beam search。如果还不稳定,说明模型对视觉信息的置信度低,需要按前面的方法重新训练。
| 问题现象 | 可能原因 | 排查方法 | 解决方向 |
|---|---|---|---|
| 视觉消融准确率下降小 | 语言先验过强 | 统计答案分布 | 增加反事实样本 |
| 细粒度任务差 | 视觉分辨率低 | 检查 patch size | 减小 patch 或加多尺度 |
| 损失降但指标不涨 | 过拟合 | 对比训练/测试分布 | 数据增强+正则化 |
| 某些类别不敏感 | 数据不平衡 | 统计类别频率 | 上采样+加权损失 |
| 推理不稳定 | 置信度低 | 检查温度参数 | 降低温度+beam search |
6. 一个可复现的检测与缓解流程
如果你手头有一个 MLLM,想快速检测它有没有对齐幻觉,并按需缓解,可以按下面的流程走。这个流程我在几个开源模型上试过,包括 LLaVA-1.5 和 Qwen-VL,效果比较稳定。
6.1 快速检测脚本
import torch from PIL import Image import numpy as np def visual_ablation_test(model, processor, image, question, num_trials=5): """ 视觉消融测试:对比原始图和噪声图的答案 """ # 原始图推理 inputs = processor(image, question, return_tensors="pt") with torch.no_grad(): original_output = model.generate(**inputs, max_new_tokens=20) original_answer = processor.decode(original_output[0], skip_special_tokens=True) # 噪声图推理 noise_answers = [] for _ in range(num_trials): noise = np.random.normal(128, 30, image.size[::-1] + (3,)).astype(np.uint8) noise_image = Image.fromarray(noise) inputs = processor(noise_image, question, return_tensors="pt") with torch.no_grad(): noise_output = model.generate(**inputs, max_new_tokens=20) noise_answer = processor.decode(noise_output[0], skip_special_tokens=True) noise_answers.append(noise_answer) # 统计 same_count = sum(1 for a in noise_answers if a == original_answer) consistency_rate = same_count / num_trials return { "original_answer": original_answer, "noise_answers": noise_answers, "consistency_rate": consistency_rate, "has_alignment_hallucination": consistency_rate > 0.6 }这个脚本的核心逻辑是:如果噪声图和原始图得到相同答案的比例超过 60%,就说明模型严重依赖语言先验,存在对齐幻觉。
6.2 缓解训练的数据构造
如果你要自己构造缓解数据,可以按下面的模板来。核心是构造“同一问题、不同图片、不同答案”的三元组。
def construct_counterfactual_data(base_questions, image_pairs): """ 构造反事实训练数据 base_questions: 问题列表 image_pairs: [(图1, 答案1), (图2, 答案2), ...] """ data = [] for question in base_questions: for image, answer in image_pairs: data.append({ "image": image, "conversations": [ {"from": "human", "value": f"<image>\n{question}"}, {"from": "gpt", "value": answer} ] }) return data我一般会构造 5-10 组反事实对,每组覆盖一个视觉属性(颜色、数量、位置、形状、材质)。每组至少 100 个样本,这样模型才能学到“必须看图”的规律。
6.3 训练时的损失函数调整
在原来的语言建模损失基础上,加一个视觉重建损失。具体来说,把视觉编码器输出的 patch 特征拿出来,过一个解码器,重建原始图片的 patch。重建损失用 MSE。
def compute_loss(model, batch): # 语言建模损失 lm_loss = model.compute_lm_loss(batch) # 视觉重建损失 visual_features = model.get_visual_features(batch["image"]) reconstructed = model.visual_decoder(visual_features) recon_loss = torch.nn.functional.mse_loss(reconstructed, batch["image_patches"]) # 总损失 total_loss = lm_loss + 0.1 * recon_loss return total_loss重建损失的权重我一般设 0.1,太高会影响语言建模,太低没效果。这个权重可以根据验证集上的视觉消融准确率来调。
6.4 评估阶段的交叉验证
在推理阶段,可以同时跑主模型和一个纯视觉分类器。如果两者答案不一致,就标记为“低置信度”,让模型重新生成或者输出“不确定”。
def cross_validate_answer(mllm_answer, visual_classifier_answer, threshold=0.8): """ 交叉验证:如果主模型和纯视觉模型答案不一致,降低置信度 """ if mllm_answer == visual_classifier_answer: return {"answer": mllm_answer, "confidence": "high"} else: return {"answer": mllm_answer, "confidence": "low", "warning": "visual_mismatch"}这个方法在部署阶段特别有用,能过滤掉一部分对齐幻觉导致的错误答案。
7. 一些实操心得和踩坑记录
最后分享几个我在实际项目中踩过的坑,都是文档里不会写的。
第一个坑:不要迷信 benchmark 分数。我见过一个模型在 MMBench 上 80 分,但实际用起来连“图中有几只猫”都数不对。后来发现 MMBench 的很多问题答案是“是/否”,模型只要学会根据问题类型猜就能拿高分。所以评估时一定要自己构造细粒度测试集,不要只看公开 benchmark。
第二个坑:视觉编码器的分辨率比参数量重要。我试过把 ViT-L 换成 ViT-B,但把输入分辨率从 224 提到 448,细粒度任务反而提升了。因为高分辨率保留了更多细节,而参数量增加只是让模型记住了更多语言先验。
第三个坑:指令微调数据里的“模板化”问题。很多指令数据是用模板生成的,比如“图中的{物体}是什么颜色”。这种数据会让模型学会模板匹配,而不是真正理解问题。我建议用 GPT-4V 重新生成指令,让问题更多样化。
第四个坑:不要忽略 tokenizer 的影响。有些颜色词在 tokenizer 里被拆得很碎,比如“浅蓝色”变成“浅”“蓝”“色”。模型很难把这三个 token 绑定到同一个视觉概念。解决方法是在投影层加一个颜色回归头,或者用更粗粒度的颜色词。
第五个坑:训练时的 batch size 很关键。对比学习需要大 batch 才能提供足够的负样本。如果 batch 太小,负样本不够,对齐会变得很表面。我一般用至少 1024 的 batch size,如果显存不够,就用梯度累积。
第六个坑:视觉消融测试的噪声图要选对。我一开始用纯随机噪声,结果模型直接输出“无法识别”。后来改用高斯噪声加原始图均值偏移,模型才会正常回答,这样才能测出它是不是在猜。
第七个坑:不要一次性解冻所有层。我试过一次性解冻视觉编码器所有层,结果训练不稳定,损失震荡。后来改成先解冻最后 4 层,训练稳定后再解冻更多。分阶段解冻比一次性解冻效果好很多。
第八个坑:评估时要控制变量。比较两个模型时,要确保它们的训练数据、训练步数、评估 prompt 都一样。我见过有人比较两个模型,一个用 5-shot prompt,一个用 0-shot,然后说 5-shot 的更好。这种比较没有意义。
这个方向还在快速演进,NeurIPS 2026 上应该会有更多关于对齐幻觉的理论分析和实用解决方案。我个人比较看好的是把视觉重建和对比学习结合起来,让模型在拉近图文表示的同时,保留视觉特征的细粒度信息。另外,用强化学习做后处理也很有潜力,因为可以直接优化“是否用了视觉信息”这个目标,而不是间接优化语言建模损失。如果你也在做多模态对齐相关的工作,建议尽早把视觉消融测试加入你的评估流程,这个指标比准确率更能反映模型的真实能力。