Anomalib 中的 AnomalyVFM:基于视觉基础模型的零样本工业异常检测实现详解
【免费下载链接】anomalibAn anomaly detection library comprising state-of-the-art algorithms and features such as experiment management, hyper-parameter optimization, and edge inference.项目地址: https://gitcode.com/GitHub_Trending/an/anomalib
本文以 Anomalib 官方 API 参考文档anomalyvfm.md所覆盖的两个核心类 —— Lightning 封装AnomalyVFM与 PyTorch 实现AnomalyVFMModel—— 为主线,结合仓库中的组件源码、配置文件与模型模块 README,完整讲解该零样本(zero-shot)异常检测模型的 API 用法、参数含义、内部数据流与底层实现原理。读完后,你将掌握如何用一行 CLI 命令或几行 Python 代码直接部署该模型,理解 RADIO 视觉基础模型 + DoRA 适配器 + 异常解码器的结构组成,以及该模型在精度、导出等方面的使用边界。
1. AnomalyVFM 是什么:零样本异常检测的定位
AnomalyVFM 源自论文《AnomalyVFM — Transforming Vision Foundation Models into Zero-Shot Anomaly Detectors》(CVPR 2026),是 Anomalib 图像模型族中的成员,可通过from anomalib.models.image import AnomalyVFM直接导入。据模块 README(src/anomalib/models/image/anomalyvfm/README.md)与包级文档字符串(anomalyvfm/__init__.py)描述:
- 零样本设定:该模型构建在预训练视觉基础模型(VFM)之上,官方训练流程先用 FLUX 生成合成图像再在其上训练;Anomalib 的实现只支持零样本推理,不需要也不支持在本地再训练;
- 任务类型:属于分割(Segmentation)模型,一次前向同时输出图像级异常分数与像素级异常掩码,即同时支持异常检测与异常定位两个任务;
- 导出限制:包级 Notes 明确指出该模型因 Vision Transformer 架构需要较多 GPU 显存,且后续章节将看到源码中显式禁用了导出功能。
包级__init__.py只导出AnomalyVFM(Lightning 模型),而AnomalyVFMModel位于 torch_model.py 中,两者正是 API 参考页分别用automodule挂接的对象。
2.AnomalyVFM(Lightning 模型):API 参考逐项解读
参考页第一个automodule指令指向 anomalyvfm.lightning_model 中的AnomalyVFM类。它继承自AnomalibModule,构造签名与行为如下:
>>> from anomalib.models.image import AnomalyVFM >>> # 零样本用法:构造即完成权重加载,无需 fit >>> model = AnomalyVFM()2.1 构造函数参数
__init__(lightning_model.py#L44-L63)接收五个参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
pre_processor | True | 预处理配置;传True时使用configure_pre_processor返回的默认配置 |
post_processor | True | 后处理配置;默认由configure_post_processor返回PostProcessor() |
evaluator | True | 评估器配置,用于计算验证/测试指标 |
visualizer | True | 可视化配置 |
precision | PrecisionType.FLOAT32 | 推理精度,接受PrecisionType枚举或字符串(如"float32");字符串会被.lower()后转换为枚举,并写入内部AnomalyVFMModel.precision |
构造时先创建内部AnomalyVFMModel(),再根据precision的类型(枚举或字符串)设置self.model.precision。这解释了官方配置文件中precision: float32字段的最终去向(见第 4 节)。
2.2 预处理器:768×768 默认尺寸
configure_pre_processor(lightning_model.py#L65-L83)使用torchvision的Compose([Resize(image_size, antialias=True)]),默认目标尺寸为DEFAULT_IMAGE_SIZE = 768,即768×768。这是 RADIO 骨干(patch size 16)下的空间特征网格基础:768/16 = 48×48 个 patch token。
值得注意的一个实现细节:configure_transforms(lightning_model.py#L131-L140)会忽略外部传入的image_size并打印警告,因为该模型自带固定的变换管线——也就是说,该模型并不遵循 Anomalib 全局image_size配置的通用约定。
2.3 推理路径:validation/test/predict 三合一
validation_step(lightning_model.py#L85-L103)是唯一的实质推理逻辑:
anomaly_scores, anomaly_maps = self.model(batch.image) predictions = InferenceBatch(pred_score=anomaly_scores, anomaly_map=anomaly_maps) return batch.update(**predictions._asdict())test_step与predict_step均直接重定向到validation_step,因此anomalib test与anomalib predict走的完全是同一套推理代码。
2.4 零样本属性与导出限制
两个属性与方法明确了该模型的边界:
learning_type恒返回LearningType.ZERO_SHOT(lightning_model.py#L113-L120);trainer_arguments返回空字典——不需要训练超参,这也意味着不应调用anomalib train;to_torch/to_onnx/to_openvino三个导出入口全部被覆写为空操作,仅打印警告 "Exporting the model is not supported for AnomalyVFM model. Skipping..."(lightning_model.py#L152-L165)。因此该模型无法像其他模型那样部署到 OpenVINO/ONNX 边缘推理路径,只能在 PyTorch 运行时内使用。
3.AnomalyVFMModel(PyTorch 模型):权重加载与前向流程
参考页第二个automodule指令指向 anomalyvfm.torch_model 中的AnomalyVFMModel。其 docstring 概括了整体集成:"RADIO 基础 VFM + PEFT 适配器 + 简单解码器(像素级掩码)+ 简单预测器(图像级分数)"。
3.1 依赖与权重下载
构造函数(torch_model.py#L40-L65)做了三件事:
- 硬依赖检查:若缺少
huggingface_hub或safetensors,抛出ImportError并提示pip install anomalib[huggingface]; - 挂载 PEFT:
self.model.add_peft(),默认秩r=64(见 3.3 节); - 下载预训练权重:通过
hf_hub_download从 Hugging Face Hub 仓库MaticFuc/anomalyvfm_radio拉取model.safetensors,并固定到 revision17654e763c8fae5ae1c44e2ec421a427783d6196以保证可复现,随后load_state_dict完成加载。
因此首次实例化需要联网(local_files_only=False),且权重会进入 HF 缓存目录;后续实例化命中缓存。
3.2 前向传播:双输出结构
forward(torch_model.py#L67-L107)在torch.autocast + torch.no_grad()下执行(推理模型,全程不建图),流程为:
summary, ftrs = self.model(img) # RADIO 输出 summary 与空间特征 ftrs = ftrs.permute(0, 2, 1).reshape(b, -1, h//16, w//16) # 还原为特征图 anomaly_score = self.predictor(summary).sigmoid() # 图像级分数 anomaly_maps, _ = self.decoder(ftrs) # 解码器输出 (mask, conf) anomaly_maps = anomaly_maps.sigmoid() anomaly_maps = self.mean_kernel(anomaly_maps) # 5×5 平均池化平滑 anomaly_maps = functional.interpolate(anomaly_maps, size=(h, w), mode="bilinear", ...)关键实现细节:
- 精度策略:
precision为None或float32时用torch.float32;否则 CPU 上自动回退到bfloat16,GPU 上用float16(torch_model.py#L82-L87); - 空间对齐:特征图按
h // patch_size, w // patch_size重建(patch_size = 16,定义于 BaseModel),这要求输入分辨率能被 16 整除——默认 768×768 满足该条件; - 平滑与上采样:掩码先过 5×5
AvgPool2d(mean_kernel)抑制锯齿噪声,再双线性插值回原图尺寸。
3.3BaseModel:RADIO 骨干 + DoRA
BaseModel(torch_model.py#L110-L143)封装RADIOModel,固定feature_dim = 1024、patch_size = 16;add_peft(r=64)调用 dora.py 中的add_peft,递归遍历 RADIO 的每个子模块,将名字为qkv的线性层替换为DoRAQKVWrapper、名字为proj的替换为DoRAWrapper。
从 dora.py 的源码看,这些包装器实现了 DoRA(Weight-Decomposed Low-Rank Adaptation):
- 普通线性层(DoRAWrapper):在冻结原权重基础上学习低秩增量
delta_w = (B @ A) * (alpha / r),然后对W + delta_w做幅值/方向分解——magnitude(初始化为原权重逐行范数)乘以上单位方向,得到最终权重参与前向; - QKV 融合层(DoRAQKVWrapper):只对 Q 与 V 两个子块做低秩适配与幅值分解,K 保持原始权重,最后
torch.cat([final_q, base_k, final_v])重组; r=0时所有包装器退化为直通原始层,因此该参数也可理解为"适配器开关"。
这个设计与 AnomalyVFM 论文的设定一致:只在预训练 VFM 上附加少量可训练参数,主干特征保持不变。
3.4 RADIO 骨干内部结构
RADIOModel 由 radio.py 定义,要点:
- 输入归一化:
InputConditioner使用 CLIP 风格的 mean/std(radio.py#L399-L416)对 0~1 图像做归一化; - Patch 化:
ViTPatchGenerator(radio.py#L88-L129)以patch_size=16、embed_dim=1024将图像 unfold 成 patch token,经768→1024线性投影,并前置num_prefix_tokens=8个可学习前缀 token(相当于扩展版 [CLS]); - 动态分辨率位置编码:基础位置编码按 128×128 网格(16384 个 token)初始化,
_interpolate_pos_encoding(radio.py#L323-L375)在输入分辨率对应网格不等于 128×128 时用双三次插值重采样空间位置编码,前缀 token 位置编码不足/超出时补零或截断——这让同一套权重可处理不同尺寸的输入; - 双输出:
forward返回summary(取前 3 个前缀 token 特征、压平为 1024×3 维向量,summary_idxs = [0, 1, 2])与spatial_features(第 8 个 token 之后的全部 patch 特征)。
3.5 解码器与预测器
decoder.py 提供两个轻量头部:
SimplePredictor:单个nn.Linear(dim, 1),输入summary(1024×3,即feat_dim * 3),输出图像级 logit,经sigmoid得到异常分数;SimpleDecoder(decoder.py#L70-L106):一个BottleNeck(3×3 卷积 + GroupNorm×2)后接upsample_blocks=2个DecoderBlockBilinear(每次上采样 2 倍并将通道减半,1024→512→256),最后两个 1×1 卷积分别输出mask logit与conf logit(forward返回二元组,但AnomalyVFMModel.forward只取第一个);AnomalyVFMModel初始化时按feat_dim = 1024实例化SimpleDecoder(1024, 1, 1)与SimplePredictor(3072)(torch_model.py#L52-L54)。
此外,模块 README 说明 ICPR 与 JIMS 两个论文版本的差异仅在于adapt_cls_features(分类头特征是否做适配,JIMS 版为默认的 False);当前仓库源码未暴露该开关,可理解为默认按 JIMS 版本实现。
4. 配置与命令行用法
4.1 模型配置文件
官方提供的模型配置 examples/configs/model/anomalyvfm.yaml 全文仅两项:
model: class_path: anomalib.models.AnomalyVFM init_args: precision: float32class_path通过 Anomalib 的anomalib.models命名空间解析到AnomalyVFM(image/__init__.py 中from .anomalyvfm import AnomalyVFM);precision字符串在构造时被转换为PrecisionType并注入内部 torch 模型。由于trainer_arguments返回空字典,该配置不需要(也无法)追加max_steps、batch_size等训练项。
4.2 CLI:直接零样本评测
模块 README 给出的标准评测命令为:
anomalib test --model AnomalyVFM --data MVTecAD --data.category <category>例如对 MVTec AD 的bottle类别跑零样本评测:
anomalib test --model AnomalyVFM --data MVTecAD --data.category bottle由于predict_step与validation_step共用同一实现,推理侧命令同理:
anomalib predict --model AnomalyVFM --data <path-or-dataset>4.3 Python API 示例
from anomalib.models import AnomalyVFM model = AnomalyVFM() # 首次运行自动从 HF Hub 下载 RADIO + DoRA 权重 model.test() # 在配置的数据集上零样本评测 # 或单图推理 prediction = model.predict("path/to/image.jpg") prediction.visualize(save_path="anomaly_result.png")注意两个前提:其一,需要安装anomalib[huggingface]额外依赖组(huggingface_hub、safetensors),否则构造时抛ImportError;其二,该模型不能fit,也不能导出 ONNX/OpenVINO/TorchScript(调用to_onnx等只会得到跳过警告)。
5. 参考性能:MVTec AD 零样本结果
据模块 README(anomalyvfm/README.md#L28-L49)记载,该 Anomalib 实现在 MVTec AD 上的零样本结果如下:
| category | I-AUROC | I-F1Max | P-AUROC | P-F1Max | AUPRO |
|---|---|---|---|---|---|
| bottle | 98.37 | 97.64 | 94.92 | 69.85 | 90.11 |
| cable | 91.92 | 88.14 | 87.54 | 18.80 | 56.55 |
| capsule | 96.47 | 95.24 | 97.86 | 42.31 | 93.57 |
| carpet | 99.84 | 98.89 | 99.65 | 75.47 | 98.69 |
| grid | 99.92 | 99.13 | 97.42 | 43.16 | 90.91 |
| hazelnut | 99.14 | 97.14 | 96.70 | 55.71 | 92.93 |
| leather | 99.97 | 99.46 | 99.56 | 57.72 | 99.01 |
| metal_nut | 98.19 | 97.30 | 66.28 | 28.84 | 83.53 |
| pill | 95.40 | 95.27 | 87.63 | 38.55 | 91.75 |
| screw | 97.94 | 95.55 | 99.36 | 47.91 | 96.55 |
| tile | 99.42 | 98.82 | 96.24 | 74.48 | 93.44 |
| toothbrush | 91.81 | 93.10 | 92.65 | 36.26 | 91.68 |
| transistor | 78.87 | 72.22 | 68.75 | 15.45 | 54.03 |
| wood | 100.00 | 100.00 | 96.23 | 70.38 | 78.82 |
| zipper | 98.84 | 97.14 | 98.36 | 62.57 | 94.36 |
| average | 96.41 | 95.00 | 91.94 | 49.16 | 87.06 |
这些数据表明该实现完全复现了论文报告的零样本水平:图像级指标(I-AUROC/I-F1Max)普遍高于 90,而像素级指标(P-F1Max 平均 49.16)与图像级存在明显差距,这是零样本掩码预测的常见特征,复现或调参时应以 AUPRO(平均 87.06)作为定位质量的综合参考。
6. 小结与使用边界
回到 API 参考页覆盖的两个类,可以这样概括anomalyvfm.md的完整技术图景:
AnomalyVFM是面向anomalib test/predict流水线的 Lightning 封装:固定 768×768 预处理、零样本学习类型、空训练参数、不支持导出;AnomalyVFMModel是推理核心:RADIO VFM 骨干(1024 维、patch 16、8 前缀 token、可插值位置编码)+ 秩 64 的 DoRA 适配器 + 双分支轻量头(分数预测器与掩码解码器),权重固定 revision 从 HF Hub 加载;- 使用门槛只有两点:安装
anomalib[huggingface]依赖组、确保输入分辨率可被 16 整除(默认预处理已满足)。
仓库中未包含针对 AnomalyVFM 的专属单元测试文件,其正确性主要由模块 README 的 MVTec AD 评测表与上述固定权重 revision 共同约束。若需要评估其他数据集(VisA、Real-IAD、MPDD 等)的表现,模块 README 指引参考原论文或官方实现。
【免费下载链接】anomalibAn anomaly detection library comprising state-of-the-art algorithms and features such as experiment management, hyper-parameter optimization, and edge inference.项目地址: https://gitcode.com/GitHub_Trending/an/anomalib
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考