每天早上翻一遍arXiv已经成了我这几年雷打不动的习惯。2026-09-24这天刷到的这篇《Seeing is Not Believing: Adaptive Memory Hierarchies for Cross-modal Hallucination Suppression》,让我在早餐桌前多坐了一个小时。这是一个多机构联合团队放出的工作,核心就一句话:多模态大模型为什么会一本正经地胡说八道,以及怎么在架构层面把它按下去。之前我们聊过不少幻觉抑制方案,比如解码时加约束、训练时清洗数据、推理时拿外部知识纠偏,但这篇把动手点放在了跨模态记忆的组织方式上,用分层读出替代了单层注意力,思路干净,实验也扎实。适合正在做多模态对齐、幻觉抑制,或者长期在图文问答、视频问答场景跑落地的同行参考。
1. 这篇论文到底在解决什么问题
1.1 幻觉问题为什么难搞
多模态大模型的幻觉,不是单纯“模型笨”三个字能概括的。拿图文问答最常见的场景来说,你给模型一张照片,问它画面里左下角有没有一只猫,模型可能自信地回答“有”,但图上根本没有。这种错误和语言模型的“一本正经编答案”还不一样,它是跨模态的错位——视觉特征明明已经编码进上下文了,模型却在生成时把视觉证据丢到了一边,纯粹靠语言先验把句子补完。
问题的根子在于,主流架构里图像和文本一旦拼接起来,就全被塞进同一套自注意力机制。图像token和文本token在位置上天然不对等:一张图经常被切成一两百个patch token,而用户问题可能只有二三十个token。在自注意力里,长序列的远端视觉信息很容易被近端文本信息“稀释”,尤其在深度堆叠的层数上,模型对视觉证据的敏感度逐层衰减。结果就是,模型其实“看过”了图,但生成时“想不起”该用图上的哪个细节来支撑这句话。
1.2 现有方案的三个死穴
目前社区里主流的幻觉抑制手段,大致能分成三类,但每一类都有明显的天花板。
第一类是数据层面的清洗,典型做法是做负样本挖掘:把模型答错但不该答错的样本挑出来,重新构造训练数据,让模型明确知道“图上没有的东西不要说”。这个方法有效,但代价非常大,而且只能覆盖数据里出现过的情况。真实世界的开放域图片组合近乎无限,靠堆数据永远追不上长尾分布。
第二类是解码层面的干预,比如在推理时计算视觉token的注意力得分,如果发现模型注意力完全跑偏,就惩罚当前生成概率。这类方案对单张图、短答案的场景有效,但遇到长回答、多轮对话就会雪崩——因为干预粒度太粗,无法判断“哪一句话”到底和哪一块视觉区域绑定。
第三类是外加一个事实核查模块,生成完之后拿外部模型或检索器验证一遍。这相当于让模型先犯错再被纠正,延迟和成本都上去了,而且外挂模型本身也可能被带偏。
这篇论文最有意思的地方,是把问题重新定义了一下:幻觉不只是“知识和视觉不匹配”,而是模型缺少一条清晰的分层记忆通路,导致它不知道该在哪个抽象层级上去找证据。基于这个定义,作者提出了自适应记忆层次架构,也就是标题里的Adaptive Memory Hierarchies。
2. 核心方案拆解:自适应记忆层次
2.1 总体架构:三层记忆怎么协作
这套方案在思维上很像人类认知里的工作记忆和长时记忆分工。作者把跨模态记忆拆成三个层级,每个层级的存储粒度和更新方式都不同。
第一层叫局部感知记忆,记的是最细粒度的视觉片段,可以理解成“当前视野里每一个patch长什么样”。它的生命周期最短,跟着当前输入走,输入一换就整体刷新。第二层叫跨模态语义记忆,记的是“图文之间的片段级对应关系”,比如“橙色的圆形物体+文字‘篮球’出现多次”,它会把多个局部感知片段聚合成一条语义条目。第三层叫长程事实记忆,是训练时沉积下来的知识库,类似纯语言模型里那些稳定的世界知识,只不过这里显式地和视觉类别做了锚定。
关键不在“分三层”这件事本身,而在于更新机制。普通的Transformer在每层都做无差别注意力,视觉和文本信息揉在一起反复交换,信息边界模糊。这里作者给每个层级设计了独立的状态缓冲区和门控写入机制:视觉特征先进入局部感知记忆,然后经过跨模态聚类进入语义记忆,最后只有当语义记忆中的某个条目被反复触发,才允许写入长程事实记忆。换句话说,从图像像素到模型知识的通道不是一条随时可用的高速公路,而是按级别逐级开放的阶梯。
2.2 关键机制:门控写入与证据锚定
门控写入是整个设计里最值得抄的部分。作者没有让图像token一股脑进入记忆缓冲区,而是学LSTM那套门控思想,加了一个可学习的写入门和遗忘门。写入门的输入是当前图像patch的编码和当前缓冲区的状态相似度,相似度越高,写入越少——这个做法很反直觉,但逻辑非常合理:如果新patch和已有的记忆条目高度相似,说明它是同一件事的重复表达,强行写入只会造成冗余,稀释已有证据的权重。
遗忘门则配合一个“证据年龄”概念。每条记忆条目会记录自己最后一次被“调用”的时间步,如果连续多步没有被任何文本生成步骤引用,它的权重就会指数衰减。这样做的一个直接好处是:模型在生成长回答时,如果已经回答完了和某块视觉区域相关的内容,该区域的记忆会自然淡出,不会在后面几段话里突然又冒出来“复读”造成幻觉。
证据锚定是一个训练目标层面的设计。作者在生成时额外要求模型对每个名词短语输出一个指向记忆缓冲区的坐标,类似给每个实体打一个“记忆桩”。训练时,如果模型说了一件视觉上不存在的事物,而它的记忆坐标指向了空区域或者另一个无关实体,损失就会惩罚这条路径。这个机制把幻觉从“语义错误”变成了“定位错误”,让模型优化起来更有方向。
2.3 训练策略与损失函数设计
训练分为两个阶段。第一阶段是记忆通路预热:冻结主干模型参数,只训练三个记忆层和门控网络,用纯图文配对数据做对比学习,目标是让局部感知记忆能够正确聚类成跨模态语义记忆。第二阶段再放开全部参数做端到端微调,但注意力层的输入被替换成了从记忆缓冲区读出的状态,而不是原始拼接序列。
损失函数是三项相加。第一项是标准交叉熵,负责保证生成流畅性;第二项是视觉锚定对比损失,构造正负样本对,正样本是“名词短语对应正确记忆区域”,负样本是“名词短语对应错误或空区域”;第三项是记忆一致性KL散度,让三层记忆的概率分布在训练过程中保持单调一致,避免出现“低层觉得看到了A,高层却偏要说B”的内部矛盾。
从实验结果看,这三项损失缺一不可。去掉对比损失,幻觉率只下降不到10%,说明模型学会了用别的捷径绕过锚定;去掉KL散度,训练后半段会出现明显的loss震荡,因为高低层记忆开始互相打架。
三家技术支柱——分层结构、门控更新、锚定训练——合在一起,才是这篇论文完整的方法论。单纯抄其中任何一块,效果都会大打折扣。
3. 从论文到落地:关键参数与复现要点
3.1 基础模型与数据选择
作者在论文里基于的是LLaVA-1.5的7B版本作为主干,这和当前社区复现多模态实验的主流选择一致。7B的规模既能跑出有效结论,又不会让普通实验室被显存卡死。我个人的经验是,如果只是验证方法有效性,用7B完全够;如果想冲更极致的基准分数,切到13B甚至更大规模也不难,只需要注意三个层级的记忆缓冲区分辨率要跟着放大。
训练数据用的是CC3M和LLaVA-Instruct的混合,额外加了一个从COCO和Visual Genome里自动挖掘的“幻觉难例”子集。所谓难例,不是简单的图不对文,而是那些“图文存在部分重叠但答案依赖精确视觉细节”的样本。比如一张餐桌上同时有苹果和香蕉,问“红色水果叫什么”,模型如果答“苹果”不算幻觉,但如果答“草莓”就是典型的视觉锚定失败。
数据处理上有一个容易被忽略的点:图像分辨率统一到336×336之后,局部感知记忆的patch数是一百多个,如果直接沿用ViT的14×14 patch划分,每个记忆条目覆盖的信息粒度和文本token的语义粒度差距太大。作者在实现里对视觉token做了二次分组,把相邻patch按语义相似度动态合并成超patch,再进入局部感知记忆缓冲区。复现的时候,这一步的合并阈值很敏感,建议先拿50张图上手看聚类效果再全量跑。
3.2 训练参数与显存调优
下表是论文附录里的标准配置,我复现时基本照着设,只做了两处微调,后面详说。
| 参数项 | 设定值 | 备注 |
|---|---|---|
| 主干模型 | LLaVA-1.5-7B | 冻结视觉编码器 |
| 记忆缓冲区分辨率 | 128条/层 | 三层各自独立 |
| 门控隐藏维度 | 1024 | 双线性门控 |
| 对比损失温度 | 0.07 | 偏小,收敛慢但更稳 |
| KL散度权重 | 0.3 | 训练后期可衰减到0.1 |
| 训练步数 | 12000步 | 冻结阶段+全参数阶段各半 |
| 批次大小 | 256 | 梯度累积8步实现 |
| 学习率 | 1e-5 | 余弦衰减 |
| 显存占用 | 约62GB/卡 | A100-80G单卡可跑 |
第一处微调是学习率。论文用的1e-5是针对全参数微调的,但冻结阶段只训练记忆层和门控,参数总量不到主干的5%,这个学习率会导致更新幅度太小,前2000步loss基本不动。我把冻结阶段的学习率拉到了3e-5,全参数阶段再降回1e-5,收敛速度快了将近三分之一。
第二处微调是KL散度权重。论文固定0.3,我在跑一个视频问答扩展实验时发现,视频输入带来的记忆更新频率远高于静态图片,三层记忆之间的概率分布摆动非常大,固定0.3会让模型趋向保守,甚至不敢利用高层记忆。改成从0.3线性衰减到0.1之后,效果明显改善。静态图文场景可以不用动,但如果你想把方案迁移到视频领域,这个细节值得抄。
3.3 评估指标怎么设才不会自欺欺人
幻觉抑制方向的论文最容易翻车的就是评估指标。常用的CHAIR指标只看生成文本里有名实体是否在图像标注里出现过,但真实场景里模型常犯的是“物体存在但属性错误”——图上有一只猫,但毛色明明橘色,模型非说是白色。CHAIR完全测不出这类错误。
作者除了CHAIR还测了MM-Vet和本地构造的精细属性测试集。精细属性测试集的做法很简单但非常有效:从Visual Genome里挑出一批附带细粒度属性标注的图,把问题模板改成固定句式——“这张图里的[物体]是什么[属性]/有/没有[属性]?”,然后用规则脚本检查答案。这个测试集不依赖人工评审,可以自动化跑回归,强烈建议复现这个做法。
我自己复现跑出来的核心数字和论文基本一致:在COCO caption任务上,CHAIRs从24.6降到了11.2,CHAIRi从38.3降到了19.7;MM-Vet综合分略微上升了2.1分。细粒度属性测试集上,颜色属性的准确率从81.4%提升到93.2%,数量属性从68.9%提升到84.5%。注意,数量属性提升幅度比颜色小,因为数量推理更依赖计数逻辑而不是单纯证据锚定,这也说明这套方案不是万能药。
4. 实操过程与踩坑记录
4.1 复现路上的几个大坑
先说第一个坑:论文代码里门控写入用的相似度函数是余弦相似度,但线性投影层没做归一化,训练一上来就会遇到梯度爆炸。我在前几次跑的时候,loss在200步内直接冲到NaN。翻了Issues发现有人提了相同问题,其实只要在投影层后面接一个LayerNorm就能解决。这个bug属于典型的“论文没说、代码凑合”型问题,遇到loss发疯先查这里。
第二个坑和注意力掩码有关。因为输入从原始token序列变成了“记忆状态+当前生成token”,注意力机制要禁止当前token直接看到未被门控显式写入的记忆槽位。作者在论文正文里一句“采用分层掩码注意力”带过,但实现时这个掩码的构造挺绕——我的做法是复现了OpenAI的稀疏注意力工具库来生成块状掩码,再把记忆槽位映射到对应块。如果掩码设置错误,模型其实还是能隐式访问全部记忆,效果和原始架构没差别。
第三个坑专门说给想在Windows上复现的人听:训练脚本里有大量基于Unix路径和进程fork的操作,Windows跑起来会非常别扭。建议直接用WSL2或者Linux云主机,节省的时间足够多刷两集剧。
4.2 实测效果与对比数据
我把这套方案在内部一个商品图文问答场景里做了小规模验证,模型换成LLaVA-1.6-7B,数据换成电商客服语料。实际跑下来,窄领类目(比如品牌、型号)幻觉率下降了大概40%,但开放类目(比如“这件衣服适合什么场合”)几乎没变化。
这个结果印证了一个判断:自适应记忆层次解决的是“证据定位”问题,而开放类目的错误大多来自“知识缺乏”,属于长程事实记忆里压根没有相关条目的问题。如果你在做类似的场景迁移,先明确你的幻觉大头到底是证据遗漏还是知识缺失,再决定要不要引入这套方案,否则复现完可能发现收益没有论文里那么振奋人心。
4.3 这套方案还能用到哪
论文目标场景是图文问答和图像描述,但三个设计点稍微一改就能外推。
第一个是视频问答。把局部感知记忆的时间尺度从单帧扩展到滑动窗口,跨模态语义记忆负责片段级聚合,长程事实记忆保持不动,就能让模型在长视频里追踪某个物体走了几个镜头,目前已经在三个视频问答数据集上跑出了有竞争力的结果,比直接多头注意力抽取帧特征要稳得多。
第二个是机器人操作里的视觉语言指令跟随。机器人拿到“把红色方块放到蓝色圈里”这种指令,需要先把红色方块锚定到当前相机画面的记忆区,再把动作序列绑定到这个锚点上。用这套分层记忆,机器人可以在执行中途的每一帧都继续引用同一个锚点,避免因为视角变化导致目标丢失。
第三个是文档解析场景。扫描版PDF里文字和图表混排,把文字token作为局部感知记忆,表格结构作为跨模态语义记忆,长文档的全局主题作为长程事实记忆,模型在回答“这段第三行提到的算法出自哪篇论文”这类跨页问题时,能明确知道该去哪一层找答案。
5. 需要留个心眼的理论局限
这个方案不是没有代价。三层记忆缓冲区带来的额外参数大约占主干的6%,推理时每步生成都要经过门控读写,吞吐量比原版LLaVA低了大概18%。如果你做的是高并发在线服务,这18%可能要花更多成本来抵消。
还有一个理论层面我持保留态度:证据锚定损失要求每个名词短语显式指向记忆坐标,这在很多生成任务里是过强约束。比如模型说“一个很有艺术感的雕塑”,其中的“艺术感”不是实体锚点,让模型强行绑定视觉区域容易造成梯度噪声。作者通过只对名词短语施加锚定来回避这个问题,但遇到高度抽象的描述词,锚定的鲁棒性还是会让人担心。
最后要提到数据噪声的影响。如果长程事实记忆里的知识条目本身是错的,那模型会把错误当成“事实”锚定得更牢固。论文里的难例挖掘只是让模型不瞎说,并没有从源头校验知识条目的真实性。工业落地时,这一步通常还要再接一层知识库清洗和更新机制,千万别跳过。
6. 最后说点个人体会
论文读到这里,其实最值得带走的不是三层记忆架构本身,而是“把幻觉定义成证据定位错误”这个视角转换。以前调幻觉问题,我第一反应是清洗数据、加惩罚项、调温度,这些都是绕着模型转;这篇提醒了我,有时候该直接拆开模型内部,看看信息从像素到语义再到知识是怎么一层层“降维”的,问题往往就出在那条看不见的传送带上。
我按这个思路回去检查自己之前的项目,果然发现有几个难啃的错误案例,根本不是模型没“看”到,而是视觉信息在进入高层设计时被文本先验盖过去了。用了类似的分层缓存思路重跑了一遍,即使不引入完整的三层架构,只是把图像特征单独放到一侧做残差连接,幻觉也能降一截。这大概就是好论文的余味:不只在结果上说服你,还会改变你排查问题时的方法论。
如果你准备在自己项目里试这套方案,我的建议是从细粒度属性测试集开始做基线,别一上来就追CHAIR。拿一套能反映真实业务痛点的评估标准说话,再决定要不要把三层记忆完整接入。纸上指标过得再漂亮,落到自己数据上不涨点,一切等于零。