【CVPR2024-工业异常检测】PromptAD方法(CLIP和提示学习)

  1. Preliminaries

3.1. CLIP and Prompt Learning(CLIP和提示学习)

CLIP(Contrastive Language Image Pre-training 对比语言图像预训练)

输入:未知图像 + 多组文本提示(如 “a photo of [class]”)
操作

  1. 图像编码:视觉编码器 f(·) 提取图像特征 f(i)
  2. 文本编码:文本编码器 g(·) 提取每个文本提示 s_k 的特征 g(s_k)
  3. 相似度计算:计算图像特征与所有文本特征的余弦相似度
  4. 概率分布:通过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在下游任务的表现。

输入:少量正常样本(小样本设置)
操作

  1. 设计可训练提示模板
    • 模板形式:[P1][P2]...[PE_P][class_k]
    [P1]...[PE_P] 为可训练的token,[class_k] 为固定的类别名称
  2. 对比学习优化
    • 通过对比损失(如交叉熵)调整提示参数,使正常样本特征与正常提示特征对齐
  3. 生成最终提示
    • 学习后的提示模板直接用于推理

输出:优化后的文本提示,提升分类或检测性能(如异常检测)。


例子背景

任务:训练模型区分图片是“猫”还是“狗”
传统方法:需要大量标注数据训练模型
Prompt Learning方法:只改提示模板,不修改CLIP模型本身,用少量数据优化提示。


Prompt Learning步骤

输入

• 少量标注图片(如5张猫、5张狗)
• 初始模板:“a photo of [class]”([class]替换为“猫”或“狗”)

操作
  1. 定义可训练模板
    • 原始模板:[P1][P2] a photo of [class]
    [P1][P2]可训练的token(模型自动学习的“魔法词语”)
    [class]固定类别名称(直接替换为“猫”或“狗”)
    • 例如训练后的模板可能是:"清晰特写 毛茸茸的 a photo of 猫"

  2. 训练过程
    • 输入一张狗图片,计算它与优化后提示的相似度:
    ◦ 狗的提示:[P1][P2] a photo of 狗
    ◦ 猫的提示:[P1][P2] a photo of 猫
    目标:让狗图片与狗的提示相似度 远高于 猫的提示
    • 通过对比损失(如交叉熵)更新[P1][P2]的向量值

  3. 生成最终提示
    • 训练完成后,固定[P1][P2]的参数
    • 推理时直接使用模板:
    ◦ 输入狗图片 ➔ 计算与[P1][P2] a photo of 狗的匹配概率

输出

• 优化后的提示模板,例如:
• 狗:“特写镜头 草地上的 a photo of 狗”
• 猫:“室内环境 窗边的 a photo of 猫”
效果:使用优化后的提示,分类准确率从70%提升到90%!


关键点

  1. 可训练token([P1][P2])
    • 相当于“自动学习的神奇修饰词”,比如“特写镜头”、“毛茸茸的”
    • 模型通过少量数据调整这些词的含义,让提示更匹配任务需求

  2. 固定类别([class])
    • 直接使用“猫”、“狗”等真实类别名,不修改
    • 保证语义明确,避免模型混淆


类比理解

传统方法:让模型从头学习“猫狗是啥”(费时费力)
Prompt Learning
• 相当于给模型一个填空题模板:
[学来的修饰词] 一张照片的 [猫/狗]”
• 模型只需要填对修饰词,就能更准确定义类别!

关键点
  1. CLIP优势:无需训练数据,直接通过文本提示实现零样本分类。
  2. Prompt Learning作用
    • 自动优化提示模板,减少人工设计成本
    • 在少样本场景下提升模型对特定任务(如异常检测)的适应能力
  3. 对比学习核心:通过正负样本对比(如正常 vs 异常提示),增强语义区分性。

示例应用
在异常检测中,通过学习正常提示 [P1][P2][obj] 和生成异常提示 [P1][P2][obj][flaw],使模型区分正常与异常特征。

### CLIP 模型在异常检测中的应用 CLIP (Contrastive Language–Image Pre-training) 是一种多模态预训练模型,能够理解图像文本之间的关系。对于异常检测任务而言,CLIP 可以通过其强大的表征能力来识别正常样本与异常样本的区别。 利用 CLIP 进行异常检测的一个常见策略是基于特征空间的距离度量来进行分类。具体来说,在给定一组正常的训练样本之后,可以计算这些样本经过 CLIP 编码后的平均向量作为正类中心;当测试新样本时,则测量该样本编码后得到的向量与此正类中心间的距离,如果超过一定阈值则判定为异常[^1]。 此外,还可以采用对比学习的方式增强 CLIP 对于特定领域内的异常感知能力。例如,可以通过构建包含大量正常实例及其对应描述的任务导向型数据集,并让 CLIP 学习区分不同类型的输入模式。这样不仅有助于提高模型泛化性能,还能更好地适应实际应用场景下的需求变化[^2]。 ```python import torch from clip import load as load_clip device = "cuda" if torch.cuda.is_available() else "cpu" model, preprocess = load_clip("ViT-B/32", device=device) def compute_anomaly_score(image_tensor): with torch.no_grad(): image_features = model.encode_image(image_tensor.to(device)) normal_center = ... # 预先计算好的正常类别中心 anomaly_score = torch.norm((image_features - normal_center), dim=-1).item() return anomaly_score ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值