一文看懂 CLIP 文本编码器:如何把文字变成能和图像比大小的向量
2026/9/2 9:31:50 网站建设 项目流程

一文看懂 CLIP 文本编码器:如何把文字变成能和图像比大小的向量

【免费下载链接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image项目地址: https://gitcode.com/GitHub_Trending/cl/CLIP

不用手写一条标注数据,CLIP 文本编码器就能把一句英文描述变成定长向量,让你直接拿它和图像向量比相似度——这正是跨模态检索的底层能力。

它到底解决了什么问题

图片天生是像素矩阵,文字天生是字符序列,两者没法直接相减、更没法比"像不像"。CLIP 文本编码器的职责,就是把任意一段文字变成一个向量,使它能和图像编码器产出的向量住进同一套坐标系,从而可以用余弦相似度来衡量匹配程度。

🧭 可以把它想成一台"坐标转换器":给一张照片、一句话各分配一个地图坐标点,之后判断它们是否匹配,就变成量这两个点之间距离的小事。

这一节的价值一句话:文本编码器是"文字端"的坐标转换器,它决定了文字能否被放进和图像同等的空间里。

内部工作原理

下面按"数据进来 → 中间变换 → 最后输出"三个问题拆一遍,对应源码在 clip/clip.py 和 clip/model.py。

数据进来时变成了什么?

你传入"a photo of a cat",它先被拆成一串整数。拆分的依据是字节对编码(BPE, Byte Pair Encoding):常见子词整块保留,生僻词切成更小的片段,具体逻辑在 clip/simple_tokenizer.py。tokenize()再在序列头尾各塞一个特殊标记——<|startoftext|>(句首)和</s>(句尾,下文称 eot),最后填成一个固定 77 长度的整数张量,不够就用 0 补齐。到这里,文字已经变成"能喂给神经网络"的数字,但还只是孤立的编号。

中间经历了哪些变换?

拿到整数序列后,encode_text做三件事:

  1. 词嵌入nn.Embedding(vocab_size, transformer_width)把每个编号换成一个稠密向量(ViT-B 系列维度为 768)。
  2. 位置嵌入positional_embedding是可学习参数,按位置逐一加上,告诉模型"哪个词在第几个位置",因为嵌入本身不携带顺序信息。
  3. Transformer 编码:向量转成LND布局后进入Transformer,由多层ResidualAttentionBlock堆叠,每层含多头自注意力 + 前馈网络 + 层归一化 + 残差连接。

其中最有讲究的是注意力掩码build_attention_mask-inf填充上三角,让每个词只能"看到"它自己和它前面的词。这是因果(causal)结构,保证第 n 个词在汇总信息时不会偷看后面的内容,编码出的向量自然带有"从左到右读完"的语义。

最后输出了什么?

Transformer 跑完得到[batch, 77, 768]的向量组。模型并不取第一个词,而是定位到 eot 位置——由于 eot 的编号是序列里最大的,text.argmax(dim=-1)恰好能把它找出来——取该位置的向量再乘投影矩阵,映射到与图像特征相同的 512 维空间。

# 取 eot 位置特征并投影到 512 维 x = x[torch.arange(x.shape[0]), text.argmax(dim=-1)] @ self.text_projection

这一节的价值一句话:分词、嵌入+自注意力、eot 投影,三段变换把离散编号一路加工成可与图像对表的 512 维向量。

动手跑起来

最小可运行示例(需先pip install ftfy regex tqdm与 PyTorch):

import clip import torch model, _ = clip.load("ViT-B/32") # 加载模型(含文本编码器) texts = ["a photo of a cat", "a picture of a dog", "an image of a bird"] tokens = clip.tokenize(texts).to(model.device) # 分词成定长 77 的整数序列 with torch.no_grad(): feats = model.encode_text(tokens) # 文本编码器输出 print(feats.shape) # torch.Size([3, 512])

输出torch.Size([3, 512]):3 个句子,每个变成一个 512 维向量。接着算句间相似度:

import torch.nn.functional as F sim = F.cosine_similarity(feats, feats.T, dim=-1) # 3x3 余弦相似度矩阵 print(sim)

得到一个 3×3 矩阵,对角线恒为 1;语义接近的句子得分更高,比如 cat 与 dog 通常比 cat 与 bird 更接近。

这一节的价值一句话:两行调用就能拿到可直接比大小的文字向量,门槛低到适合当第一个实验。

模型规格对比与选型

不同规模模型的文本编码器参数如下(clip.load时按名称选取):

模型Transformer 层数注意力头数隐藏维度
ViT-B/321212768
ViT-B/161212768
ViT-L/1424161024

注意 ViT-B/32 与 ViT-B/16 的文本编码器完全相同,差别只在图像端分辨率。🎯 新手建议从 ViT-B/32 起步:速度最快、显存占用最低,足够验证"文字→向量→比相似度"整条链路;确认流程跑通后,再按需升级到 ViT-L/14 换取更高精度。

这一节的价值一句话:先用最小的 B/32 把链路跑通,再谈精度升级,避免一上来就堆大模型。

写在最后

  • 一条流水线:BPE 分词 → 嵌入+自注意力 → eot 投影,全程把文字加工成 512 维向量。
  • 一个关键结构:因果注意力掩码让编码带有从左到右的阅读语义。
  • 一次比大小:输出向量与图像向量做余弦相似度,即得到匹配得分。

典型场景一句话:以文搜图、零样本分类、跨模态检索都建立在这套"文字向量 ↔ 图像向量"之上。

延伸阅读:README.md 与官方教程 notebooks/Interacting_with_CLIP.ipynb。

【免费下载链接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image项目地址: https://gitcode.com/GitHub_Trending/cl/CLIP

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询