
如果你正在做多模态预训练大概率会遇到一种奇怪的现象训练 loss 一直在降zero-shot 准确率却涨得很慢甚至停滞很久。你会怀疑是学习率不对于是调低学习率还是不动你会怀疑是数据量不够于是继续加数据结果变化依然有限。这时候真正该检查的往往不是优化器而是知识有没有在模态之间流动起来。最近在看多模态预训练相关工作的时候有一个标题给我留下了很深印象它没有直接提出一种新架构而是试图用四个概念——知识流动、模态协同、早期统一、配方——把多模态预训练里那些“只说得出感觉、说不清机制”的问题统一起来。一开始我觉得这只是写作上的包装后来用这四个词去回看自己的训练经验发现确实能解释很多以前只能归咎于“玄学”的现象。这篇文章我想围绕这四个方向展开但不会面面俱到地去罗列模型对比。我更想把它当作一套分析框架来回答一个具体的问题当你训练一个多模态模型时为什么有些模型长期不温不火另一些模型结构相似却能在跨模态任务上表现更好差异到底发生在哪一层这会是一篇偏方法论和经验判断的文章不是模型源码逐行讲解。如果你正准备从零开始做一个图文预训练项目或者已经在训练过程中反复调不动这篇文章应该能帮你把问题定位到更准确的环节。1. 多模态预训练的“黑箱”先从知识流动说起1.1 知识流动不是泛泛而谈而是有方向、有路径、有损耗的信息迁移多模态预训练最常见的范式是拿海量的“图像-文本对”让模型把图像和文本映射到同一个语义空间。公开论文里非常经典的实现方式就是对比学习图像编码器抽出一批图像特征文本编码器抽出一批文本特征正样本对在空间里尽量靠近负样本对尽量远离。训练结束之后我们默认两个模态的表示已经“对齐”了。但“对齐”只是最终目标不是训练过程的机制。真正值得问的是梯度信号是怎么从文本侧流到图像侧又从图像侧流回文本侧的哪些层承担了语义对齐哪些层只是在各自模态内部做特征提取如果你把多模态 Transformer 看成一个信息网络知识流动就是一条有方向的路径。在跨模态 attention 层文本 token 可以读到图像 token 的表示图像 token 也能读到文本 token 的表示。这个交互发生在浅层语义信息会更早混合如果发生在深层两个模态的编码器基本就是各跑各的最后在某个融合层做一次“见面”。更关键的是知识流动是有损耗的。文本侧如果“太强”图像侧特征可能被当成无关噪声图像侧如果“太强”文本的抽象语义又会变得模糊。这种损耗不会直接显示在 loss 曲线上但会在下游任务上暴露出来。所以我理解标题里“物理”这个词想表达的并不是物理定律而是多模态训练背后那些稳定、可观察、可验证的规律。你不需要像物理学家一样推导公式但至少要知道知识在模型内部是从哪里流向哪里又在哪里可能断掉。1.2 怎么判断知识真的流动了不只是看 loss判断知识有没有真正流动单看训练 loss 是不够的。loss 下降只能说明当前训练目标在被优化不能说明两个模态形成了有效的交互。我一般会按顺序做四件事看 zero-shot 是否对模态敏感。固定图像侧换一批文本固定文本侧换一批图像。如果无论怎么换模型输出都没有明显变化说明知识流动很可能已经中断。做一次“模态置换”实验。把图像替换成随机噪声看文本输出是否仍然“看起来合理”。如果依然合理而且性能几乎不掉说明模型已经退化成依赖文本路径的模型视觉信息没有被真正利用。反过来做一次。把所有文本替换成占位符看视觉识别任务是否仍然正常。如果视觉性能大幅下降说明跨模态知识没有回流到视觉侧图像编码器并没有因为引入了文本而变得更强。观察两个编码器的梯度 norm。对比学习训练中如果视觉侧梯度长期接近零说明视觉编码器基本停了模型只是在用文本侧的表征“硬凑”结果。这些实验都很简单但能帮你区分一个关键问题你的模型是在协同处理两个模态还是只在其中一个模态上做“单模态拟合”。1.3 知识流动断裂的常见信号下面这几种情况在实际训练中非常常见信号一loss 持续下降但 zero-shot 不涨。这通常意味着模型学到的不是语义理解而是在匹配表层统计特征。比如图像和文本里都经常出现某个固定颜色模型可能就直接用颜色当作匹配信号。信号二单模态下游任务提升巨大跨模态任务毫无进展。这说明两个模态各自都有不错表征但共享空间没有形成。信号三继续加数据效果没有改善。如果知识流动路径本身有问题更多数据只会固化错误的通路。遇到这些信号我的建议是先不要急着加 batch size也不要马上换模型。先做上面那组“模态置换实验”确认是哪一侧知识断了再决定修哪条链路。知识如果没有流动加数据只是放大噪声流动方向不对换更大的模型只会更快跑偏。2. 模态协同的核心问题谁来主导谁在补充谁在退化2.1 对比学习与生成式统一两种协同哲学的差异模态协同听起来像是一个很正面的词好像两个模态天然应该互相帮助。但实际训练里协同关系非常脆弱。不同训练范式的协同方式也不一样。对比学习本质上是让两个模态在共享空间里互相“校准”。它修的是双向高速路图像往文本方向走文本往图像方向走两者靠近就奖励远离就惩罚。这种方式的优点是稳定结构简单负样本设计得当就能学到不错的匹配关系。缺点是它只能学“相关性”很难学“因果性”。模型知道哪张图和哪句话经常一起出现但不知道一句话之所以成立是因为图像里那个关键物体提供了底层证据。生成式统一则是另一套哲学。常见的做法是把图像转换成离散 token用文本模型去预测或重建这些 token或者反过来。它的协同方式更密模型每预测一个 token都在用另一个模态的信息做条件。有人会觉得这更接近“真正理解”但它也有代价图像 tokenization 会损失细节生成目标可能让模型过度关注低频显式语义忽略视觉上不明显但很关键的信息。打个比方对比学习像是两个人共享一份共同笔记每个人用自己的语言把笔记补充完整生成式统一像是一个人要求另一个人按照自己的语法复述刚才看到的一切。前者容易取得共识但共识可能很浅后者容易暴露理解漏洞但训练不稳定。2.2 模态塌缩强模态把弱模态“吞噬”了模态协同里最容易出现的问题是模态塌缩。这不是训练崩溃而是模型找到一个偷懒解主要依赖信息更密集、更容易预测的模态忽略另一个模态。在图文预训练里被忽略的往往是视觉侧。原因是文本往往包含更显式的语义一个句子通常直白地描述主体、动作、颜色、关系而图像尤其是网络爬取的小图、模糊图、抽象图信息提取难度更高。模型在训练中发现只要把文本路径走好loss 就能降下来于是视觉编码器的梯度越来越少图像特征几乎不再变化。模态塌缩的典型表现视觉编码器梯度 norm 长期偏小甚至几乎不动。在图文检索任务里把图像换成噪声检索结果没有明显变化。图像侧单模态评估指标涨得很慢文本侧却一路高歌。根本原因通常不在权重初始化而在于数据对太弱、负样本太难或太简单、对比损失权重失衡、温度参数不合适。模型在训练中会自动选择“低垂果实”哪一个模态更容易拟合就把哪个模态当作主要依据。2.3 用权重、数据配比和“换模实验”调节协同关系想让两个模态保持协同而不是一方被压制需要做一些显式干预。第一不要让单模态监督信号消失。可以在对比 loss 之外给两个模态各自加一点单模态任务。比如图像侧加一个掩码图像重建文本侧加一个掩码语言建模。这样即使对比分支里某一侧梯度变弱模型仍然有动力维护该模态的表征质量。第二调整数据配比。不是所有 image-text pair 难度都一样。如果数据里大量是“一张蓝天图配一句蓝天白云”这种极其直白的对子模型很容易只看文本忽略图像细节。尽量让图像分辨率、清晰度、物体复杂度以及文本长度、表达风格、语义粒度都有足够的分布宽度。这样模型才会被迫在两个模态之间来回寻找信息。第三把温度参数当成一个需要观察的对象而不是一次设好就不管。对比学习里的温度会影响负样本的区分难度。温度太小模型会过度关注难负样本训练震荡温度太大负样本区分度过低两个模态特征会被“拉成一团”。我习惯在训练初期把温度设得略高等 loss 稳定后再逐步降低让负样本的压力随训练逐步增加。我常用下面这张表做协同问题的快速诊断现象可能原因先查什么图像换成随机噪声结果几乎不变视觉路径被忽略视觉 encoder 梯度、图像数据质量、对比 loss 权重文本换成随机词结果几乎不变文本路径被忽略文本 encoder 梯度、文本数据多样性两个模态单测都很好跨模态任务差共享空间没有形成投影头结构、负样本质量、温度参数训练震荡loss 反复跳温度或学习率不合适初始温度、warmup、梯度范数这张表背后其实是一个更通用的方法先确认哪一侧在工作再决定改哪一块。不要一上来就把所有超参都重调一遍那样你永远不知道真正的原因是什么。3. Early Unification 不是“越早越好”而是一次风险换收益的选择3.1 Early Fusion 与 Late Fusion 的本质区别在讨论多模态架构时我们常听到 Early Fusion 和 Late Fusion。这组概念听起来像是一种编码方式但从训练视角看它更像一个“时机选择”两个模态的信息到底在模型的哪个阶段开始交互。Late Fusion 的做法是每个模态先独立编码最后在高层的融合层做交互。图像编码器只管图像文本编码器只管文本最后把两个表示拼在一起或做一个 attention。优点是稳定各个模块可以独立调试出问题时容易定位。缺点也很明显信息交互的时机太晚视觉细节和文本语义往往很难对上。Early Fusion 的做法是在模型输入阶段就把视觉 token 和文本 token 拼接在一起一起送进同一个 Transformer。从第一层开始两种模态就会相互影响。早期统一的好处在于跨模态交互可以发生在前几次 attention 里模型有更多机会学到跨模态的组合特征而不只是最后做一次浅层匹配。但这里必须澄清一个容易混淆的点很多公开的多模态模型并不是真正的 Early Fusion。有的是在视觉编码器后面接一个 connector再把输出送入语言模型有的是用 cross-attention 把视觉信息“注入”文本生成过程。这些方案都算融合但交互深度不同。真正意义上的早期统一要求两种模态的 token 在最底层就进入同一个骨干网络共享同一套 query、key、value 映射。3.2 早期统一的好处知识可以更早地交叉回流早期统一最吸引人的地方是让知识在模型能力边界处就互相“开会”而不是等到最后加一个决策头去缝合。举个例子。如果视觉 token 和文本 token 从第一层就一起进入 Transformer那文本的 attention 可以在很浅的层次就“看到”图像区域。模型不再需要等深层编码器把视觉信息抽象成高级语义后才去匹配文本而是在特征还是边缘、颜色、纹理时就开始交互。这对细粒度对齐非常有帮助比如“红色的汽车”这种概念文本侧知道红色视觉侧看到红色区域两个信号可以在浅层直接建立连接。早期统一还有一个容易被忽略的好处它能让文本信息回流到视觉编码器。对比学习里视觉 encoder 只知道图像和文本是否匹配但不知道文本具体说了什么早期统一让视觉 token 直接接收文本 token 的影响视觉表征会学到更多语言能描述但纯视觉任务不关心的语义维度。对于中小规模的模型这种深度交互通常能显著提升表示质量。但对于超大规模模型早期统一也不是越早越好。它相当于把两种异源信息丢给同一个优化器去解耦优化难度会明显上升。3.3 成本与风险稳定性和可调试性下降早期统一的代价最直接地体现在训练稳定性和可调试性上。如果你没有用预训练好的单模态编码器初始化两个模态一起从头训练大概率会跑出“两个模态都不像样”的结果。这个阶段图像 token 和文本 token 在语义空间上完全没有对齐关系网络需要同时解决两个完全不同域的表征优化器会非常忙碌loss 曲线会表现出明显的高方差。显存开销也不可忽视。从底层开始保留两种模态的激活对长序列和超大分辨率非常不友好。如果你要同时处理高分辨率图像和长文本早期统一很容易遇到显存瓶颈进而被迫减小 batch size而 batch size 又是对比学习效果的重要变量之一。更麻烦的是调试体验变差。Late Fusion 出问题时你可以单测图像 encoder、单测文本 encoder、检查融合层快速定位是哪一段坏了。Early Fusion 一旦训练效果不好你会不太容易回答“这个问题到底出在视觉侧、文本侧还是融合阶段”。排查范围一下子变大了。3.4 实操建议先 Late 后 Early我的建议是如果你是第一次做多模态预训练先把 Late Fusion 跑通。验证数据链路、loss、评估流程都稳定之后再考虑切换到早期统一。切换时一次只改一个变量。比如先把文本 token 接入层从最后一层换到倒数第二层观察效果稳定后再逐步深入不要一步从 Late Fusion 直接跳到最底层接入。这样一旦出现性能回退你能大概知道问题发生的位置。同时一定要保留一份单模态 checkpoint。早期统一可能提升跨模态能力也可能让单模态能力下降或遗忘。如果只记录最终多模态指标你会以为效果变好了但实际可能只是模型借助文本信息把测试集刷上去了视觉编码器本身的表征已经退化了。不要为了“显得先进”直接选早期统一。先看你的基线是否稳定。如果 Late Fusion 都跑得不稳定Early Fusion 只会把问题函数放大。4. Recipes把每个训练决策变成可复现的实验记录4.1 为什么很多多模态训练经验更像“手艺活”多模态训练的高方差来自大量隐性变量数据顺序、负采样分布、学习率调度、温度参数、初始化、batch 组合、梯度裁剪、评估阶段。论文里通常只报告一组最终配置但同样的配置在不同数据、不同初始化下结果可能差很多。这也是“recipe”这个说法成立的原因。它把经验从“感觉”变成“记录”从个人记忆变成团队资产。如果你今天用一组参数跑出了好结果但没有完整记录数据版本、模型配置、优化参数和评估策略那这组结果对团队没有任何复现价值。更现实的情况是同一个项目、不同的人来跑结果可能差距很大。原因不是代码写得不一样而是训练多模态模型的“手感”掌握在少数人手里。把配方显式化是一种把“手感”转化为工程能力的方式。4.2 一个最小可复现配方包含哪些内容一个完整可复现的多模态训练配方至少包含四块数据配方、模型配方、优化配方、评估配方。数据配方要记录数据来源、清洗规则、图像文本对的过滤条件。比如字幕长度过滤、图像分辨率下限、宽高比范围、去重阈值以及训练集和验证集的划分方式。验证集绝对不能和训练集共享同一数据流否则你看到的指标全是幻觉。模型配方要记录图像编码器结构、文本编码器结构、投影头层数和维度、温度参数初始值。更细节的还包括位置编码方式、是否冻结某些模块、归一化层放在哪里。优化配方要记录优化器、学习率、权重衰减、warmup、batch size、梯度累积步数、混合精度策略以及损失函数中每个任务项的权重。评估配方要记录每隔多少步跑一次评估、选择哪些 zero-shot 任务、保存策略是 best checkpoint 还是 last checkpoint、最终采用什么指标。我整理过一个最小配置表的常见取值范围注意这是实践参考不是标准答案项目常见取值范围说明图像编码器ViT-B/32 起步大容量适合大数据小容量适合快速验证文本编码器Transformer 6~12 层取决于文本长度和任务复杂度投影头MLP 1~3 层输出 256~1024 维不是越深越好先浅后深对比温度 τ初始 0.07 左右需要随训练调整过大过小都会影响结果batch size对比学习常见 4096 以上小 batch 也能跑但需要更多步数学习率1e-4 ~ 1e-3 区间起步需要按 batch size 缩放warmup1000~5000 步避免早期动力学失稳如果你想快速验证一个想法可以先用一个最小的脚本把链路跑通。对比学习训练循环的伪代码结构通常是这样的# 一个示例性的对比学习训练循环伪代码 for images, texts in dataloader: img_feat image_encoder(images) # [B, D] txt_feat text_encoder(texts) # [B, D] img_feat l2_normalize(projector(img_feat)) txt_feat l2_normalize(projector(txt_feat)) logits img_feat txt_feat.T / tau # [B, B] labels arange(B) loss cross_entropy(logits, labels) loss.backward() optimizer.step()这段代码看起来很简单但真正影响结果的往往在代码之外负样本怎么构成、温度怎么更新、batch 里图像文本是否均匀、评估集是否稳定。这些才是配方里最容易被忽略的部分。4.3 从单卡到多卡稳定性验证与日志记录很多人拿到一套多模态训练代码第一件事就是直接把 batch size 拉大机器越多越好。我见过太多项目在单卡上正常一上多卡就出问题。正确的顺序应该是先在单卡上用很小的 batch size 跑 1000 步左右确认 loss 可以下降、梯度范数合理、投影头输出没有 NaN。再切到多卡保持 batch size 不变仅仅增加设备数确认 loss 曲线和单卡时保持一致。如果有明显偏差先检查数据加载、随机种子和梯度同步。在 batch size 真正扩大之后再调整学习率。学习率缩放规则有很多种linear scaling 和 sqrt scaling 会给出不同建议但公认要点是batch size 变大学习率通常也要变大但不能无限制变大。整个过程中日志至少需要记录 step、loss、learning_rate、temperature、grad_norm、当前评估指标和数据 index 版本。只记录 loss 不记录 grad_norm排查问题时会缺少关键证据。很多训练异常会先表现在梯度上然后才表现在 loss 上。梯度突然消失或爆炸往往比 loss 突变更早出现。4.4 排查链路训练 Loss 下降但效果不涨按什么顺序排查如果你遇到“loss 正常但效果不涨”的经典情况我建议按下面顺序排查先看评估链路。是不是评估代码加载了旧模型数据加载是否出错类别顺序是否和训练时不一致这步虽然基础但最容易浪费时间。先排除工具链否则后面所有排查都在错误的地基上。再做“换模实验”。把图像或文本替换成随机输入看模型表现是否退化。如果模型对某侧输入的变化不敏感说明该模态没有在预测中发挥真实作用。再检查数据质量。随机抽 1000 条 image-text pair人眼检查配对语义是否一致。对比学习对负样本分布极度敏感。如果负样本太简单模型不需要理解语义就能区分如果负样本太难loss 下降也不代表正样本排在前面。再检查优化参数。温度 τ、负样本数量、batch size 是否合理。如果 batch size 只有 256一个 batch 里只有 256 个负样本对比学习的区分能力很有限。最后再看模型容量和结构。如果以上都没问题才考虑是不是视觉编码器太弱、投影头太浅、融合时机太晚或太早。这个排查链路的核心原则是先确认问题的位置再决定改什么。不要因为效果不涨就同时调整数据、模型、loss 和优化器。那样就算最后效果变好了你也无法判断是哪个因素起了作用。5. 从复现基线到建立自己的评估闭环5.1 先复现再改动一次一条变量的纪律多模态预训练非常容易让人产生“想同时验证很多新想法”的冲动。今天想换一个更大的视觉编码器明天想改损失函数后天又想引入一个新的生成式辅助任务。如果所有改动同时进行出了问题时你会完全不知道是哪一个模块出了错。更稳妥的做法是先复现一个公开基线记录它在你环境里的指标和训练曲线。这次复现不要跳步保持和原论文一致的优化器、学习率、batch size、数据预处理。哪怕复现结果不完美也记录下差异。然后从基线出发每次只改一个变量。比如想验证“可学习温度”是否有用先保持数据、模型、优化器全部不动只把固定温度改成可学习温度观察结果变化。想验证早融合是否有用也只先做架构改动不碰数据配比和损失权重。这样每次实验结果都能形成一条清晰的因果证据。5.2 建立自己的 Mini-Eval 集只盯着公开测试集很容易被不稳定的评估噪声误导。公开测试集覆盖场景广但未必代表你真实业务里最关心的数据分布。我一般会建议团队准备一个 100 到 1000 条的 mini-eval 集专门衡量自己场景下的关键能力。这个评估集不需要很大但必须稳定、有区分度。它应该包含多模态的常规样本、单模态样本、常见的噪声场景以及一些长尾或难例。每次改动模型后都用同一评估集跑一组指标形成历史曲线。Mini-eval 集还有一个隐蔽的好处它可以帮助你判断模型是不是“假涨”。比如某个改进让公开测试集涨了 2 个点但在你的 mini-eval 上反而跌了这说明改进可能过度拟合了公开测试集而不是真的提升了多模态理解能力。5.3 什么阶段该自己预训练什么阶段直接用开源模型这里要写清楚边界。对大多数团队来说我其实不建议从零训练大型多模态模型。算力只是一部分更大的成本在于数据清洗、训练框架、评估体系、运维监控和排错能力。这些都不是一两个工程师短期内能补齐的。如果业务只需要通用图文理解、检索或内容审核直接使用开源的多模态基础模型再用 LoRA、Adapter 或其他参数高效微调手段适配到自己的领域通常更现实。这样你能把大部分精力放在数据质量和业务评估上而不是训练稳定性上。只有当下面几种情况出现时才值得考虑自己从零预训练你需要的模态组合比较特殊例如雷达图、遥感影像、医学图像和通用自然图像差异过大你的业务语言非常特殊领域术语密集公开预训练数据覆盖不足你本身就是研究预训练机制、想做算法改进需要在一个可控环境下验证自己的假设。这时候前面说的配方思想就非常关键。它让从零训练不再只是拼灵感和算力而是变成可追踪、可复盘、可在下一轮训练中迭代的工程流程。多模态预训练的未来大概率不是某个模型突然横空出世而是越来越多团队能把自己的训练过程写成一份长周期、可复现、可迭代的 recipe。技术会落后于新模型但一套好的实验方法会持续帮你在新模型出现时更快定位它的价值。回到开头那个问题loss 下降但效果不涨怎么办现在我的回答是先别急着调参。先看知识流动的方向确认两个模态都在起作用再看模态协同的平衡有没有模态塌缩再看统一时机的选择是不是和你的数据、算力条件匹配最后把每次训练都记录成一份完整配方。这四个问题几乎是任何一个多模态预训练项目从“能跑”走向“可控”的必经之路。物理很难但至少我们可以先把一部分“玄学”变成工程。