- 人工智能
- 计算机视觉
- 预训练
【免费下载链接】PaddleSeg
Easy-to-use image segmentation library with awesome pre-trained model zoo, supporting wide-range of practical tasks in Semantic Segmentation, Interactive Segmentation, Panoptic Segmentation, Image Matting, 3D Segmentation, etc.
QualityInspector 是 PaddleSeg 仓库中的一个工业质检子项目,内置了一套完整的**无监督异常检测(Unsupervised Anomaly Detection, UAD)**方案,覆盖 PaDiM、PatchCore、STFPM 三种基于表示的算法,配套 MVTec AD 数据集的训练、评估、预测工具与 YAML 配置体系。本文以contrib/QualityInspector/docs/uad/README.md为主线,结合contrib/QualityInspector/qinspector/uad/与tools/uad/下的源码实现,完整讲解算法原理、数据集组织、命令行操作与配置文件逐项解读,读者可据此在自有缺陷检测场景中直接落地。
1. 无监督异常检测算法原理
无监督异常检测(UAD)的核心假设是:工业场景中缺陷样本稀少且形态未知,难以收集,而正常(OK)样本充足。因此算法只使用正常样本建模"正常分布",推理时凡是偏离该分布的图像区域即判定为缺陷。技术方向可划分为两类:
- 基于表示的算法:通过某种映射将输入图片映射到特征空间,在该空间中正常样本与异常样本更容易区分。特点是推理速度快,但一般只能实现patch 级(区域级)的分割;
- 基于重构的算法:仅用正常样本训练的重构模型只能很好地重构正常样本,无法准确重构缺陷样本,通过对比重构误差检测缺陷。特点是能够实现像素级分割,但速度较慢。
在具体实现上,基于表示的算法通常采用 ImageNet 预训练 backbone 提取特征,推理时对比正常样本与异常样本的特征差异完成缺陷的分类与分割;基于重构的算法通常以自编码器为重构模型,推理时对比重构前后图像的差异完成分类与分割。
目前 QualityInspector 的 UAD 方案支持三种基于表示的算法,其中 PaDiM、PatchCore 无需训练网络:
| 算法 | 论文思想 | 训练阶段 | 推理阶段 |
|---|---|---|---|
| PaDiM | Patch Distribution Modeling | 用预训练 CNN 提取多尺度特征,随机降维后逐位置拟合多元高斯分布 | 用马氏距离衡量每个特征位置的异常分数,分数越高异常可能性越大 |
| PatchCore | KNN Greedy CoreSet 采样 | 提取多尺度特征,经 KNN Greedy CoreSet 采样最具代表性的特征点,构建特征向量记忆池 | 比对测试特征与记忆池的距离得到每个特征位置的异常分数 |
| STFPM | 师生特征金字塔匹配 | 学生网络将自身特征与冻结的教师网络逐尺度匹配,学习正常样本分布 | 对比教师、学生各尺度特征,差异越大异常分数越高 |
从源码结构看,PaDiM/PatchCore 属于"训练即特征统计"的范式(backbone 全程no_grad),而 STFPM 的配置中带有epochs/lr/momentum/weight_decay等真实训练超参,是需要训练网络参数的算法,三种算法互补覆盖不同精度与成本需求。
1.1 PaDiM 源码级实现
PaDiM 的模型定义在 contrib/QualityInspector/qinspector/uad/models/padim.py 中,ResNet_PaDiM直接复用 Paddle 视觉库的resnet18 / resnet50 / wide_resnet50_2,前向时在paddle.no_grad()下依次取出layer1 / layer2 / layer3三个尺度的中间特征作为嵌入来源:
with paddle.no_grad(): x = self.model.conv1(x) x = self.model.bn1(x) x = self.model.relu(x) x = self.model.maxpool(x) x = self.model.layer1(x) res.append(x) x = self.model.layer2(x) res.append(x) x = self.model.layer3(x) res.append(x) return res训练脚本 contrib/QualityInspector/tools/uad/padim/train.py 中体现了完整的建模流程:
- 收集训练集所有正常样本的
layer1/layer2/layer3特征,将后两层上采样到与layer1相同分辨率后沿通道拼接(embedding concat); - 从拼接特征中随机选取 d 个通道降维(
fins表中resnet18对应原始维度 448,降维到 100); - 对每个特征位置计算均值与协方差,拟合多元高斯分布,协方差矩阵加入
0.01 * I正则项保证数值稳定; - 将
{mean, cov}分布参数与 backbone 权重一起以.pdparams保存。
推理时用马氏距离衡量测试特征与训练分布每个位置的偏离程度。正因网络不参与梯度更新,文档特别说明:执行 PaDiM/PatchCore 训练命令时log 中 loss 恒为 0 是正常现象。
1.2 数据集加载与数据增强
数据集读取逻辑在 contrib/QualityInspector/qinspector/uad/datasets/mvtec.py 中,MVTecDataset按train/test阶段扫描{class_name}/train与{class_name}/test下的所有缺陷子目录与good目录,对非good样本再关联ground_truth/{defect_type}/{name}_mask.png标签图。图片与标签使用相同管线处理:Resize(resize)→CenterCrop(cropsize)→ToTensor(),图片额外做 ImageNet 均值的Normalize(mean[0.485, 0.456, 0.406],std[0.229, 0.224, 0.225])。训练阶段只返回图片,测试/预测阶段返回(x, y, mask)三元组用于计算 AUROC 与可视化。
2. 数据集准备(MVTec AD 格式)
QualityInspector 的 UAD 工具以 MVTec AD 数据集为例。首先下载数据集并保存在QualityInspector/data中,目录结构如下:
data/mvtec_anomaly_detection/ | |--bottle # 某类产品 | |--ground_truth # 标签图 | |--broken_large # 某类缺陷标签图 | |--000_mask.png | |--001_mask.png | |--... | | |--broken_small # 某类缺陷标签图 | |--... | | |--contamination # 某类缺陷标签图 | |--... | |--test # 测试样本 | |--good # 正常样本测试图 | |--000.png | |--... | |--broken_large # 某类缺陷测试图 | |--000.png | |--... | |--broken_small # 某类缺陷测试图 | |--... | |--contamination # 某类缺陷测试图 | |--... | |--train # 训练样本 | |--good # 正常样本训练图 | |--000.png | |--... ...MVTec AD 数据包含结构和纹理类型的零件共计 15 类,其中训练集只包含 OK 图像,测试集包含 NG 和 OK 图像。从 contrib/QualityInspector/qinspector/uad/datasets/mvtec.py 可见 15 类的完整划分:
- 纹理类(textures):
carpet, grid, leather, tile, wood - 物体类(objects):
bottle, cable, capsule, hazelnut, metal_nut, pill, screw, toothbrush, transistor, zipper
如果希望使用自己的数据集,请组织成上述 MVTec AD 格式,将自定义数据集作为 MVTec AD 中的一个 category,即路径设置为QualityInspector/data/mvtec_anomaly_detection/{category}/...;标签文件为灰度图,缺陷部分像素值为 255。
3. 训练、评估、预测命令
以 PaDiM 模型为例,训练、评估、预测脚本存放在tools/uad/padim/目录下(PatchCore、STFPM 对应tools/uad/patchcore/、tools/uad/stfpm/)。通过--config参数传入对应模型 YML 配置文件,通过--category参数指定 MVTec AD 中的某个类别:
- 训练:
python tools/uad/padim/train.py --config ./configs/uad/padim/padim_resnet18_mvtec.yml --category bottle说明:由于 padim 和 patchcore 的网络不参与训练,执行上述命令时若 log 产生 loss 为 0 是正常现象。
- 评估:
python tools/uad/padim/val.py --config ./configs/uad/padim/padim_resnet18_mvtec.yml --category bottle- 预测:
python tools/uad/padim/predict.py --config ./configs/uad/padim/padim_resnet18_mvtec.yml --category bottle从 contrib/QualityInspector/tools/uad/padim/train.py 的 argparse 定义看,--category除单个类别外,还支持textures、objects、all三个聚合取值,分别批量处理纹理类、物体类或全部 15 类,并自动将逐类 Image_AUROC / Pixel_AUROC 结果写入{save_path}/{backbone}/{category}_seed{seed}.csv,最后输出 mean 平均行。因此若配置category: all,一条命令即可完成全数据集训练与评估。
3.1 各算法在 MVTec AD 上的实验结果
三个算法目录下的 README 记录了以 resnet18 为 backbone、在 MVTec AD 上的图像级与像素级 ROCAUC 指标:
PaDiM(resnet18)
| 指标 | Avg | Carpet | Grid | Leather | Tile | Wood | Bottle | Cable | Capsule | Hazelnut | Metal Nut | Pill | Screw | Toothbrush | Transistor | Zipper |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Image-level | 0.918 | 0.996 | 0.928 | 1.000 | 0.965 | 0.981 | 0.999 | 0.876 | 0.875 | 0.760 | 0.984 | 0.844 | 0.774 | 0.969 | 0.972 | 0.850 |
| Pixel-level | 0.962 | 0.990 | 0.944 | 0.987 | 0.894 | 0.931 | 0.979 | 0.949 | 0.980 | 0.970 | 0.963 | 0.923 | 0.975 | 0.985 | 0.974 | 0.981 |
PatchCore(resnet18)
| 指标 | Avg | Carpet | Grid | Leather | Tile | Wood | Bottle | Cable | Capsule | Hazelnut | Metal Nut | Pill | Screw | Toothbrush | Transistor | Zipper |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Image-level | 0.979 | 0.992 | 0.971 | 1.000 | 0.990 | 0.990 | 1.000 | 0.979 | 0.982 | 0.999 | 0.997 | 0.939 | 0.947 | 0.942 | 0.993 | 0.971 |
| Pixel-level | 0.978 | 0.991 | 0.978 | 0.999 | 0.937 | 0.942 | 0.982 | 0.985 | 0.989 | 0.988 | 0.984 | 0.976 | 0.994 | 0.991 | 0.957 | 0.987 |
| PRO_score | 0.932 | 0.961 | 0.923 | 0.971 | 0.848 | 0.893 | 0.947 | 0.943 | 0.937 | 0.935 | 0.939 | 0.928 | 0.971 | 0.918 | 0.910 | 0.957 |
STFPM(resnet18)
| 指标 | Avg | Carpet | Grid | Leather | Tile | Wood | Bottle | Cable | Capsule | Hazelnut | Metal Nut | Pill | Screw | Toothbrush | Transistor | Zipper |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Image-level | 0.948 | 0.988 | 0.994 | 1.000 | 0.988 | 0.994 | 0.979 | 0.929 | 0.979 | 1.000 | 0.978 | 0.816 | 0.850 | 0.875 | 0.896 | 0.956 |
| Pixel-level | 0.962 | 0.990 | 0.986 | 0.995 | 0.971 | 0.955 | 1.000 | 0.937 | 0.954 | 0.986 | 0.961 | 0.905 | 0.985 | 0.990 | 0.830 | 0.984 |
整体来看,PatchCore 的 Image-level 平均 ROCAUC 最高(0.979),STFPM 与 PaDiM 的像素级表现接近(均为 0.962),而 PatchCore 额外提供 PRO_score 指标(0.932)用于评价缺陷区域定位质量。
4. 配置文件解读
无监督异常检测(UAD)模型的参数可以通过YML 配置文件和命令行参数两种方式指定,如果 YML 文件与命令行同时指定同一个参数,命令行指定的优先级更高。这一优先级由 contrib/QualityInspector/qinspector/cvlib/uad_configs.py 中的ConfigParser实现(如--device、--category、--resize等均可覆盖 YML 默认值),便于不修改配置文件的临时实验。
4.1 PaDiM 配置(padim_resnet18_mvtec.yml)
配置文件位于 contrib/QualityInspector/configs/uad/padim/padim_resnet18_mvtec.yml,主要参数如下:
# common arguments device: gpu seed: 3 # 指定numpy, paddle的随机种子 # dataset arguments batch_size: 1 num_workers: 0 category: bottle # 指定MVTecAD数据集的某个类别 resize: [256, 256] # 指定读取图像的resize尺寸 crop_size: [224, 224] # 指定resize图像的crop尺寸 data_path: data/mvtec_anomaly_detection # 指定MVTecAD数据集的根目录 save_path: output/ # 指定训练时模型参数保存的路径和评估/预测时结果图片的保存路径 # train arguments do_eval: True # 指定训练后是否进行评估 backbone: resnet18 # 支持resnet18, resnet50, wide_resnet50_2 # val and predict arguments save_pic: True # 指定是否保存第一张评估图片/预测图片的结果 model_path: output/resnet18/bottle/bottle.pdparams # 指定加载模型参数的路径 # predict arguments img_path: data/mvtec_anomaly_detection/bottle/test/broken_large/000.png # 指定预测的图片路径 threshold: 0.5 # 指定预测后二值化异常分数图的阈值参数说明与源码对照:
seed:同时作用于random、numpy、paddle三个随机源(见train.py中random.seed / np.random.seed / paddle.seed),保证特征降维的随机通道选择等步骤可复现;resize与crop_size:分别对应MVTecDataset中的T.Resize与T.CenterCrop,PaDiM 默认 256 缩放到 224 中心裁剪,PatchCore 默认crop_size: [256, 256](即不裁剪);category:除单类别外,配置值支持textures、objects、all(见 contrib/QualityInspector/qinspector/uad/datasets/mvtec.py 的CLASS_NAMES划分),all时自动遍历全部 15 类并输出汇总 CSV;backbone:PaDiM/PatchCore 支持resnet18 / resnet50 / wide_resnet50_2(与padim.py中models字典一致),STFPM 支持resnet18 / resnet34 / resnet50 / resnet101;不同 backbone 的嵌入维度不同,train.py的fins表记录了各 backbone 的特征通道数(resnet18 为 448,resnet50 / wide_resnet50_2 为 1792);model_path:评估/预测时加载的权重路径,需与backbone、category、save_path组合保持一致,如 PaDiM 训练保存路径为output/{backbone}/{category}/{class_name}.pdparams(见train.py的save_name拼接逻辑),PatchCore 则保存为output/coreset_resnet18_10/bottle.pdparams形式;threshold:预测时对异常分数图做二值化的阈值,PaDiM/PatchCore 默认 0.5,STFPM 默认 0.01,具体取值应结合验证集 AUROC 曲线与缺陷率调节。
4.2 PatchCore 特有参数
contrib/QualityInspector/configs/uad/patchcore/patchcore_resnet18_mvtec.yml 在公共参数之外新增:
method: coreset # projection method, one of [sample, ortho, svd_ortho, gaussian, coreset] k: 10 # using feature channelsmethod:特征记忆池的构建/投影方式,可选sample / ortho / svd_ortho / gaussian / coreset,默认coreset(KNN Greedy CoreSet 采样,与论文一致),相关实现位于 contrib/QualityInspector/qinspector/uad/utils/k_center_greedy.py 与 contrib/QualityInspector/qinspector/uad/utils/random_projection.py;k:使用的特征通道数,默认 10,直接影响记忆池规模与推理开销。
4.3 STFPM 特有参数
contrib/QualityInspector/configs/uad/stfpm/stfpm_resnet18_mvtec.yml 是三个算法中唯一需要真实训练网络的配置,包含完整训练超参:
# train arguments epochs: 100 do_eval: True # After training, whether to eval model; backbone: resnet18 # Support resnet18, resnet34, resnet50, resnet101 lr: 0.4 momentum: 0.9 weight_decay: 1.0e-4 # val arguments compute_pro: Falselr: 0.4、momentum: 0.9、weight_decay: 1.0e-4:SGD 优化器参数,用于学生网络向冻结的教师网络逐尺度特征匹配学习;compute_pro:是否额外计算 PRO(Per-Region Overlap)指标,默认False,开启后评估耗时增加但可获得更全面的定位质量评估(PatchCore README 中已给出 PRO_score 参考值 0.932)。
5. 使用流程小结与注意事项
- 数据:按 MVTec AD 目录格式准备数据(训练集仅 OK 图,测试集含 OK/NG 图,
ground_truth为缺陷像素值为 255 的灰度图),放入QualityInspector/data/mvtec_anomaly_detection/; - 选型:对精度要求高且推理资源充足可选 PatchCore(Image-level 平均 ROCAUC 最高),追求更细粒度像素定位可关注 PaDiM/STFPM,需要可训练网络则选择 STFPM;
- 执行:分别调用
tools/uad/{padim|patchcore|stfpm}/{train|val|predict}.py,通过--config指定对应 YML、--category指定类别,命令行参数可覆盖 YML 中同名项; - 注意:PaDiM/PatchCore 训练日志中 loss 恒为 0 属正常现象(backbone 不参与训练,仅统计特征分布/构建记忆池);评估与预测前务必确认
model_path指向正确权重,STFPM 的阈值默认值(0.01)明显低于 PaDiM/PatchCore(0.5),按需基于验证集调整threshold以平衡误报与漏检。
6. 相关资源索引
- UAD 总览文档:contrib/QualityInspector/docs/uad/README.md
- 算法配置与结果:PaDiM README / 配置、PatchCore README / 配置、STFPM README / 配置
- 核心实现:padim.py、patchcore.py、stfpm.py、mvtec.py
- 工具脚本:tools/uad/padim/train.py、tools/uad/padim/val.py、tools/uad/padim/predict.py(PatchCore/STFPM 结构相同)
- 参数解析:contrib/QualityInspector/qinspector/cvlib/uad_configs.py
- 人工智能
- 计算机视觉
- 预训练
【免费下载链接】PaddleSeg
Easy-to-use image segmentation library with awesome pre-trained model zoo, supporting wide-range of practical tasks in Semantic Segmentation, Interactive Segmentation, Panoptic Segmentation, Image Matting, 3D Segmentation, etc.
相关推荐
如何用MLflow构建异常检测系统:从模型训练到生产部署的完整指南
如何用MLflow构建异常检测系统:从模型训练到生产部署的完整指南 MLflow是一个强大的机器学习工作流程开源平台,能够帮助数据科学家和工程师高效管理机器学习
MLOpsLLMOps人工智能大模型模型评测LLM 网关可观测性PaddleDetection 半监督检测监督基线完全指南:纯监督模型库、部分监督数据准备与训练评估实战
PaddleDetection 半监督检测监督基线完全指南:纯监督模型库、部分监督数据准备与训练评估实战 半监督检测(Semi Supervised Objec
人工智能深度学习计算机视觉Anomalib STFPM 模型详解:Student-Teacher 特征金字塔匹配的无监督异常检测实现
Anomalib STFPM 模型详解:Student Teacher 特征金字塔匹配的无监督异常检测实现 本文围绕 anomalib 仓库中 STFPM(St
人工智能计算机视觉深度学习模型评测
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考