03_CLIP图文对齐实战

发布时间:2026/7/25 2:43:51
03_CLIP图文对齐实战 CLIP图文对齐实战用ViT-B/32实现零样本分类本文是《空间智能全栈实战》系列的实战教程配套完整源码可下载。前言在空间智能技术栈中理解图像中的内容是什么是所有下游任务的基础。无论是3D重建后的场景标注、无人机航拍的自动识别还是3D空间问答系统都需要一个能同时理解图像和文本的模型。CLIPContrastive Language-Image Pre-training正是为此而生。CLIP由OpenAI于2021年提出通过对比学习将图像和文本映射到同一个向量空间使得一只猫的图片和文本a photo of a cat在向量空间中距离很近。最吸引人的特性是零样本分类zero-shot classification——不需要训练任何分类器只需给出候选文本列表CLIP就能判断图片最匹配哪个描述。适合人群有PyTorch基础、想快速上手多模态模型的开发者。读完本文你将掌握CLIP模型的加载、图文特征提取、相似度计算并实现一个完整的零样本图像分类器。环境准备安装依赖pipinstalltorch torchvision pipinstallftfy regex tqdm pipinstallgithttps://github.com/openai/CLIP.git或者使用pip直接安装pipinstallclip-by-openai模型下载CLIP首次加载时会自动从OpenAI服务器下载模型权重。ViT-B/32模型约350MB下载后缓存在~/.cache/clip/目录下。如果网络不通可以手动下载权重文件放到缓存目录。硬件要求组件最低要求推荐CPU4核8核以上GPU可选任意CUDA GPU内存4GB8GBCLIP在CPU上也能运行只是推理速度稍慢。ViT-B/32在CPU上处理一张图片约0.5秒。核心原理CLIP的核心思想是对比学习。训练时给定一个batch的图像-文本对CLIP同时编码图像和文本然后计算所有图像与所有文本之间的余弦相似度矩阵。目标是让匹配对的相似度最大不匹配对的相似度最小。双塔架构图像 → Image Encoder (ViT) → 图像特征 I ∈ R^512 ↕ 余弦相似度 文本 → Text Encoder (Transformer) → 文本特征 T ∈ R^512零样本分类流程将每个类别名称构造成文本提示如 “a photo of a {class}”用文本编码器提取所有候选文本的特征用图像编码器提取待分类图像的特征计算图像特征与每个文本特征的余弦相似度取相似度最高的类别作为预测结果相似度计算公式sim ( I , T ) I ⋅ T ∥ I ∥ ⋅ ∥ T ∥ \text{sim}(I, T) \frac{I \cdot T}{\|I\| \cdot \|T\|}sim(I,T)∥I∥⋅∥T∥I⋅T​CLIP使用一个可学习的温度参数τ \tauτ来缩放相似度最终的logits为logits τ ⋅ sim ( I , T ) \text{logits} \tau \cdot \text{sim}(I, T)logitsτ⋅sim(I,T)ViT-B/32中的B表示Base规模32表示patch大小为32x32像素。一张224x224的图片被分成7x749个patch每个patch经过线性投影后作为Transformer的token输入。代码实战以下代码来自项目仓库module4/clip_alignment.py。基础加载模型与特征提取importclipimporttorchfromPILimportImage# 加载模型和预处理函数devicecudaiftorch.cuda.is_available()elsecpumodel,preprocessclip.load(ViT-B/32,devicedevice)# 图像预处理image_pathdata/test_image.jpgimagepreprocess(Image.open(image_path)).unsqueeze(0).to(device)# 文本编码texts[a photo of a cat,a photo of a dog,a photo of a car]text_tokensclip.tokenize(texts).to(device)# 提取特征withtorch.no_grad():image_featuresmodel.encode_image(image)# (1, 512)text_featuresmodel.encode_text(text_tokens)# (3, 512)# 计算相似度并softmax得到概率logits_per_image(100.0*image_features text_features.T).softmax(dim-1)probslogits_per_image.cpu().numpy()print(零样本分类结果:)fortext,probinzip(texts,probs[0]):print(f{text}:{prob*100:.2f}%)封装完整的零样本分类器importclipimporttorchimportnumpyasnpfromPILimportImagefromtypingimportList,TupleclassCLIPZeroShotClassifier:CLIP零样本分类器# 推荐的提示模板PROMPT_TEMPLATES[a photo of a {}.,a photo of a {} in the wild.,a photo of a {} on a table.,a rendering of a {}.,a 3D model of a {}.,]def__init__(self,model_nameViT-B/32,deviceNone):self.devicedeviceor(cudaiftorch.cuda.is_available()elsecpu)self.model,self.preprocessclip.load(model_name,deviceself.device)self.model.eval()# 获取文本特征维度self.feat_dimself.model.encode_text(clip.tokenize([test]).to(self.device)).shape[-1]print(f[INFO] CLIP{model_name}loaded on{self.device}, ffeature dim{self.feat_dim})defencode_image(self,image_path:str)-torch.Tensor:编码单张图像imageImage.open(image_path).convert(RGB)image_inputself.preprocess(image).unsqueeze(0).to(self.device)withtorch.no_grad():featuresmodel.encode_image(image_input)featuresfeatures/features.norm(dim-1,keepdimTrue)returnfeatures.cpu()defencode_images_batch(self,image_paths:List[str])-torch.Tensor:批量编码图像images[]forpathinimage_paths:imgImage.open(path).convert(RGB)images.append(self.preprocess(img))image_inputtorch.stack(images).to(self.device)withtorch.no_grad():featuresmodel.encode_image(image_input)featuresfeatures/features.norm(dim-1,keepdimTrue)returnfeatures.cpu()defencode_text_with_prompts(self,classes:List[str])-torch.Tensor:使用多模板提示编码文本集成策略all_features[]fortemplateinself.PROMPT_TEMPLATES:texts[template.format(c)forcinclasses]tokensclip.tokenize(texts).to(self.device)withtorch.no_grad():featuresmodel.encode_text(tokens)featuresfeatures/features.norm(dim-1,keepdimTrue)all_features.append(features.cpu())# 对所有模板的特征取平均avg_featurestorch.stack(all_features).mean(dim0)avg_featuresavg_features/avg_features.norm(dim-1,keepdimTrue)returnavg_featuresdefclassify(self,image_path:str,classes:List[str],use_prompts:boolTrue)-List[Tuple[str,float]]:零样本分类image_featuresself.encode_image(image_path)ifuse_prompts:text_featuresself.encode_text_with_prompts(classes)else:texts[fa photo of a{c}forcinclasses]tokensclip.tokenize(texts).to(self.device)withtorch.no_grad():text_featuresmodel.encode_text(tokens)text_featurestext_features/text_features.norm(dim-1,keepdimTrue)text_featurestext_features.cpu()# 计算余弦相似度similarity(100.0*image_features text_features.T).softmax(dim-1)probssimilarity[0].numpy()# 按概率排序results[(classes[i],float(probs[i]))foriinrange(len(classes))]results.sort(keylambdax:x[1],reverseTrue)returnresults# 使用示例classifierCLIPZeroShotClassifier(ViT-B/32)classes[cat,dog,car,building,tree,person]resultsclassifier.classify(data/test_image.jpg,classes)print(\n分类结果按置信度排序:)forlabel,probinresults:print(f{label:12s}:{prob*100:6.2f}%)进阶图文检索CLIP不仅能做分类还能做图文检索——给定一张图找最匹配的文本描述或给定一段文本找最匹配的图片。classCLIPRetriever:CLIP图文检索器def__init__(self,classifier):self.modelclassifier.model self.preprocessclassifier.preprocess self.deviceclassifier.devicedefbuild_image_database(self,image_paths):构建图像特征库features_list[]forpathinimage_paths:imgImage.open(path).convert(RGB)img_inputself.preprocess(img).unsqueeze(0).to(self.device)withtorch.no_grad():featself.model.encode_image(img_input)featfeat/feat.norm(dim-1,keepdimTrue)features_list.append(feat.cpu())self.image_dbtorch.cat(features_list,dim0)self.image_pathsimage_pathsprint(f[OK] 图像库构建完成:{len(image_paths)}张图像)deftext_to_image(self,query_text,top_k5):文本检索图像tokensclip.tokenize([query_text]).to(self.device)withtorch.no_grad():text_featself.model.encode_text(tokens)text_feattext_feat/text_feat.norm(dim-1,keepdimTrue)text_feattext_feat.cpu()similarities(100.0*text_feat self.image_db.T).softmax(dim-1)probssimilarities[0].numpy()top_indicesnp.argsort(probs)[::-1][:top_k]results[]foridxintop_indices:results.append((self.image_paths[idx],float(probs[idx])))returnresults特征可视化importmatplotlib.pyplotaspltfromsklearn.decompositionimportPCAdefvisualize_clip_features(classifier,image_paths,labels):用PCA可视化CLIP特征空间featuresclassifier.encode_images_batch(image_paths).numpy()# PCA降维到2DpcaPCA(n_components2)features_2dpca.fit_transform(features)# 绘图plt.figure(figsize(8,6))colorsplt.cm.Set1(np.linspace(0,1,len(set(labels))))fori,labelinenumerate(labels):masknp.array(labels)label plt.scatter(features_2d[mask,0],features_2d[mask,1],colorcolors[i],labellabel,s50,alpha0.7)plt.legend()plt.title(CLIP Feature Space (PCA))plt.xlabel(PC1)plt.ylabel(PC2)plt.savefig(clip_features_pca.png,dpi150)print([OK] 特征可视化已保存: clip_features_pca.png)运行结果执行零样本分类脚本后输出如下[INFO] CLIP ViT-B/32 loaded on cpu, feature dim512 分类结果按置信度排序: cat : 94.32% dog : 3.18% person : 1.27% car : 0.89% tree : 0.21% building : 0.13%使用多模板集成策略后分类准确率通常比单模板提升2-5个百分点。在ImageNet零样本分类上ViT-B/32的Top-1准确率约为63%对于不需要训练的零样本场景已经非常实用。PCA可视化图中同一类别的图像在CLIP特征空间中会聚集在一起不同类别之间有明显的间隔说明CLIP确实学到了有区分度的图文对齐表示。常见问题Q1: clip.load()下载模型超时国内网络可能无法直接访问OpenAI的模型服务器。解决方法设置代理或手动下载模型权重。权重URL格式为https://openaipublic.azureedge.net/clip/models/...下载后放到~/.cache/clip/目录文件名保持原样。Q2: RuntimeError: Expected all tensors on the same device图像和文本token没有放到同一个设备上。确保所有输入都调用.to(device)device必须一致。常见错误是模型在GPU但输入在CPU或反过来。Q3: 中文文本分类效果很差原始CLIP主要在英文数据上训练中文支持较弱。解决方案使用OpenAI的CLIP的中文版本如clip.load(ViT-B/32, device)改用Chinese-CLIP或先用翻译API将中文文本翻译成英文再编码。Q4: 零样本分类准确率不如预期提示词prompt工程对CLIP零样本性能影响很大。建议使用多模板集成如本文代码中的5个模板根据任务场景设计特定模板。例如做3D重建场景标注时用 “a 3D rendering of a {}” 比通用模板效果好。Q5: 批量处理时内存溢出clip.tokenize对超长文本会截断默认最大token数为77。如果文本列表很长分批处理batch_size32foriinrange(0,len(texts),batch_size):batchtexts[i:ibatch_size]tokensclip.tokenize(batch).to(device)# ... 处理进阶方向Chinese-CLIP如果需要中文支持使用中文-CLIP模型如OFA-Sys/chinese-clip-vit-base-patch16在中文图文检索和零样本分类上效果显著优于英文CLIP翻译方案。CLIP特征用于3D理解将CLIP的图像特征蒸馏到3D点云或高斯表示中实现3D场景的语义开放词汇理解。这是空间智能的核心技术之一后续教程会详细展开。提示工程优化研究CoOpContext Optimization等方法将手动设计的提示替换为可学习的连续向量在少量标注数据上微调提示大幅提升下游任务性能。配套源码下载本文代码已收录在《空间智能全栈实战》完整代码仓库中包含7大模块54个Python脚本。专栏订阅空间智能全栈实战专栏系统学习从无人机到3D世界的完整技术栈。更多资源模块1-2代码包COLMAP 3DGS基础模块4代码包空间VLM与3D理解完整7模块代码合集付费专栏推荐《空间智能商业级项目实战》会技术但不知道怎么赚钱12个商业级项目全流程拆解覆盖3DGS看房、景区数字化、电商3D、古建筑测绘、SLAM建图。专栏特色每篇6000-10000字深度远超免费教程完整可运行代码 合同模板 报价体系附赠定价计算器、商业提案生成器、验收SOP学完可直接接单变现专栏目录12篇房地产3D看房系统完整项目实战景区数字化项目8周交付全流程电商3D商品批量生成平台3DGS模型压缩与Web端秒开优化3DGS训练30参数完全调优指南COLMAP高精度重建质控体系3DGS-SLAM实时建图系统搭建空间智能项目报价体系与合同模板技术IP打造与获客体系项目交付标准与售后SOP古建筑数字化保护项目全流程技术选型决策树与方案设计框架 点击订阅专栏开启变现之路