恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
一篇讲透 CLIP 文本编码器:文字如何变向量
首页
资讯中心
/
一篇讲透 CLIP 文本编码器:文字如何变向量
一篇讲透 CLIP 文本编码器:文字如何变向量
发布时间:2026/9/2 9:02:47
一篇讲透 CLIP 文本编码器文字如何变向量【免费下载链接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image项目地址: https://gitcode.com/GitHub_Trending/cl/CLIP相册里堆满没标签的照片你随手写下一只猫一只狗一只鸟模型就把几百张照片分进三个文件夹——全程不标注一张图、不训练一次。干这件事的是 CLIP 文本编码器它先把每句话压成 512 维向量再用余弦相似度挑出和图像向量最贴近的那句文字。纯文字和一串像素特征凭什么能算出相似度答案就藏在这台编码器里文本在比较之前已经被悄悄翻译成了和图像同一坐标系的向量。整条流水线其实是三个工种在接力。文字变向量的三个工种拆字工是 simple_tokenizer 与 tokenize()负责把句子变成 ID 序列读心组藏在 encode_text 的前半段把 ID 变成带位置信息的向量并堆进 Transformer对齐台是 encode_text 的最后两行完成一次换坐标系。拆字工BPE 子词切分与 77 长度限制怎么理解拆字工处理句子前会先统一清洗、转小写然后用 BPE字节对编码切分。BPE 的思路很像面点师处理面团常用词整块直接用没见过的长词则按训练时统计出的高频组合一点点拆开最后每块都保证在词表里。cat 整块过关unhappiness 会被拆成几个子词小块。切完的序列两头各打一个下界符|startoftext| 打头、 收尾告诉模型文本从这里开始、在那里结束。随后所有序列被塞进同一个 77 长度的容器不够长的用 0 补齐超长的看你的选择——截断或报错。核心逻辑压缩成几行就是def tokenize(texts, context_length77, truncateFalse): sot _tokenizer.encoder[|startoftext|] # 下界符打头 eot _tokenizer.encoder[/s] # /s 收尾 # BPE 切分后把首尾标记拼进每条序列 all_tokens [[sot] _tokenizer.encode(t) [eot] for t in texts] result torch.zeros(len(texts), context_length) # [N, 77] 零矩阵 for i, toks in enumerate(all_tokens): if len(toks) context_length and truncate: toks toks[:context_length] # 截断到 77 toks[-1] eot # 末尾仍放结束标记 elif len(toks) context_length: raise RuntimeError(too long) # 默认行为直接报错 result[i, :len(toks)] torch.tensor(toks) return result输出就是形状 [N, 77] 的整数 ID 矩阵短句右端留一片 0这就是读心组要接的料。读心组双嵌入相加与因果掩码的注意力读心组干活的第一件事是双嵌入相加。token 嵌入是一张查表每个 ID 对应一个 512 维向量代表它是什么。单有身份还不够模型还得知道它站在哪——位置嵌入就是每个座位预置的坐标牌形状 [77, 512]是随机初始化、可随训练不断修正的参数因为同一个词出现在句首和句尾对整句含义的贡献完全不同。两块相加得到同时装着身份坐标的张量形状 [N, 77, 512]。接着进 Transformer一层层堆叠的注意力块。每个词都向整句广播自己、再汇总各方回应多头自注意力等于派出多组专家一组盯语法关系、一组盯指代消歧各干各的活再合流。但这里有个硬规矩因果掩码把注意力矩阵的上三角填成 -inf每个词只能听自己和它前面的位置后面的词一律静音——像听力考试只放前半段录音不许回头偷看。# 因果掩码上三角填 -inf每个位置只能看前文clip/model.py mask torch.empty(context_length, context_length) mask.fill_(float(-inf)) mask.triu_(1) # 下三角才是可听区 # encode_text 前半段clip/model.py x self.token_embedding(text) # 查表ID - 向量 [N, 77, 512] x x self.positional_embedding # 加上位置坐标 x self.transformer(x) # 多头自注意力块逐层堆叠 x self.ln_final(x) # 收尾归一化注意力块内部还有前馈网络、层归一化和残差连接保证深层堆叠时训练依然稳定。走完最后一层张量形状仍是 [N, 77, 512]每个位置都带着全句的上下文信息。对齐台抽取 EOT 特征并投影到图像空间对齐台只干两件事。第一件是挑人77 个位置里只取 EOT 位置那个向量。因为因果掩码的存在EOT 排在队尾它听过前面整句话向量天然浓缩了全句信息。第二件是换坐标系乘上 text_projection把向量从文本塔内部宽度投到全局嵌入维度 512。# 取出每条序列里 EOT 位置ID 最大、排在最右的向量并投影 x x[torch.arange(x.shape[0]), text.argmax(dim-1)] self.text_projection这一步之后文本向量和图像向量住在同一间 512 维的房间里点积才有语义相关度的含义。开头那个问题到这里才算有答案。跟着一句话走完全程拿 a photo of a cat 走一遍前向传播看清每一站张量的变形数据流动的形状是 [N, 77] → [N, 77, 512] → [N, 512]。做零样本分类时把 a photo of a cat a photo of a dog a photo of a bird 批量过一遍得到一组文本向量再和图像向量比相似度——最高分那行就是预测类别。五分钟跑起来下面是文本向量最小示例从加载到相似度计算一共十几行import clip, torch model, preprocess clip.load(ViT-B/32) texts [a photo of a cat, a picture of a dog, an image of a bird] with torch.no_grad(): tokens clip.tokenize(texts) # [3, 77] 整数 ID feats model.encode_text(tokens) # [3, 512] 文本向量 sim feats feats.T # 文本间余弦相似度 [3, 3] print(sim)输出是一个 3×3 矩阵对角线接近 1其余三个词彼此含义相近、分数互有高低。把其中一行换成model.encode_image的结果就是图文检索的全部数学。选型与避坑 三档文本编码器配置一览ViT-L/14 需显存更宽裕CPU 建议从 ViT-B/32 起步模型Transformer 层数注意力头数隐藏维度ViT-B/321212768ViT-B/161212768ViT-L/1424161024️ 常见坑77 是硬上限。短文本右端补 0超长则二选一truncateTrue截断或直接抛 RuntimeError。截断有个暗细节tokens[-1] eot会把被切掉的尾部位置换成 EOT但这个 EOT 只听到半句话EOT 抽取出来的向量会打折扣。宁可手动把 prompt 写短也别依赖截断。文本与图像向量必须同空间、同尺度才能比比较前先各自做 L2 归一化。走model.forward时它已替你完成归一化并乘上 logit_scale单独调 encode_text / encode_image 就得自己归一化否则点积数值没有可比性。跨 checkpoint 混用向量没有意义不同权重学的是不同坐标系相似度分数纯属噪声。收尾CLIP 文本编码器的主线一句话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),仅供参考