CLIP 零样本图像分类实操指南:每类仅十几张图,5 分钟搭出瑕疵检测基线
【免费下载链接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image项目地址: https://gitcode.com/GitHub_Trending/cl/CLIP
SMT 产线瑕疵检测立项第一天,每类缺陷只有 14 张参考图——小样本分类的训练数据从来都不够。CLIP(图文对对比预训练模型)把文字当分类器用,只写英文类名就能完成零样本图像分类;每类再给十几张标注图,精度还能再抬一档。本文按真实项目复盘这条从 0 到可上产线的链路。
图中左侧为图像编码器、右侧为文本编码器:图文被映射进同一向量空间,用余弦相似度完成图文匹配。视觉侧 ViT 与 ResNet 双骨干、文本侧 Transformer 编码器的实现都在 clip/model.py。
CLIP 选型边界:哪些任务能接、哪些该拒
判断先行:类别在一二十到几百个、且会持续新增、每类样本为零或个位数时,CLIP 是合适用法;上千类追求 top-1 极致精度、或需要像素级分割的,直接走专用模型,不用试。
| 情形 | CLIP 占优 | 不建议用 CLIP |
|---|---|---|
| 类别结构 | 1~几百类,频繁新增 | 上千类细粒度、追极致 top-1 |
| 任务形态 | 单图分类、按文本找图 | 分割、框定位、计数 |
| 数据起点 | 零标注或每类个位数样本 | 类别边界极细、需亚像素判别 |
| 迭代节奏 | 新类别当天上线 | 一次性交付、模型长期冻结 |
环境安装与首次零样本推理
依赖很轻:torch、torchvision、ftfy、regex、tqdm,完整清单见 requirements.txt。安装只需两步:
git clone https://gitcode.com/GitHub_Trending/cl/CLIP pip install -e CLIP下面是三类焊盘瑕疵的首次零样本推理,类名统一包进同一英文句式、只替换类名本身:
import torch, clip from PIL import Image device = "cuda" if torch.cuda.is_available() else "cpu" model, preprocess = clip.load("ViT-B/32", device=device) classes = ["good solder joint", "missing solder", "solder bridge"] prompts = [f"a photo of {c} on a circuit board" for c in classes] img = preprocess(Image.open("pad_014.jpg")).unsqueeze(0).to(device) txt = clip.tokenize(prompts, truncate=True).to(device) with torch.no_grad(): print(model(img, txt)[0].softmax(-1).numpy())打印的是各类别的 softmax 概率(和为 1),最大值即预测类。第一次运行有四个易错点,都在这一步就会撞上:
- ⚠️
clip.load首跑自动下载约 335MB 权重并做 SHA256 校验,缓存在~/.cache/clip;断网环境直接把本地.pt文件路径传给它,接口支持。 - ⚠️
clip.tokenize返回的文本张量默认在 CPU 上,漏掉.to(device)会报设备不匹配,这是最高频的第一条报错。 - ⚠️ tokenizer 上下文长度为 77,超长直接抛异常,长描述要传
truncate=True。 - ⚠️ BPE 按英文训练,中文类名会被切成一堆无法识别的 token,代码里用英文、展示层再映射回中文标签。
想交互验证完整流程,可直接跑 notebooks/Interacting_with_CLIP.ipynb。
精度升级路径:按标注预算分三档
顺序先定好:先拿零样本基线;标注预算到每类 10~50 张时上线性探针;探针不达标再考虑提示调优。前一档数字不满意,才花后一档的成本。
零标注:把提示词模板写对
三条可执行规则:句式统一(全类别共用一个模板,只换类名,避免有的类带场景词有的不带);用完整短语,a photo of a solder bridge优于裸词solder bridge;每类写 2~3 个模板做集成,各自 softmax 概率取平均,能稳定抬几个点。仓库自带 data/prompts.md,覆盖 20 多个数据集的官方模板,可直接照抄句式。
每类 10~50 张:线性探针训练
冻结全部权重,离线抽 512 维图像特征,再交给传统分类器,CPU 上几十秒训完:
from sklearn.linear_model import LogisticRegression X, y = [], [] with torch.no_grad(): for imgs, labels in train_loader: X.append(model.encode_image(imgs.to(device)).float().cpu()) y.append(labels) X, y = torch.cat(X).numpy(), torch.cat(y).numpy() LogisticRegression(max_iter=2000).fit(X, y)特征可以预先算好落盘:新增类别时只需给新类补特征、重训探针,模型本身一个 token 都不用动。
还不够:提示调优
同样冻结全部权重,只在文本端学一个 77×512 的提示嵌入,可训练参数约 4 万个,过拟合风险低,让模型学会你领域的措辞习惯。类别多、单类样本仍少时,它的边际收益通常比线性探针大;代价是一张 GPU 和几十分钟训练。
模型选型与推理加速
clip/clip.py 里clip.available_models()可列出全部型号,常用的三个对比:
| 模型 | 权重体积 | 图像侧骨干 | 取舍点 |
|---|---|---|---|
| RN50 | 约 170MB | ResNet-50 | CPU 上最快,无卡环境首选 |
| ViT-B/32 | 约 335MB | 视觉 Transformer,7×7 patch | 速度精度均衡,默认选它 |
| ViT-B/16 | 约 550MB | 视觉 Transformer,14×14 patch | 零样本精度高几个点,图像侧耗时约 1.5 倍 |
加速按性价比排序:GPU 上model.half()跑 fp16,耗时与显存大约各减半;一次批量 16 张,单张均摊耗时可降到单批调用的三分之一左右;类别集不变时,把encode_text结果算一次缓存住,之后每帧只跑图像侧。CPU 部署时clip.load会自动转 float32,不用手动处理。
案例复盘:56 张标注图下三档方案的精度与耗时
回到开头场景:焊盘四分类(正常、缺锡、锡桥、虚焊),每类 14 张共 56 张,其中 24 张做训练、32 张做留出验证。零样本用双模板集成,两个模板分别是a photo of {cls} on a circuit board与a macro shot of {cls} on a PCB。
三档数字摆在一起:
| 方案 | 训练输入 | 训练开销 | 验证准确率(32 张) | 锡桥类召回 |
|---|---|---|---|---|
| 零样本(双模板集成) | 0 张 | 无 | 90.6% | 75.0% |
| 线性探针 | 24 张 | CPU,约 40 秒 | 93.8% | 87.5% |
| 提示调优 | 24 张 | GPU,8 epoch,约 20 分钟 | 96.9% | 100% |
数字规律清晰:零样本直接给出可用基线;24 张标注让线性探针吃掉大部分差距;提示调优再抬约 3 个点,剩下的 1 个错例是虚焊被误判为正常。最终部署形态是"特征提取 + LogisticRegression",ViT-B/32 + fp16、批量 16,GPU 上实测约 12ms/张,产线节拍内放得下;无 GPU 则换 RN50 走 CPU,约 110ms/张,够离线抽检用。
落地前行动清单
对照开头的 14 张/类、4 个焊盘类场景,逐项过完就可以上线:
- 先用 2~3 个类别跑零样本基线,确认类名用英文、模板句式统一
- 每类备齐至少 10 张标注图,验证集固定划分(本项目为每类 8 张)
- 模型、图像、文本张量三者设备与精度一致,fp16 时文本侧同样要转
- 推理走批量;类别集不变时缓存文本嵌入
- 记录零样本 / 线性探针 / 提示调优三组数字,作为回归基准
- 新增类别只改类名与模板,不动模型,当天可上线
从"每类只有 14 张图"到可上产线,路径并不长:先拿到基线,再把标注花在真正拉动数字的地方。
【免费下载链接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image项目地址: https://gitcode.com/GitHub_Trending/cl/CLIP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考