1. 基础知识
神经网络的前向传播和反向传播
前向传播(forward pass)指的是:按顺序(从输入层到输出层)计算和存储神经网络中每层的结果。
反向传播(backward propagation)指的是计算神经网络参数梯度的方法。
在卷积神经网络中,先理解前向传播中的卷积和池化。卷积是用卷积核在原始图像上遍历,对应元素相乘再求和,得到的新图像在尺寸上会有减小。可以通过下图直观的去理解。假设输入图像的有m行,n列,卷积核的尺寸为 filter_size×filter_size,输出图像的尺寸即为(m-filter_size+1)×(n-filter_size+1)
在卷积神经网络中,数据的格式主要是以张量(多维数组)的形式存储。图片的格式为一个三维张量,行×列×通道数。卷积核的格式为一个四维张量,卷积核数×行×列×通道数。
具体操作可根据下图理解,若原输入图片格式为(7×7×3)的张量,使用的卷积核为(2×3×3×3),则有两个卷积核,输入图像和每个卷积核都有三个通道。以卷积核w0为例,将图片的三个通道与卷积核的对应通道分别进行二维卷积操作,然后将三个通道得到的结果相加得到输出图像的一个通道。以此类推,对每个卷积核都进行操作后即可得到最终的输出。
可见输出最终是一个三维张量,输出通道数等于卷积核个数,输出的尺寸与输入每个通道二维卷积操作后得到的尺寸相同。
池化一般是对图片进行下采样,最大池化就是在图片中用每个区域的最大值代表这个区域,平均池化就是用每个区域平均值代表这个区域。
在反向传播中的卷积和池化。最大池化为例,如上图,红色区域只有最大值6对池化后的结果有影响,而其他位置对池化后的结果影响都为0。那么假设池化后的数字6处,有delta误差δ,那么反向传播后,红色区域的6处对应delta误差为δ,其他三个位置对应的delta误差为0。所以最大池化前向传播时,不仅要记录区域最大值,同时也要记录下来区域最大值的位置,方便反向传播。
而平均池化,每个值对结果的贡献都是池化区域大小的倒数,所以若池化后左上角区域的delta误差为δ,池化区域大小为4,则反向传播后,图像左上角的四个红色格子delta误差都为δ/4。
卷积的反向传播,以二维卷积为例,可以分为对输出求梯度与对卷积核求梯度。对输入求梯度,先将卷积结果的delta误差经过零填充扩展到与原输入尺寸一致,然后将卷积核旋转180°,最后将扩展的误差图和旋转后的卷积核做全卷积,则能得到对输入的反向传播梯度图。
若对卷积核反向传播,则需要输入数据X和卷积结果的delta误差图
∂
L
∂
X
\frac{\partial L}{\partial X}
∂X∂L, 若卷积核为K,则
∂
L
∂
K
[
i
,
j
]
=
∑
p
=
0
H
Y
−
1
∑
q
=
0
W
Y
−
1
(
∂
L
∂
Y
[
p
,
q
]
⋅
X
[
p
+
i
,
q
+
j
]
)
\frac{\partial L}{\partial K[i,j]} = \sum_{p=0}^{H_Y-1} \sum_{q=0}^{W_Y-1} \left( \frac{\partial L}{\partial Y[p,q]} \cdot X[p+i, q+j] \right)
∂K[i,j]∂L=∑p=0HY−1∑q=0WY−1(∂Y[p,q]∂L⋅X[p+i,q+j])
2. 数据集调研
根据缺陷类型,我在网上对公开数据集进行了一些调研。
2.1 Multi-light source illumination Dataset
Multi-light source illumination Dataset是目前符合毕设情景的数据集。
该数据集来源于论文Fusion of multi-light source illuminated images for effective defect inspection on highly reflective surfaces该论文构建了一个多光源照明/采集系统,捕获了不同照明方向下的高反射不锈钢工件 (USB连接器) 图像。
数据集包含700个样品(USB连接器)的多光源照明图像 (四张单光源照明图像和一张均匀照明图像) ,这些样品具有四种典型的表面缺陷,包括 BrightLine、Deformation、Scratch 和 Dent。收集的图像被拆分为比为 4:1 的训练数据集和测试数据集。更具体地说,训练数据集由 560个USB连接器的图像(总共 2800 张图像)组成,测试数据集包含新一批 240 个 USB 连接器的图像(总共 1200 张图像)。
该数据集没有使用文档,分类较为草率,只分为RenameNumber1和ReNameNumber 2两个文件夹
根据图像名称分析其结构如下,例:1_High_Down_A_UNOB_Deformation
其中 1 为样本编号,应该是不同样本的编号
其中High表示光源亮度强度,分为High 和 Low
其中Down表示光源方向,包括Down、Left、Right、Upper 和 Uniformity,对应下左右上和均匀光照
其中A指USB的正面,即带有孔洞的一面,B为USB背面
其中Deformation为缺陷类型,包括BrightLine(光明线)、Deformation(变形)、Scratch(划痕) 和 Dent(凹陷)四种
其中UNOB暂未弄清具体含义,数据集中还有UYOB分类。
数据集下载地址https://github.com/Xavierman/Fusion-of-multi-light-source-illuminated-images-for-defect-inspection
2.2 MVTec AD和MVTec 3D-AD
2.2.1 MVTec AD
官网下载
MVTec AD是用于无监督异常检测的综合真实世界数据集。MVTec AD全称为MVTec Anomaly Detection,是第一个全面的、多目标的、多缺陷的异常检测数据集,专注于现实世界的应用。
MVTec AD包含5354张不同对象和纹理类别的高分辨率彩色图像。它分为 15 个不同的对象和纹理类别。每个类别都包含一组无缺陷的训练图像和一组具有各种缺陷的测试图像以及没有缺陷的图像。此外,它还提供了像素级别的ground truth。
针对MVTec AD数据集的所有5种纹理和10种物体类别的示例图像如下所示。对于每个类别,最上面的一行显示一个无异常图像。中间行显示了一个异常的例子,在下行中,给出了一个突出异常区域的近距离视图。
该数据集结构规范,下载后结构如下
mvtec
|-- bottle
|-----|----- ground_truth
|-----|--------|------ broken_large
|-----|--------|------ broken_small
|-----|--------|------ contamination
|-----|----- test
|-----|--------|------ good
|-----|--------|------ broken_large
|-----|--------|------ broken_small
|-----|--------|------ contamination
|-----|----- train
|-----|--------|------ good
|-- cable
|-- ...
同时它也在Towards Total Recall in Industrial Anomaly Detection中被使用,用来测试patchcore异常检测方法。在搞清楚patchcore代码前可以先用该数据集练手,它的被测物体和缺陷种类较多,且结构清楚完整,可以用来训练对代码不同模块作用的理解。
2.2.2 MVTec 3D-AD
MVTec 3D-AD是第一个用于无监督异常检测和定位任务的全面的3D数据集。它使用高分辨率的工业3D传感器来获取10种不同物体类别的深度扫描。对于所有的物体类别,它提出了一个训练集和验证集,其中每个训练集仅由正常样本的扫描组成。对应的测试集包含各种缺陷的样本,如划痕、凹痕、孔洞、污染或变形。它也为每个异常测试样本提供精确的ground truth。
以MVTec 3D - AD数据集的全部10个数据集类别为例。对于每个类别,左列显示了一个正常样本点云,其上投影了RGB值。第二列展示了一个异常测试样本的特写视图。异常点以红色突出显示在第三列。
其数据集结构类似MVTec AD,如下所示
mvtec_3d_anomaly_detection
|-- bagel
|-----|----- calibration
|-----|----- validation
|-----|----- test
|-----|--------|------ combined
|-----|--------|------ contamination
|-----|--------|------ crack
|-----|--------|------ hole
|-----|--------|------ good
|-----|----- train
|-----|--------|------ good
|-- cable_gland
|-- ...
MVTec 3D-AD与MVTec AD的主要差别在于它在RGB图像的基础上,增加了深度数据和点云数据,支持三维数据的缺陷检测。它适用于多模态数据融合和几何形状异常检测。暂时不适合用来训练毕设项目。
在仔细了解该数据集的结构以后,我觉得这种结构清晰条理,也容易看懂,若实验室自己采集相应图像构成数据集,我认为可以仿照此结构,方便自己使用,也便于之后实验室来新人后用来学习。
2.3 NEU-DET钢材表面缺陷数据集
该数据集由东北大学宋克臣团队制作,专注于钢材表面缺陷的检测与识别。数据集包含了1800张图片,涵盖了六种常见的钢材表面缺陷类型,分别是:
Crazing(裂纹)
Inclusion(夹杂物)
Patches(斑点)
Pitted Surface(麻面)
Rolled-in Scale(轧入氧化皮)
Scratches(划痕)
其数据集结构如下
NEU-DET
|-- train
|-----|----- images
|-----|--------|------ crazing_6.jpg
|-----|--------|------ ···
|-----|----- labels
|-----|--------|------ crazing_6.txt
|-----|--------|------ ···
|-- valid
|-----|----- images
|-----|--------|------ crazing_1.jpg
|-----|--------|------ ···
|-----|----- labels
|-----|--------|------ crazing_1.txt
|-----|--------|------ ···
该数据集所有图片样式均为.jpg格式,适用于计算机视觉任务,同时每张图片都配备有.txt格式的标签文件,描述图片中的缺陷类型和位置信息。数据集下载地址:https://gitcode.com/open-source-toolkit/fa031/overview
2.4 Magnetic-tiledefect-datasets
该数据集是中国科学院自动所一个课题组收集的数据集,是“Saliency of magnetic tile surface defects”这篇论文的数据集。数据集中包含1344张图片,收集了6种常见磁瓦缺陷的图像,包括
Blowhole(气孔)
Crack(裂纹)
Fray(磨损)
Break(破损)
Uneven(磨削过程造成的不均匀)
Free(无缺陷样本)
其中所有样本都带有像素级缺陷标注
其数据集结构如下
Magnetic-tile-defect-datasets.-master
|-- MT_Blowhole
|-----|----- imgs
|-- MT_Break
|-----|----- imgs
|-- MT_Crack
|-----|----- imgs
|-- MT_Fray
|-----|----- imgs
|-- MT_Free
|-----|----- imgs
|-- MT_Uneven
|-----|----- imgs
磁性瓷砖表面通常带有规则但复杂的纹理,这些纹理可能会对缺陷检测模型造成干扰,有助于研究模型在去噪和特征提取中的鲁棒性。该数据集之后可以用于测试各种深度学习模型(如 U-Net、Faster R-CNN)在工业表面缺陷检测中的性能,用于后续选择可替换模型时使用。下载:https://github.com/abin24/Magnetic-tile-defect-datasets.
2.5 铝型材表面瑕疵识别数据集
该数据集是[飞粤云端2018]广东工业智造大数据创新大赛—智能算法赛的竞赛用数据集,包含
训练集:初赛训练集包括1228条有瑕疵的标注图片(train1: 250张, train2: 978张)和1018条无瑕疵的图片。
测试集A:包含440条测试数据。
测试集B:包含1,000条测试数据。
同时附有瑕疵类型说明,能够快速认识各种缺陷类型。同时使用铝型材作为被测对象,图片清晰,贴近工业场景,适用于金属表面缺陷检测的测试,可在缺陷检测的练习中使用。
下载:https://tianchi.aliyun.com/dataset/140666
3. patchcore代码分析
在patchcore.backbones中,作者提供了常见的深度学习模型,比如 ResNet、VGG、EfficientNet 和 Vision Transformer (ViT) 系列。它依赖 torchvision 和 timm库,主要用来加载预训练的深度学习模型,方便用户通过指定模型的名称快速获取对应的模型实例。模块中定义了_BACKBONES字典和load(name) 函数。
以调用resnet50为例
model = load("resnet50")
'''
执行过程为
_BACKBONES["resnet50"] # 返回 "models.resnet50(pretrained=True)"
eval("models.resnet50(pretrained=True)") # 执行这行代码,加载模型
'''
patchcore.metrics用来计算图像级别和像素级别的异常检测性能指标,主要目的是评估模型的检测效果。它包括两部分:图像级别的检索指标计算和像素级别的检索指标计算。
函数compute_imagewise_retrieval_metrics用来计算图像级检测指标,包括AUROC、FPR(假阳性率)、TPR(真阳性率)。模块导入sklearn中的metrics,通过metrics.roc_curve和metrics.roc_auc_score获得评价指标。
fpr, tpr, thresholds = metrics.roc_curve(
anomaly_ground_truth_labels, anomaly_prediction_weights
)
auroc = metrics.roc_auc_score(
anomaly_ground_truth_labels, anomaly_prediction_weights
)
其中thresholds指不同阈值,它将得分进行二值化,用来计算对应的 FPR 和 TPR 值。
函数compute_pixelwise_retrieval_metrics用来计算像素级检测指标,包括AUROC、FPR、TPR、精确率(Precision)、召回率(Recall)、F1得分,以及最佳阈值和对应的假阳性率与假阴性率。函数先用
flat_anomaly_segmentations = anomaly_segmentations.ravel()
flat_ground_truth_masks = ground_truth_masks.ravel()
将分割结果和真实标签展开成一维向量,用于逐像素计算指标。然后仍使用metrics.roc_curve、metrics.roc_auc_score和metrics.precision_recall_curve用于计算ROC,AUROC和准确率,召回率。根据精确率与召回率,计算F1-Score
F1_scores = np.divide(
2 * precision * recall,
precision + recall,
out=np.zeros_like(precision),
where=(precision + recall) != 0,
)
找到F1得分最高的阈值作为最佳阈值。最后根据最佳阈值,将预测得分转换为二值化结果(正常/异常),计算假阳性率(FPR)和假阴性率(FNR)。最终返回的是一个包含auroc,fpr,tpr,optimal_threshold,optimal_fpr,optimal_fnr的词典。
predictions = (flat_anomaly_segmentations >= optimal_threshold).astype(int)
fpr_optim = np.mean(predictions > flat_ground_truth_masks)
fnr_optim = np.mean(predictions < flat_ground_truth_masks)
patchcore.common模块,主要使用深度学习进行特征提取和最近邻搜索。
FaissNN类中,允许切换CPU和GPU使用,核心功能包含fit、run、_create_index
fit使用输入特征创建 FAISS 索引。run 查询最近邻,返回最近邻搜索的距离和指标。_create_index创建对应的 FAISS 索引对象(L2 平方距离)。
ApproximateFaissNN类继承自 FaissNN,FaissNN中创建的是一个基于 L2 距离 的IndexFlatL2 索引,在ApproximateFaissNN中创建了一个基于IVFPQ的索引,两者都是用于最近邻检索,不过IndexFlatL2是暴力搜索所有样本点,不需要训练,适合小样本且精确的场景,而IVFPQ舍弃一定精度换取了更快的速度,且需要训练聚类,更适合大规模样本处理。
特征处理与合并定义三个类:_BaseMerger, AverageMerger, ConcatMerger,其中_BaseMerger为父类,AverageMerger, ConcatMerger分别继承于它,并定义了特征降维方法。AverageMerger将特征矩阵的最后两个维度先展成一维,然后通过平均值缩减,使NxCxWxH -> NxC;ConcatMerger将特征矩阵的后三个维度展成一维,使NxCxWxH -> NxCWH。