Lecture 033 · 可选:固定模型,重算四个候选条件 · 实现代码
3 · 可选:固定模型,重算四个候选条件 · 实现代码
主线阅读与优先实验
真实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 未运行:请不要将空结果写成真实相似度。')