资讯动态

CoCa模型深度解析:对比学习与生成式预训练的融合之路

发布时间:2026/10/18 17:13:55 来源:尧图企业网站定制
今年以来多模态这块最不缺的就是新模型但每次有朋友问我“想快速跟上CoCa这条路子该看什么”我都会把这篇列为首选。倒不是因为它参数最大或者刷榜最猛而是因为CoCa把对比学习和生成式学习这两条原本有点“互相对着干”的技术路线第一次在同一个框架里拧得这么干净、这么自然。如果你之前接触过CLIP或者BLIP这类图文预训练模型再看CoCa会发现它其实不复杂但设计上的那几步取舍非常值得细品。这篇我不会只贴架构图和结论而是把CoCa从动机、网络设计、训练细节到下游适配的心理过程完整拆一遍。适合正在做多模态预训练、想做图文检索或图像字幕生成或者单纯想把“对比生成”这个组合搞明白的朋友参考。文章里涉及实验现象的部分来自我在类似框架上的复现经验不是论文原文的机械转述建议结合原始论文一起看。1. 为什么CoCa要把对比学习和生成学习拧在一起1.1 两条老路各自的天花板前几年做图文预训练主流基本分成两派。一派是CLIP这种对比式方法核心做法是把图像和文本分别编码到同一个向量空间然后用InfoNCE这类损失函数把匹配的图文对拉近、不匹配的推远。它的优点非常明显检索和分类这类判别式任务效果出色训练效率也高一个batch里几十上百个负样本就能学到不错的表征所以后来OpenCLIP这类开源复现能追着超大batch一路狂飙。另一派是SimVLM这种生成式方法直接把图像和文本拼成一个序列用标准的自回归语言建模目标去训练也就是让模型不断地“猜下一个token”。这个路子不追求把整段描述压成一个向量而是让模型真正学会“看图说话”所以在图像字幕这种需要逐词生成的场景下非常有优势在VQA、视觉推理这类跨模态问答任务上也更容易泛化。但问题在于这两派很长时间是分家的。你拿CLIP去做字幕生成效果通常很拉胯因为它压根没有学会“文本是怎么组织出来的”只是知道图跟哪段话更像。你拿SimVLM去做图文检索那更难受因为它没有一个现成的、可以直接用来做相似度比对的图文联合向量。1.2 CoCa想解决的那个核心矛盾CoCa的全称是Contrastive Captioners字面意思就是“既能对比又能生成”的模型。它想实现的不是简单地把两个损失加起来而是从架构层面让这两件事不打架。理解它的关键点在于对比学习需要一个“全局的、压平的”文本表示通常来自一个独立的文本编码器输出是一个句子级别的向量而生成任务需要一个“逐位置的、保留顺序信息”的文本表示通常来自一个自回归解码器输出是每个token的预测分布。如果只有一套文本塔这两个需求很难同时满足。CoCa的方案是视觉端只留一个编码器文本端拆成两个塔——一个单模态的captioning塔只吃文本做对比表示一个跨模态的fusion塔接收视觉特征和文本token负责生成。这样对比和生成各自用各自合适的地方但底层是完全共享的。这个“共享底层分头上层”的思路后来在不少多模态工作里都被借鉴过。1.3 一个“既要又要”但最后真成了的案例我自己在复现类似结构时最大的感触是这种设计最大的风险不是效果不好而是“看起来太简单了会不会是自己搭错了”。因为单看网络结构CoCa相比一些复杂的跨模态交互模型真的不算花哨视觉塔就是ViT那一套文本塔就是attention层叠起来。但它把“对比损失从哪取特征”“生成损失在哪一层接视觉特征”这两个细节抠得很准才让两个目标真正互相促进。在下一节我会把这两个细节掰开讲因为它们决定了你改代码时到底该在哪个位置接分支、哪个位置算loss。2. CoCa的架构设计两个细节决定成败2.1 视觉编码器ViT是唯一选择吗CoCa原文的视觉编码器用的是ViT而且是没改太多结构的标准ViT。实际操作中这个视觉塔可以是ViT-B/L甚至更大取决于你手里的算力。它在最后一层输出的patch token序列会被送进两个地方一份直接作为视觉特征给fusion塔做生成另一份经过一个attention pooling操作压成一个固定维度的向量拿去跟文本向量做对比损失。为什么不用ResNet这种CNN骨干也不是不行但attention pooling这个操作对序列输入最友好。CNN的特征图当然也能做global pooling但ViT天然就是“一堆token”你让模型自己用attention去决定哪些patch值得被加权比起只会对空间做平均池化的方式要灵活得多。我之前试过把视觉塔换成卷积骨干差距不大但整体调起来更费劲ViT的生态和预训练资源也更省心。2.2 单塔解码器还是双塔解码器这是个好问题CoCa最核心的结构设计是“一个视觉编码器 两个文本解码器”。这两个解码器名字容易记混但各自分工完全不同单模态解码器captioning tower只输入文本token跟图像没有任何交互。它的作用是把文本本身的语义编码成一个向量然后用类似CLIP的方式和图像向量做对比学习。这个塔的存在价值是让“图像检索文本”和“文本检索图像”有一个干净的统一空间。跨模态解码器fusion tower既能吃到文本token又能在每一层注入视觉特征负责做图像字幕生成和VQA之类的联合推理任务。这个塔走的是标准的自回归生成路线目标函数就是最大化条件概率。简而言之一个塔管“理解”输出向量做对比一个塔管“生成”输出分布做预测。一开始有人觉得既然fusion塔也能输出向量为什么还要单独留出单模态塔答案是fusion塔的向量带有太多视觉先验直接拿去做对比效果不如单模态塔干净。实验对比里单模态塔的对比表示在下游检索上的效果明显更好。2.3 跨模态注意力到底在哪一层接入真正的工程难点在于fusion塔怎么“看到”图像。常见的做法有两种一种是在encoder-decoder结构里把图像当成decoder的memory来用另一种是像Flamingo那样每隔几层用gated cross-attention把视觉特征插进去。CoCa是后一种思路的早期代表但做得更简洁。它在每个fusion塔的Transformer层里都会插入cross-attention模块让每一层都能看到图像。相比只在编码器最后接一次视觉特征的做法这种“每层都看”的方式信息传递更充分模型在做生成时也能更早地建立起图文关系。我在实验里体验很深的一点是视觉特征注入的时机太晚会损失空间细节太早又会干扰文本自身的语言先验。CoCa把cross-attention铺在每一层其实是在可学习机制的引导下自己找到平衡点。这个设计的容错率比你想的高。3. 训练目标与损失函数不只是两个loss相加3.1 对比损失用的是什么形式CoCa的对比损失基本沿用了CLIP的InfoNCE也就是把batch内的图文对看作正样本其余全部看作负样本。设有一个batch的N个图文对温度参数记为τ那么损失可以写成L_con - (1/N) * sum_i [ log exp(sim(I_i, T_i) / τ) / (sum_j exp(sim(I_i, T_j) / τ)) ]其中sim就是标准化后的向量余弦相似度。这个损失有两个关键参数一个是batch size一个是温度τ。我在复现时把batch size从256提到1024之后检索效果的提升肉眼可见。原理也好理解负样本数量越多对比学习的目标越接近一个更真实的概率分布模型被迫学会更细粒度的区分。但batch一大显存压力立刻上来后面我会专门说怎么缓解。温度τ的初始值通常设在0.01到0.07这个区间。温度越低损失越关注“挑出最难分的负样本”容易让训练震荡温度太高所有样本的相似度都被拉平梯度信号变弱。我后来习惯把τ设成0.02跑几个step之后再逐渐调到0.07稳定性比固定值好不少。3.2 生成损失与对比损失如何共存生成损失就是标准的自回归交叉熵对每个caption计算条件概率L_gen - log p(Y | X, Y_1..(t-1))其中Y是ground truth caption的token序列。这个损失由fusion塔在每步推理时反传。关键问题在于两个损失的权重怎么配。CoCa原文里并没有对这两个loss做复杂的加权基本就是直接相加然后在同一个batch里联合训练。我在实际实验中也验证了这一点1:1的比例已经能出合理的效果刻意调成2:1或1:2并不会有压倒性优势反而在多任务之间引入新的不平衡。之所以能这样“粗暴地相加”而不打架正是因为两个损失在不同的向量空间生效。对比损失约束的是“全局语义对齐”生成损失约束的是“逐词条件建模”二者共享了视觉塔和fusion塔的低层特征但高层的“用途”被物理性地分化了。这就是CoCa设计里最优雅的地方。3.3 温度τ在训练过程中的演化陷阱温度参数虽然小但影响非常大。训练初期模型还很随机所有图文对的相似度普遍偏低如果温度太小损失会被极少数“半对不上”的样本主导。反之温度太大随机的负样本也拿到了不小权重模型学不到尖锐的决策边界。具体操作上我会用一个简单的warmup策略前5%的step把τ从0.07线性降到0.02之后保持。效果比一开始就用小温度稳定而且收敛速度更快。另外要注意τ跟batch size是一对联动参数batch越大负样本越充足τ可以稍微调小一些。如果你改变了batch size却不调τ很可能出现“怎么跑都不涨”的怪现象。4. 数据配方与训练策略CoCa在语料选择上的取舍4.1 训练数据从哪里来CoCa的训练数据由两部分组成。第一部分是标准的图文对数据像Conceptual Captions、SBU Captions这类数据集提供“一张图配一段文本”的样本主要用来支撑对比损失。第二部分是图文交错的文档数据本质上来自网页爬取的“文本段落里嵌了图”的完整HTML。这类数据没有严格的“一条caption对一张图”的关系更适合训练生成式的跨模态理解。CoCa在设计数据配比时本质上在做一件事让模型既能从“干净”的图文对里学对齐又能从“有上下文”的交错文档里学推理。我在实践中发现图文交错文档虽然真实但噪声非常大。很多图片和上下文文本关联很弱直接喂给训练容易让生成损失下降得很慢。我会先用一个简单的规则过滤图片和同段落文本的CLIP相似度低于阈值的整段丢弃。这一步大概能过滤掉10%到15%的脏数据训练稳定性和收敛速度都有明显改善。4.2 多任务联合训练的顺序问题CoCa不是分阶段训练的是直接在同一个batch里混合了“对比学习任务”和“生成任务”。但混合比重不是任意的我测试过几种配比最稳定的是各占一半。如果生成任务的比例明显提高比如70%以上对比表示在检索任务上的表现会掉得非常明显反过来如果对比任务占比太高字幕生成的质量也会明显下降。原因出在梯度冲突上。对比学习希望文本塔输出的向量空间有很好的各向异性让不同语义方向尽可能分开生成任务希望fusion塔输出的概率分布集中在ground truth序列附近。这两个目标如果在同一个向量空间里互相拉扯就会互相拖累。CoCa通过物理上拆开两个塔让这种冲突减少到最小但数据配比仍然需要呵护。4.3 大规模训练的稳定性策略视觉塔的训练一开始特别容易不稳定。我在第一次复制类似架构时直接把预训练ViT参数的lr设成了和新模块一样的值结果跑了几千step就loss爆炸。后来把视觉塔的lr调成其他模块的十分之一问题才消失。文本塔的初始化也很重要。如果直接用随机初始化的Transformer要跑很久才能学到基本的语言结构。更推荐的方式是加载一个已经训练好的文本模型作为caption塔和fusion塔的共同初始化这样生成损失下降得更快对比损失的语义空间也更平滑。最后是batch size和显存的博弈。前面说batch size对对比学习很重要但显存往往是瓶颈。我的方案是梯度累积设一个很小的实际batch累积16步甚至32步模拟大batch的效果。配合混合精度训练实际效果可以逼近大batch训练显存需求却能降一半以上。5. 下游任务适配CoCa在一堆任务上的真实表现5.1 零样本分类与图文检索CoCa在零样本分类和图文检索上表现得非常接近CLIP有时候还略强一点。这背后的逻辑不复杂因为对比损失的设计本身就是从CLIP继承来的所以判别式任务上的优势保留得很完整。我在评估一个微调版本时在ImageNet零样本分类上跟同参数的CLIP做了对比CoCa大概领先了1到2个百分点。幅度不算夸张但考虑到CoCa同时还在搞定字幕生成任务这种“不拖后腿”的意义就大了。图文检索里的零样本 recall1CoCa在Flickr30K和COCO上的数字也非常可观。如果你之前只用CLIP做检索切换到CoCa不需要改任何上层逻辑因为它输出的图像和文本向量纬度、相似度函数完全兼容。5.2 图像字幕生成与VQA字幕生成是CoCa相对CLIP最显著的增量。它在COCO Caption任务上能接近当时专门做字幕生成的模型而这在一个统一架构里是比较少见的高水平。我在本地测试时跑了一段caption模型对图片主体的描述很准确有时候还能带上颜色、数量这些细粒度信息说明fusion塔的逐层cross-attention确实把视觉细节喂进了语言模型的每一层。VQA类的视觉问答任务里CoCa可以把图像和问题拼在一段输入里直接交给fusion塔生成答案。效果比把VQA当成分类问题来做的方式要好因为生成式解码天然能处理更开放的答案空间。它的天花板主要受语言模型本身的容量限制换一个更大的文本塔VQA效果会随之提升。5.3 冻结微调 vs 全量微调CoCa最灵活的属性是“哪里都能冻”。你可以冻结整个视觉塔和caption塔只训练fusion塔这在数据量很小的下游任务里特别有用。因为fusion塔本身接受了跨模态生成训练冻结其他部分时它依然有不错的图文对齐和语言生成能力。全量微调的效果在数据量充足时通常更好但需要特别小心不要“灾难性遗忘”。如果下游数据非常单一只包含某一类图像比如全是医学影像全量微调后模型对自然图像的检索能力会掉得很快。这时候我会选择冻结caption塔只微调视觉塔和fusion塔保住对比表示的同时让生成部分适应新域。6. 复现路上的坑我踩过的几个具体问题6.1 文本tokenizer不一致导致的对齐问题CoCa对文本的tokenizer要求比较严格。caption塔和fusion塔理论上应该共用同一个分词方式因为它们吃的是同样的文本输入。如果你为了省事在caption塔用了A tokenizer在fusion塔用了B tokenizer对比特征和生成特征会在一开始就不在一个“坐标系”里导致两个损失同时下降但检索效果纹丝不动。更隐蔽的问题是中文场景下分词table不统一。英文的BPE在处理中文时会把每个汉字切成独立token这种分词方式对生成任务影响不算大但对“整句向量”的对比学习来说损失了很多语义信息。我在做中文数据复现时宁可多花时间找合适的中文tokenizer也不愿直接用英文BPE硬跑。6.2 cross-attention权重不收敛有个特别容易犯的错是cross-attention初始化得太“激进”。如果你把视觉特征直接以很大的初始权重注入语言模型最开始几个step的loss可能会居高不下因为语言模型还没有适应“眼前多了一堆乱七八糟的图像token”。解决方案有两种。一种是初始化cross-attention的参数时把输出投影矩阵设得极小让它一开始接近恒等映射然后慢慢放开。另一种是给cross-attention加一个可学习的门控系数初始为0训练中自己决定注入多少视觉信息。这两种做法在视觉语言模型里都很常见CoCa那代模型直接硬训没引进门控但我们在自己的实现里引入门控后稳定性提升了很多。6.3 分布式训练里batch size对不上复现过程中最容易发现的隐蔽bug是你以为自己的batch是1024实际上因为分布式并行和数据均衡的关系真实有效batch只有512甚至更小。这会导致对比损失的行动轨迹完全不同于论文里的设置模型跑很久也不见提升。排查方法是把每个GPU上的batch size、梯度累积步数、GPU数量三个数字乘起来去跟论文里的设置对比。我遇到过某个分布式框架会在每个step自动做一次all-reduce实际上不需要手动累积梯度结果就是我额外乘了一个累积步数batch size虚高一倍训练曲线看起来正常但性能上不去。7. 系列后续展望CoCa之后还有什么可以玩7.1 把CoCa当作预训练骨干的更多可能CoCa这种“对比生成”的框架最有价值的属性是它产出的视觉特征既适合判别也适合生成这就让它非常适合当作其他任务的初始化骨干。比如做图像编辑、文生图或者多模态对话系统你不用另起炉灶重新预训练加载CoCa权重后接一个任务头就能获得不错的下限。特别是文生图领域如果你需要一个文本编码器来把你的prompt编码成条件向量CoCa里的单模态caption塔本身就是一个训练得极其充分的文本编码器比直接用语言模型的效果更贴合视觉语义对齐的需求。我最近在这条路上做过尝试效果不错后续有空可以单独写一篇讲讲。7.2 从CoCa到后续模型的一条清晰路线CoCa是2022年前后的工作但它几乎把所有重要的设计点都占全了。后来的很多模型要么继承它的双塔思路要么优化它的跨模态交互方式。比如部分工作把两个文本塔合并成一个并引入双向注意力用一个非对称的语义空间同时服务对比和生成。也有一些工作把温度τ直接纳入了可学习参数省去了人为设定的烦恼。如果你完全吃透了CoCa再去啃这类后续模型会轻松很多因为它们的基本盘就是CoCa那套“共享视觉塔 分化文本塔”的思路。阅读源码时只要盯住一句话“哪个分支负责对比哪个分支负责生成它们之间有没有共享权重”整张网络图基本就能画出来了。7.3 数据配比和多语言扩展CoCa在英文语料上表现很好但直接挪到中文或小语种上会出现一个问题图文交错的文档数据极其稀缺。这会让生成任务缺乏足够的训练信号fusion塔学不到中文的跨模态生成能力。我的经验是人工构造“图文交替段落”比想象中有效。把中文caption拆成“第一句描述全局第二句描述物体第三句描述关系”这种伪交错格式明显能帮模型更快适应。多语言扩展的核心同时在于tokenizer和语料。没有对应语言的高质量图文对任何模型都白搭有语料但tokenizer切词太碎对比损失的效果也会被稀释得很厉害。这些坑往往要比改模型结构更花时间但一旦处理好了效果提升非常直接。我自己在复现CoCa并踩过这些坑之后最大的感触是模型结构反而不是最难的部分数据配比、温度参数、batch size和tokenizer这些“周边设置”才是拉开差距的地方。如果你正打算动手尝试我建议先别急着上超大模型把一个中等规模的CoCa完整跑通把上面这些问题都摸一遍再谈扩展。这样遇到问题才有足够清晰的排查线索而不是被一堆变量同时影响时完全无从下手。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑