CLIP 零样本图像分类实战指南:0 张标注图,100 个类别里猜中蛇
【免费下载链接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image项目地址: https://gitcode.com/GitHub_Trending/cl/CLIP
不训练、不标注、不微调,OpenAI 的 CLIP(Contrastive Language-Image Pre-Training,对比语言-图像预训练)模型在 100 个类别的零样本测试里,对着一张 CIFAR-100 图片直接给出「snake 65.31%、turtle 12.29%」的可读结果,而且全程只用了一句提示词。这篇文章带你从零装到调优,把「用文字指挥图像分类」这条能力真正跑通。
本文适合谁:三类人直接对号入座
- 要给新类别打标签、又不想标注几千张图的产品工程师:CLIP 让你用英文短语描述类别就能上线第一版分类器
- 学生与独立开发者:几行代码复现论文里的零样本预测,不用理解反向传播细节
- 想了解多模态对齐怎么落地的人:一个双塔结构 + 一套提示词库,就是全部家当
5 分钟上手:装好依赖后 8 行代码出第一个概率
一条 conda 命令装 PyTorch,两条 pip 命令装依赖和 CLIP 本体,模型权重会在首次clip.load()时自动下载。
conda install --yes -c pytorch pytorch=1.7.1 torchvision cudatoolkit=11.0 pip install ftfy regex tqdm pip install git+https://gitcode.com/GitHub_Trending/cl/CLIPimport torch, clip from PIL import Image device = "cuda" if torch.cuda.is_available() else "cpu" model, preprocess = clip.load("ViT-B/32", device=device) # 首次运行自动下载权重 image = preprocess(Image.open("CLIP.png")).unsqueeze(0).to(device) text = clip.tokenize(["a diagram", "a dog", "a cat"]).to(device) with torch.no_grad(): logits = model(image, text)[0] print(logits.softmax(dim=-1).cpu().numpy()) # [[0.9928 0.0042 0.003]]实测输出:这张架构图拿到 99.28% 的概率给了 "a diagram",几乎不给 "a dog" 和 "a cat" 留任何空间。
一图看懂核心机制:为什么两个编码器能共享一个空间
CLIP 由图像编码器和文本编码器组成:图像走视觉塔,文本走 GPT 风格 Transformer 塔,训练时用对比损失把同一张图配对的图文向量拉近、把不配对的推远。推理时只需算两侧特征的余弦相似度(代码里乘以 100 当作 logit),不需要任何任务专属的分类头。再叠加 4 亿对图文的训练数据量,模型天然「见过」大量概念,你才敢用一句提示词就发起分类。
进阶路线图:从一句提示词到训练一个逻辑回归
第一层:直接用。官方默认模板是a photo of a {},把类别名塞进{}就能跑通 CIFAR-100 这类标准基准。
第二层:提示词工程。给每个类别换多种措辞再平均相似度,是仓库里验证过的做法——CIFAR-10 准备了 18 种模板变体,Caltech-101 更是给了 34 种,完整清单见 data/prompts.md。
templates = ['a photo of a {}.', 'a blurry photo of a {}.', 'a toy {}.'] prompts = [clip.tokenize(t.format(cls)) for t in templates] sims = (model.encode_image(image) @ torch.cat(prompts).T / 100) # 相似度矩阵 scores = sims.mean(dim=0) # 同类别多模板取平均,压制单次措辞波动第三层:特征复用。冻结 CLIP 提特征,只在上层训练一个逻辑回归,官方示例里C=0.316、max_iter=1000,代码直接抄 README.md 的 linear-probe 段落即可。
真实任务演练:CIFAR-100 第 3637 张图的零样本预测
把第 3637 张测试图与 100 个类别的a photo of a {c}提示词逐一比对,Top-5 结果如下:
| 排名 | 类别 | 置信度 |
|---|---|---|
| 1 | snake | 65.31% |
| 2 | turtle | 12.29% |
| 3 | sweet_pepper | 3.83% |
| 4 | lizard | 1.88% |
| 5 | crocodile | 1.75% |
真实标签就是 snake。对照一下:ImageNet 上有 1.28M 张标注图,传统 ResNet50 全靠它们才学会分类;而 CLIP 用 0 张标注就达到了 ResNet50 的零样本水平。想更进一步,就去翻 ImageNet 的提示词集(见 notebooks/Prompt_Engineering_for_ImageNet.ipynb),用多模板平均替代单条提示。
选型对照表:8 个官方模型怎么选
clip.available_models()返回 8 个模型,分辨率从 224 到 336,精度逐级上升,推理成本也跟着上升。
| 模型 | 输入分辨率 | 体量定位 | 推荐场景 |
|---|---|---|---|
| RN50 | 224 | 小 | CPU 快速验证 |
| RN101 | 224 | 中 | CPU 可跑的更高精度 |
| RN50x4 / RN50x16 / RN50x64 | 224 | 中~超大 | 显存充足、精度优先 |
| ViT-B/32 / ViT-B/16 | 224 | 中 | GPU 上的通用主力 |
| ViT-L/14 | 224 | 大 | 追求精度的默认高端 |
| ViT-L/14@336px | 336 | 大 | 精度天花板 |
三条调优技巧:
- CPU 或显存紧张选 RN50,有 GPU 追求精度直接 ViT-B/32 起步
clip.load()可以传本地 checkpoint 路径,离线环境不必反复下载- 想自定义阈值或 top-k,记得先把图像/文本特征各自 L2 归一化,点积就是余弦相似度
避坑清单:三个新手最容易踩的坑
- 拿中文类别名直接跑:模型只在英文图文对上训练过,中文描述会显著拉低相似度,类别描述一律写英文
- 超长提示词被截断:
clip.tokenize()的context_length默认 77 token,超长的产品描述会被静默截断,措辞要精简 - 把 logit 当概率读:
model(image, text)返回的原始值是相似度×100 的分数,不是概率,必须再过一层softmax才能读百分比
一句话总结与三个进阶方向
CLIP 把图像分类从「先标注再训练」变成了「写提示词再推理」,标注成本直接砍到零。三个值得接着挖的方向:
- 拿 data/prompts.md 的提示词库扩充你自己的类别体系
- 对比零样本与线性探针在同一批数据上的差距,判断值不值得加一层逻辑回归
- 沿 model-card.md 的局限清单,给自己的场景做一轮 in-domain 测试再决定能否上线
觉得有用的话点个收藏,下一篇带你把 CLIP 接进图文检索场景。
【免费下载链接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image项目地址: https://gitcode.com/GitHub_Trending/cl/CLIP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考