有一件事困扰了我很久:给 AI 一张狗的照片,它说这是狗,这我理解。但如果你给它一张完全没见过的卡通狗,然后在旁边写一句“一张卡通风格的狗”,它居然也能认出来。你甚至不用给它看任何卡通狗的标注样本。这怎么可能?

答案在 CLIP 里。CLIP 不是那种“让模型看懂图片”的技术,它做的是让模型看懂“图片和文字之间的关系”。它把一张图片和一段文字,塞进同一个向量空间,然后让它们互相“找得到”对方。这个想法很直接,但实现起来有一堆反直觉的细节。我最早以为它是把图片和文字一一对应地训练,后来才发现完全不是那么回事——它用的是对比学习,一种让模型同时学好“应该靠近谁”和“应该远离谁”的机制。
不是“图片配文字”,而是“在海量配对里找线索”
CLIP 的训练数据是 4 亿对(图片,文字)组合,直接从互联网上爬来的。这些文字不是人工标注的类别标签,而是图片旁边的 alt-text、标题、描述——随便什么自然语言文本。OpenAI 的论文《Learning Transferable Visual Models From Natural Language Supervision》里提到,这种规模的弱监督数据让模型学到的视觉概念远比固定类别丰富。你可以在推理时输入“一只戴着墨镜和草帽的柴犬”,模型也能理解,因为它见过无数类似的自然语言描述,而不是只见过“狗”这个标签。
但真正让训练生效的,不是数据,而是架构。CLIP 有两个编码器:一个图像编码器(通常是 ViT 或 ResNet),一个文本编码器(一个 Transformer)。它们各自把输入变成一个固定长度的向量,然后通过一个简单的对比损失函数,让配对的图像和文本向量拉近,不配对的则推开。这个损失函数叫做 InfoNCE,它在一个 batch 里同时对 N 个图像和 N 个文本做计算,生成一个 N×N 的相似度矩阵,对角线上的元素是正样本,其他都是负样本。模型要最大化对角线上的相似度,同时最小化其他所有位置的相似度。
我当初最大的误解是:以为 CLIP 是让文本和图像生成完全一样的向量。实际上,它们只是被拉到了同一个向量空间,但绝对值可以不相等。这个空间里,两个向量的余弦相似度越高,表示它们在语义上越匹配。推理的时候,你输入一句话,它经过文本编码器变成一个向量,然后拿这个向量和一堆图像向量做点积,相似度最高的那张图就是答案。整个过程不需要任何微调,这就是 zero-shot 能力。
猜词游戏是怎么骗过你的?
你可能会想,如果模型只是把文本和图像向量拉近,那它怎么理解“没有”这种否定词?比如说“一张没有猫的图片”和“一张有猫的图片”,它会不会搞混?实际上,CLIP 对否定和复杂逻辑的理解确实很弱,因为它的训练目标只是配对相似度,不是逻辑推理。它看到的“没有猫”的图片,很可能只是图片里没有猫,但其他物体很多,那么“没有猫”这个描述在向量空间里就变成了“没有猫”这个文本的嵌入,和那些没有猫的图片靠近。但如果你要求它区分“一只猫盯着一条鱼”和“一条鱼盯着一只猫”,它可能会翻车,因为它没有真正的空间关系理解,只是根据整体视觉特征和文本的统计相关性来匹配。
这种机制有一个很狡猾的后果:它特别擅长“作弊”。比如你给它一张全是蓝色像素的图,文本写“一片蓝色的天空”,它会给出很高的相似度,因为蓝色像素和“蓝色天空”在训练数据里经常一起出现。但它其实没有“看到”天空,只是在匹配低层特征。这让我意识到,CLIP 的“理解”其实是一种全局的统计匹配,而不是真正的视觉推理。
一张表说清 CLIP 和传统模型的核心区别
| 传统图像分类模型 | CLIP |
|---|---|
| 需要固定类别标签,训练后只能识别这 N 类 | 接受任意自然语言文本作为查询,类别动态变化 |
| 需要大量标注数据 | 利用互联网上已有的图文配对,零样本泛化 |
| 训练和推理都是单向的:图片→标签 | 双向:图片和文本可以互相检索 |
| 对稀有类别或新概念无能为力 | 可以通过文本描述理解未见过的新类别 |
| 对偏见和短文本的鲁棒性差 | 对提示词(prompt)的写法非常敏感 |
最后一行是我踩过的一个大坑。我最早用 CLIP 做图片分类时,直接拿类别名称当文本输入,比如“cat”、“dog”,结果准确率不如预期。后来我发现,CLIP 当初在训练时看到的文本都是完整的句子,比如“a photo of a cat”,而不是孤立的单词。所以推理时加上“a photo of a”这样的前缀,准确率能提升好几个点。OpenAI 的官方博客也提到,他们使用了 prompt engineering 来提升 zero-shot 表现,比如给每个类别生成多个描述模板,然后取平均。
为什么它不能直接当 OCR 用?
CLIP 对文字的理解是基于视觉外观的,而不是基于字符序列。它可能认识“STOP”这个标志,因为训练数据里有很多停止标志牌,但它不会逐个字母地读单词。你让它识别图片中的手写数字,它可能会把“123”的文字和一堆手写体图片匹配上,但如果你把数字换成“壹贰叁”,它可能就懵了,除非训练数据里有对应的中文大写数字图片。这暴露出它的一个根本局限:对视觉符号和文字符号之间的映射,它依赖的是统计共现,而不是符号解码。
另一个局限是细粒度识别。CLIP 在区分“哈士奇”和“阿拉斯加雪橇犬”时,可能不如专门的细粒度分类器,因为它的语言描述往往比较粗犷。虽然你可以写“一只具有蓝色眼睛和明显面部斑纹的哈士奇”,但模型对这样的组合描述可能不够精细,因为训练数据里很少有这种精确到瞳孔颜色的描述。
我踩过的坑:温度参数和相似度缩放
CLIP 的损失函数里有一个可学习的温度参数 τ,它控制着相似度对数的缩放。一开始我没在意这个参数,自己实现对比损失时用了固定的温度,结果模型收敛很慢。后来读了论文附录才明白,这个温度是随着训练动态调整的,它直接影响负样本的“惩罚力度”。温度越低,模型对负样本的区分越严格,但也更容易过拟合;温度越高,区分越宽松。这个细节让我理解了为什么 CLIP 能在 4 亿对数据上稳定训练——它自适应的温度起了关键作用。
还有一个容易忽略的点:文本编码器的输入上限是 77 个 token。这意味着你不能把一大段文章塞进去,只能使用短语或短句。如果你需要处理长文本,就得先做摘要或截断,但这会丢失上下文。在实际项目中,我因为没注意截断到 77 token,导致一些长描述被悄悄截断,模型输出变得莫名其妙。
CLIP 的向量空间到底长什么样?
如果你把 CLIP 的文本和图像向量投影到二维平面,你会发现同一类概念(比如“狗”、“猫”、“汽车”)会形成不同的簇,但簇之间没有严格的边界。更有趣的是,这些簇的排列方式在一定程度上反映了语义关系。比如“狗”的簇离“猫”的簇比离“汽车”的簇更近。这种几何结构是隐式学习出来的,并没有显式指导。这让我想起 word2vec 的皇后-国王 = 女-男的类比,CLIP 的联合空间里也有类似的属性,比如“一只猫的图片”的向量减去“猫的文本”的向量,大致等于“狗的图片”的向量减去“狗的文本”的向量。这种结构让模型可以做跨模态的零样本推理,但它也带来了一个风险:模型可能会利用这种几何关系进行错误的类比,比如把“医生”和“护士”的关系映射到性别偏见上,这是 CLIP 论文里也承认的伦理问题。
那它到底能做什么?
CLIP 最强大的地方不是分类,而是检索和开放域理解。你可以用它来构建一个以文搜图系统,或者用自然语言指令来过滤数据集。在 DALL·E 2 和 Stable Diffusion 里,CLIP 被用来评估生成的图像和文本提示的匹配度,作为条件信号。但它的局限性同样明显:它对组合概念、逻辑关系、空间关系的理解很弱,对罕见视觉概念容易出错,而且对提示词的写法极其敏感——你换个形容词,结果可能完全不同。
如果你现在想用 CLIP,我建议加上 prompt engineering 和 ensemble,而不是直接裸用类别标签。同时,如果你需要处理长文本、细粒度属性或精确的空间关系,CLIP 可能不是最好的选择,可以看看后来的 BLIP-2 或 LLaVA 等模型,它们把 CLIP 的视觉编码器和语言模型结合,能更好地理解复杂指令。
说到底,CLIP 教会我们一件事:只要把文本和图像拉到同一个空间,并用足够多的数据去训练,模型就能学会一种非常灵活的“视觉常识”。但常识不是推理,它只是见多识广后的直觉,而直觉有时候会骗人。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/90.html