Padim模型参数
- [1 模型原理](#1 模型原理)
-
- [1.1PaDiM 的核心"模型参数"组成](#1.1PaDiM 的核心“模型参数”组成)
- [2 超参数](#2 超参数)
-
- [2.1 骨干网络相关(Backbone-related)](#2.1 骨干网络相关(Backbone-related))
- [2.2 特征处理相关](#2.2 特征处理相关)
- [2.3 分布建模相关](#2.3 分布建模相关)
- [2.4 输入与预处理相关](#2.4 输入与预处理相关)
- [2.5 后处理与评估相关](#2.5 后处理与评估相关)
- [2.6 设置阈值](#2.6 设置阈值)
1 模型原理
1.1PaDiM 的核心"模型参数"组成
对于输入图像被划分为 H×WH×W 个空间位置(patches),PaDiM 为每个位置 (i,j)(i,j) 存储以下两个统计量:
-
均值向量(Mean Vector)
记作: μij∈RDμij∈RD
表示该位置在所有正常训练样本中提取的特征向量的平均值。
DD 是特征维度(例如使用 ResNet18 + 多层拼接后可能为 384 或 576,再经随机降维至如 100)。
-
协方差矩阵(Covariance Matrix)
记作: Σij∈RD×DΣij∈RD×D
描述该位置正常特征的波动范围和各维度间的相关性。
实际实现中常使用对角协方差(即只保存方差,忽略特征间相关性)以降低存储和计算开销,但原始论文使用全协方差。
python
padim_model = {
'means': np.array of shape (H, W, D), # μ
'covs': np.array of shape (H, W, D, D) or (H, W, D), # Σ
'backbone': 'resnet18', # 仅记录使用的骨干网络
'feature_layers': ['layer1', 'layer2', ...],
'reduction_dim': 100,
}
2 超参数
PaDiM(Patch Distribution Modeling)模型本身不包含可训练参数,其"模型参数"实际上是指在训练阶段从正常样本中统计得到的分布参数。这些参数用于推理时计算异常分数。
2.1 骨干网络相关(Backbone-related)
- backbone: 用于提取特征的预训练 CNN 网络 'resnet18', 'wide_resnet50_2'(最常用)
- feature_layers: 从哪些网络层提取特征(多尺度融合) 如 ['layer1', 'layer2', 'layer3'](ResNet 对应输出
2.2 特征处理相关
- embedding_dim 或 reduction_dim:特征降维后的维度(通过随机采样或投影) 100, 300, 500(原始拼接后维度可能达 1792,需降维)
- use_reducer:是否使用随机降维(Random Projection / Sampling) True / False
- interpolation:特征图上采样方法(对齐空间分辨率) 'bilinear', 'bicubic'。
2.3 分布建模相关
- covariance_type: 协方差矩阵形式 'full'(全协方差)或 'diag'(对角协方差)
- eps: 协方差矩阵正则化项(防止奇异) 1e-6 ~ 1e-3
3
2.4 输入与预处理相关
input_size 输入图像尺寸(需与 backbone 兼容) (256, 256), (512, 512)
normalize_mean/std 图像归一化参数(需匹配 backbone 预训练设置) ImageNet: [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]
2.5 后处理与评估相关
- anomaly_threshold 异常分数阈值(用于二值分割) 通过验证集设定(如 99% 分位数)
- postprocess 是否使用形态学操作(如开运算) True / False
2.6 设置阈值
- 阈值计算触发 src/anomalib/models/padim/lightning_model.py → on_validation_epoch_end
- 阈值计算逻辑 src/anomalib/models/components/base/anomaly_module.py
python
def _compute_metrics_and_update_best_score(self, outputs):
# 收集所有验证样本的 image-level scores
image_scores = torch.cat([output["image_score"] for output in outputs])
# 默认使用 99% 分位数作为阈值(可配置)
threshold = torch.quantile(image_scores, self.image_threshold.quantile)
# 保存到模型属性
self.image_threshold.value = threshold
- 阈值策略定义 src/anomalib/utils/metrics/threshold.py
该类支持多种阈值策略(如 F1AdaptiveThreshold, ManualThreshold, AnomalyScoreThreshold),而 PaDiM 默认使用 AnomalyScoreThreshold,即基于分位数的固定阈值。
anomalib/models/padim/config.yaml
yaml
metrics:
image:
threshold:
method: "adaptive" # 实际对应 AnomalyScoreThreshold
quantile: 0.99 # ← 关键!默认取 99% 分位数
- 默认配置 src/anomalib/models/padim/config.yaml
python
metrics:
image:
threshold:
quantile: 0.995 # 更严格
pixel:
threshold:
quantile: 0.99
- 训练后手动赋值
python
from anomalib.models import Padim
model = Padim.load_from_checkpoint("path/to/checkpoint.ckpt")
model.image_threshold.value = torch.tensor(5.0) # 手动设为 5.0
- 推理时应用 Padim.post_process() 方法
python
def post_process(
self,
anomaly_maps: Tensor,
pred_scores: Tensor | None = None,
) -> tuple[Tensor, Tensor]:
"""Post-process predictions to get binary masks using threshold."""
# 使用已学习的阈值
pred_mask = (anomaly_maps >= self.pixel_threshold.value).long()
pred_score = pred_scores if pred_scores is not None else anomaly_maps.amax(dim=(1, 2, 3))
pred_label = (pred_score >= self.image_threshold.value).long()
return pred_mask, pred_label