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 search6. 一个可复现的检测与缓解流程如果你手头有一个 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_trials5): 视觉消融测试对比原始图和噪声图的答案 # 原始图推理 inputs processor(image, question, return_tensorspt) with torch.no_grad(): original_output model.generate(**inputs, max_new_tokens20) original_answer processor.decode(original_output[0], skip_special_tokensTrue) # 噪声图推理 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_tensorspt) with torch.no_grad(): noise_output model.generate(**inputs, max_new_tokens20) noise_answer processor.decode(noise_output[0], skip_special_tokensTrue) 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: fimage\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, threshold0.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 上应该会有更多关于对齐幻觉的理论分析和实用解决方案。我个人比较看好的是把视觉重建和对比学习结合起来让模型在拉近图文表示的同时保留视觉特征的细粒度信息。另外用强化学习做后处理也很有潜力因为可以直接优化“是否用了视觉信息”这个目标而不是间接优化语言建模损失。如果你也在做多模态对齐相关的工作建议尽早把视觉消融测试加入你的评估流程这个指标比准确率更能反映模型的真实能力。