[LAB 04 · CLIP:候选、提示与关系检验](/course/notebooks/0ba963931ddf4866b507b210d93a43bf.html) # 3 · 可选:固定模型,重算四个候选条件 · 实现代码 [独立阅读](/course/notebook-blocks/07786a60d0614351a320e5da4ea0ef2d.html) 主线阅读与优先实验 真实CLIP输入/权重/分数、候选改动、四条件规则与独立关系推理 展开完整实现代码 ``` RUN_CLIP=False # 已下载固定权重后改 True;默认只核对准备与预处理。 if RUN_CLIP: from transformers import CLIPModel, CLIPProcessor, CLIPImageProcessor, AutoTokenizer from PIL import Image REVISION='3d74acf9a28c67741b2f4f2ea7635f0aaf6f0268' local=ROOT/'.model-cache'/REVISION assert (local/'pytorch_model.bin').exists(), '先运行 python fetch_clip.py;本单元不伪造相似度。' assert sha_file(local/'pytorch_model.bin')==provenance['model_sha256'], '权重 SHA-256 不匹配,停止。' clip_model=CLIPModel.from_pretrained(local,local_files_only=True).eval() # Make the teacher run's slow image processing + fast tokenizer explicit. # A shared use_fast=False would also change the tokenizer; keep each choice separate. clip_processor=CLIPProcessor( image_processor=CLIPImageProcessor.from_pretrained(local,local_files_only=True), tokenizer=AutoTokenizer.from_pretrained(local,local_files_only=True,use_fast=True)) for parameter in clip_model.parameters():parameter.requires_grad_(False) photo=Image.open(ROOT/'assets/chelsea-cat.png').convert('RGB') image_inputs=clip_processor(images=photo,return_tensors='pt') arms={ 'A_base':(['cat','dog','horse'],'a photo of a {}.'), 'B_expand_only':(['cat','dog','horse','tiger','fox'],'a photo of a {}.'), 'C_prompt_only':(['cat','dog','horse'],'a cropped photo of a {}.'), 'D_remove_cat':(['dog','horse','tiger','fox'],'a photo of a {}.')} clip_records={} with torch.no_grad(): image_feature=clip_model.get_image_features(**image_inputs) image_feature=image_feature/image_feature.norm(dim=-1,keepdim=True) scale=float(clip_model.logit_scale.exp()) for arm,(names,template) in arms.items(): prompts=[template.format(name) for name in names] text_inputs=clip_processor(text=prompts,return_tensors='pt',padding=True) text_features=clip_model.get_text_features(**text_inputs) text_features=text_features/text_features.norm(dim=-1,keepdim=True) cosine=(image_feature@text_features.T).squeeze(0) probabilities=(cosine*scale).softmax(-1) clip_records[arm]={'candidate_names':names,'prompts':prompts,'cosine':cosine.tolist(), 'softmax':probabilities.tolist(),'top1':names[int(cosine.argmax())]} assert np.allclose(clip_records['A_base']['cosine'],clip_records['B_expand_only']['cosine'][:3],atol=2e-6) clip_result={'status':'actually run locally on CPU','model_repo':'openai/clip-vit-base-patch32','revision':REVISION, 'model_sha256':sha_file(local/'pytorch_model.bin'),'image_sha256':sha_file(ROOT/'assets/chelsea-cat.png'), 'image_source':'scikit-image v0.25.2 chelsea.png; Stefan van der Walt; CC0','logit_scale':scale, 'arms':clip_records,'limitations':['one image; no dataset-level accuracy estimate','relative candidate scores are not open-set certainty']} (OUT/'clip-results.json').write_text(json.dumps(clip_result,indent=2)) fig,axes=plt.subplots(1,3,figsize=(12,3.8));axes[0].imshow(photo);axes[0].axis('off');axes[0].set_title('Same real photograph in all arms') for arm,color in [('A_base',BLUE),('B_expand_only',GOLD)]: rr=clip_records[arm]; loc=np.arange(len(rr['candidate_names'])) axes[1].plot(loc,rr['cosine'],marker='o',label=arm,color=color) axes[2].plot(loc,rr['softmax'],marker='o',label=arm,color=color) for ax,title in zip(axes[1:],['Shared cosine remains fixed','Relative softmax changes']): ax.set(xticks=range(5),xticklabels=arms['B_expand_only'][0],title=title);ax.legend(fontsize=8);ax.grid(alpha=.18) axes[1].set_ylabel('Cosine similarity');axes[2].set_ylabel('Softmax over chosen candidates') savefig('05-clip-candidates.png') print('Actual checkpoint SHA-256:',clip_result['model_sha256']) print('arm | top1 | candidate : cosine / softmax') for arm,r in clip_records.items(): print(arm,r['top1'],[(name,round(co,4),round(pr,4)) for name,co,pr in zip(r['candidate_names'],r['cosine'],r['softmax'])]) else: print('CLIP 未运行:请不要将空结果写成真实相似度。') ```