[LAB 04 · CLIP:候选、提示与关系检验](/course/notebooks/0ba963931ddf4866b507b210d93a43bf.html) # 2 · 独立准备并核对预处理 · 实现代码 [独立阅读](/course/notebook-blocks/aaa45a4607af423da4c9144dad703b56.html) 主线阅读与优先实验 真实CLIP输入/权重/分数、候选改动、四条件规则与独立关系推理 展开完整实现代码 ``` # 当前项目中的独立材料:已存在则复用,缺失才从本讲原站准备。 from pathlib import Path import io, zipfile, requests _base = Path.cwd() _folder = 'lab10-clip' _sentinel = 'assets/chelsea-cat.png' _choices = [_base/_folder, _base/'lecture03-labs'/_folder, _base] _ready = next((p for p in _choices if (p/_sentinel).is_file()), None) if _ready is None: _url = 'https://codingai-lec03.pages.dev/course/materials/' + _folder + '.zip' _response = requests.get(_url, timeout=60) _response.raise_for_status() _payload = _response.content with zipfile.ZipFile(io.BytesIO(_payload)) as _archive: _names = [i.filename for i in _archive.infolist() if not i.is_dir()] _prefix = _folder + '/' _prefixed = all(n.startswith(_prefix) for n in _names) _destination = _base if _prefixed else _base/_folder for _item in _archive.infolist(): _target = (_destination/_item.filename).resolve() if not _target.is_relative_to(_destination.resolve()): raise ValueError('材料包中有越界路径,停止解压。') if _item.is_dir(): _target.mkdir(parents=True, exist_ok=True) elif not _target.exists(): _target.parent.mkdir(parents=True, exist_ok=True) _target.write_bytes(_archive.read(_item)) _ready = next((p for p in _choices if (p/_sentinel).is_file()), None) assert _ready is not None, '请将本讲完整材料包解压到当前项目的 ' + _folder + '/;保留文件结构。' LAB_ROOT = _ready print('材料目录已就绪:', LAB_ROOT) import json, hashlib, platform, sys from pathlib import Path import numpy as np import matplotlib.pyplot as plt ROOT=LAB_ROOT if not (ROOT/'assets').is_dir() and (ROOT/'lab10-clip'/'assets').is_dir():ROOT=ROOT/'lab10-clip' assert (ROOT/'assets').is_dir(), '请解压本实验完整包,并在该目录或其父目录运行。' OUT=ROOT/'runs/current'; OUT.mkdir(parents=True,exist_ok=True) FIG=OUT/'figures'; FIG.mkdir(exist_ok=True) plt.rcParams.update({'figure.dpi':120,'font.size':10,'axes.spines.top':False,'axes.spines.right':False}) BLUE,GOLD,GREEN,PURPLE='#002676','#E6A500','#00856A','#69458D' def sha_file(path):return hashlib.sha256(Path(path).read_bytes()).hexdigest() def savefig(name): if not plt.gcf().get_constrained_layout():plt.tight_layout() plt.savefig(FIG/name,dpi=140,bbox_inches='tight');plt.show() import torch from PIL import Image # 若宿主缺少固定预处理依赖,仅装入本次临时目录;不修改项目环境或下载模型权重。 import importlib.util, importlib.metadata, subprocess try: _transformers_version=importlib.metadata.version('transformers') except importlib.metadata.PackageNotFoundError: _transformers_version=None if _transformers_version!='4.57.1': _deps=ROOT/'_temporary_preprocessing_dependencies' subprocess.check_call([sys.executable,'-m','pip','install','--quiet','--disable-pip-version-check', '--no-cache-dir','--target',str(_deps),'transformers==4.57.1', 'numpy=='+np.__version__,'filelock>=3.20.3,<4']) sys.path.insert(0,str(_deps)) importlib.invalidate_caches() from transformers import CLIPProcessor,CLIPImageProcessor,AutoTokenizer import transformers assert transformers.__version__=='4.57.1', '请使用包内固定 requirements.txt。' torch.set_num_threads(2) provenance=json.loads((ROOT/'assets/provenance.json').read_text()) assert sha_file(ROOT/'assets/chelsea-cat.png')==provenance['image_sha256'] REVISION=provenance['revision'] local=ROOT/'.model-cache'/REVISION config_local=ROOT/'model-config' # small verified config files ship in the package; weights are downloaded only on request. manifest=json.loads((config_local/'manifest.json').read_text()) for f,expected in manifest['sha256'].items():assert sha_file(config_local/f)==expected clip_processor=CLIPProcessor(image_processor=CLIPImageProcessor.from_pretrained(config_local,local_files_only=True),tokenizer=AutoTokenizer.from_pretrained(config_local,local_files_only=True,use_fast=True)) photo=Image.open(ROOT/'assets/chelsea-cat.png').convert('RGB') 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 {}.')} image_inputs=clip_processor(images=photo,return_tensors='pt') all_prompts=list(dict.fromkeys(template.format(name) for names,template in arms.values() for name in names)) text_inputs=clip_processor(text=all_prompts,padding=True,return_tensors='pt') assert tuple(image_inputs['pixel_values'].shape)==(1,3,224,224) assert clip_processor.image_processor.__class__.__name__=='CLIPImageProcessor' assert clip_processor.tokenizer.__class__.__name__=='CLIPTokenizerFast' preprocess_verification={'scope':'preprocessing only, no weights loaded','pixel_shape':list(image_inputs['pixel_values'].shape),'pixel_sha256':hashlib.sha256(image_inputs['pixel_values'].numpy().tobytes()).hexdigest(),'prompt_count':len(all_prompts),'tokenizer':clip_processor.tokenizer.__class__.__name__,'image_processor':clip_processor.image_processor.__class__.__name__,'transformers':transformers.__version__,'image_sha256':sha_file(ROOT/'assets/chelsea-cat.png'),'revision':REVISION} historical_preprocess=json.loads((ROOT/'historical-v16/results/preprocessing-audit-20260918.json').read_text()) assert preprocess_verification['pixel_sha256']==historical_preprocess['pixel_values_sha256'] legacy_processor=CLIPProcessor.from_pretrained(config_local,local_files_only=True) legacy_image=legacy_processor(images=photo,return_tensors='pt') legacy_text=legacy_processor(text=all_prompts,padding=True,return_tensors='pt') assert torch.equal(legacy_image['pixel_values'],image_inputs['pixel_values']) assert all(torch.equal(legacy_text[k],text_inputs[k]) for k in text_inputs) preprocess_verification['legacy_default_pixel_max_abs_difference']=float((legacy_image['pixel_values']-image_inputs['pixel_values']).abs().max()) preprocess_verification['all_prompt_token_tensors_equal']=True preprocess_verification['token_ids_sha256']=hashlib.sha256(text_inputs['input_ids'].numpy().tobytes()).hexdigest() (OUT/'preprocessing-verification.json').write_text(json.dumps(preprocess_verification,indent=2));print(json.dumps(preprocess_verification,indent=2)) ```