- Preliminaries
3.1. CLIP and Prompt Learning(CLIP和提示学习)
CLIP(Contrastive Language Image Pre-training 对比语言图像预训练)
输入:未知图像 + 多组文本提示(如 “a photo of [class]”)
操作:
- 图像编码:视觉编码器
f(·)
提取图像特征f(i)
- 文本编码:文本编码器
g(·)
提取每个文本提示s_k
的特征g(s_k)
- 相似度计算:计算图像特征与所有文本特征的余弦相似度
- 概率分布:通过softmax生成图像属于各文本提示的概率分布
输出:图像属于每个文本提示的概率分布,实现零样本分类。
举个栗子🌰:
• 输入文字提示:“狗”、“猫”、“汽车”
• 计算相似度得分:8(狗)、5(猫)、1(汽车)
• Softmax处理后:
• 狗:95%
• 猫:4.7%
• 汽车:0.3%
👉 结论:这张图大概率是狗!
代码:
🔹输入:
图像 image
和多组文本提示 text
(如 "a photo of [class]"
)
输入代码为:
def forward(self, image, text, embed_cls=True, image_latent=None, image_embs=None):
image
: 输入的一张或多张图片,张量格式;text
: 多个描述该图像的文本提示,如"a photo of a cat"
;embed_cls
: 是否对文本嵌入加入CLS标记(默认是True);image_latent
: 可选的预计算图像特征(如果为None则重新计算);image_embs
: 可选的图像token级特征(用于多模态交互)。
🔹操作步骤和完整代码:
✅ 第 1 步:对输入文本进行编码,提取文本语义向量和 token 表示
# 使用文本编码器对输入的文本进行处理,得到两个输出:
# text_latent 是每条文本的整体特征向量(表示整句话的意思)
# token_embs 是每个词(token)对应的向量(为后续交叉注意力准备)
text_latent, token_embs = self._encode_text(text, embed_cls=embed_cls)
✅ 第 2 步:对输入图像进行编码,提取图像特征和 token 表示
# 如果没有预先提供图像特征,就用图像编码器重新计算
if image_latent is None or image_embs is None:
# image_latent 是整张图像的嵌入向量
# image_embs 是图像被分割成若干块(patch)后每块的特征,用于后续交叉注意力
image_latent, image_embs = self._encode_image(image)
✅ 第 3 步:生成训练用的标签(labels),对齐 token 数量
# 生成 ground-truth 标签,用于训练监督(匹配 decoder 的输出维度)
# 只取 text 的最后几个 token,长度等于 token_embs 的长度
labels = text[:, -token_embs.shape[1]:]
✅ 第 4 步:将图像 token 和文本 token 输入到多模态 transformer decoder,生成 logits
# 使用多模态解码器,将图像 token(image_embs)作为上下文
# 输入文本 token(token_embs)进行 cross-attention 编码
# 得到输出 logits(相似度分数,表示图像与每个文本之间的相关性)
logits = self.text_decoder(image_embs, token_embs)
🔹输出:
输出代码为:
return {
"image_features": image_latent, # 图像的整体特征向量
"text_features": text_latent, # 文本的整体特征向量
"logits": logits, # 图像和文本之间的相似度分数(未经过 softmax)
"labels": labels, # 监督训练的标签(即 ground-truth token)
"logit_scale": self.logit_scale.exp() # 可训练的缩放参数,用于调整相似度分布
}
🔹完整的 forward 函数代码(带注释):
def forward(self, image, text, embed_cls=True, image_latent=None, image_embs=None):
"""
图像和文本的多模态前向传播函数,实现零样本分类中的图文匹配。
参数:
image: 输入图像(tensor格式)
text: 多个文本描述提示
embed_cls: 是否在文本中加入CLS标记(默认True)
image_latent: 可选,图像的全局向量特征
image_embs: 可选,图像的局部token级特征
返回:
一个包含图像和文本特征,相似度logits,标签和缩放因子的字典
"""
# 1. 文本编码
# 将每条文本编码为一个整体特征向量(text_latent)和一个token级别的特征序列(token_embs)
text_latent, token_embs = self._encode_text(text, embed_cls=embed_cls)
# 2. 图像编码
# 如果没有提供图像特征,就计算图像的整体特征(image_latent)和token特征(image_embs)
if image_latent is None or image_embs is None:
image_latent, image_embs = self._encode_image(image)
# 3. 生成标签
# 标签用于训练对齐文本输出和真实token,保持token_embs维度一致
labels = text[:, -token_embs.shape[1]:]
# 4. 多模态交叉注意力解码器
# 将图像token作为上下文输入,文本token作为目标输入,计算 cross-attention 输出 logits
logits = self.text_decoder(image_embs, token_embs)
# 5. 输出一个包含所有重要信息的字典
return {
"image_features": image_latent, # 图像的全局特征(用于图文匹配)
"text_features": text_latent, # 文本的全局特征
"logits": logits, # 图文匹配的 logits(尚未 softmax)
"labels": labels, # ground truth 标签
"logit_scale": self.logit_scale.exp() # 可训练的缩放因子,用于调整 logits 大小
}
Prompt Learning(提示学习)步骤
目标:自动学习更有效的文本提示,提升CLIP在下游任务的表现。
输入:少量正常样本(小样本设置)
操作:
- 设计可训练提示模板:
• 模板形式:[P1][P2]...[PE_P][class_k]
•[P1]...[PE_P]
为可训练的token,[class_k]
为固定的类别名称 - 对比学习优化:
• 通过对比损失(如交叉熵)调整提示参数,使正常样本特征与正常提示特征对齐 - 生成最终提示:
• 学习后的提示模板直接用于推理
输出:优化后的文本提示,提升分类或检测性能(如异常检测)。
例子背景
任务:训练模型区分图片是“猫”还是“狗”
传统方法:需要大量标注数据训练模型
Prompt Learning方法:只改提示模板,不修改CLIP模型本身,用少量数据优化提示。
Prompt Learning步骤
输入:
• 少量标注图片(如5张猫、5张狗)
• 初始模板:“a photo of [class]”([class]替换为“猫”或“狗”)
操作:
-
定义可训练模板:
• 原始模板:[P1][P2] a photo of [class]
◦[P1][P2]
:可训练的token(模型自动学习的“魔法词语”)
◦[class]
:固定类别名称(直接替换为“猫”或“狗”)
• 例如训练后的模板可能是:"清晰特写 毛茸茸的 a photo of 猫"
-
训练过程:
• 输入一张狗图片,计算它与优化后提示的相似度:
◦ 狗的提示:[P1][P2] a photo of 狗
◦ 猫的提示:[P1][P2] a photo of 猫
• 目标:让狗图片与狗的提示相似度 远高于 猫的提示
• 通过对比损失(如交叉熵)更新[P1][P2]
的向量值 -
生成最终提示:
• 训练完成后,固定[P1][P2]
的参数
• 推理时直接使用模板:
◦ 输入狗图片 ➔ 计算与[P1][P2] a photo of 狗
的匹配概率
输出:
• 优化后的提示模板,例如:
• 狗:“特写镜头 草地上的 a photo of 狗”
• 猫:“室内环境 窗边的 a photo of 猫”
• 效果:使用优化后的提示,分类准确率从70%提升到90%!
关键点
-
可训练token([P1][P2]):
• 相当于“自动学习的神奇修饰词”,比如“特写镜头”、“毛茸茸的”
• 模型通过少量数据调整这些词的含义,让提示更匹配任务需求 -
固定类别([class]):
• 直接使用“猫”、“狗”等真实类别名,不修改
• 保证语义明确,避免模型混淆
类比理解
• 传统方法:让模型从头学习“猫狗是啥”(费时费力)
• Prompt Learning:
• 相当于给模型一个填空题模板:
“[学来的修饰词] 一张照片的 [猫/狗]”
• 模型只需要填对修饰词,就能更准确定义类别!
关键点
- CLIP优势:无需训练数据,直接通过文本提示实现零样本分类。
- Prompt Learning作用:
• 自动优化提示模板,减少人工设计成本
• 在少样本场景下提升模型对特定任务(如异常检测)的适应能力 - 对比学习核心:通过正负样本对比(如正常 vs 异常提示),增强语义区分性。
示例应用:
在异常检测中,通过学习正常提示 [P1][P2][obj]
和生成异常提示 [P1][P2][obj][flaw]
,使模型区分正常与异常特征。