open_clip 2.26 加载 ViT-B-32 做商品零样本分类,8 个类别的预测全部落到第一类,logits 几乎一样,换成 openai 官方权重仍然如此。
一开始怀疑是「logits 没做 softmax 直接取 argmax,尺度差异被忽略」,查了一圈,方向不对。
原因不止一个,得分开看。图像归一化用了 ImageNet 的 mean 与 std。另一种情况是文本提示只写了类别名,没有套模板句。
不容易想到的是,图像张量还是 uint8 没转 float,除以 255 这一步漏了。
第一件事是检查送入模型的张量范围与均值
python -c "import torch;x=torch.load('x.pt');print(x.dtype,float(x.min()),float(x.max()),float(x.mean()))"
再往下改用模型自带的 preprocess 生成输入
python -c "import open_clip;m,_,pp=open_clip.create_model_and_transforms('ViT-B-32',pretrained='openai');print(pp)"
给每个类别套上 a photo of a 模板再编码
python -c "import open_clip;t=open_clip.get_tokenizer('ViT-B-32');print(t(['a photo of a cup','a photo of a shoe']))"
等前面都确认过,再打印 top5 概率分布确认不再退化成单类
python classify.py --topk 5 --template 'a photo of a {}'
恢复的判定其实很直接。8 个类别的预测分布拉开,top1 与人工标注一致率超过 0.9,最高与次高概率差大于 0.2。
CLIP 对归一化参数极其敏感,用错 mean 与 std 时特征几乎塌缩,表现就是所有样本判同一类,先对齐官方 preprocess 再谈提示模板。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
