Registration based Few-Shot Anomaly Detection
一、先验知识
1.小样本(Few-shot)
小样本即样本数较少,数据量不多。小样本学习是希望模型可以自己学会如何去学习知识。
小样本的一些术语有:
- support set:指少量样本组成的集合。
- query:需要预测的样本。
- n-shot:support set中类别数量
- k-way:每个类的样本数量
小样本学习中有三个典型的模型:孪生网络、匹配网络、原型网络。
其中孪生神经网络的主要思想为:利用相同样本对和不同样本对之间的区别,训练出一个神经网络模型,使同类样本生成的embedding向量相近,不同样本的embedding向量远离。
2.STN
STN可以参考我之前写的一篇文章:单应性矩阵+Spatial Transformer Networks论文阅读笔记
简单的说就是STN可以通过网络训练出单应性矩阵并利用单应性矩阵对输入图像进行变换。
3.异常检测
关于异常检测这个PPT讲的比较详细:第9课
举一个异常检测的例子,数据集如下图:
常见的图片级别异常检测方法主要有:
- 密度估计方法
- 单分类方法
- 图片重构
- 自监督分类
密度估计方法: 先估计正常图片或特征的概率分布,然后根据概率分布检测图片是否满足分布,不满足的图片为异常。
典型分类
- 参数估计:高斯模型、高斯混合模型
- 非参数估计:最近邻估计、核密度估计
- 深度生成方法:GAN、VAE
高斯密度估计实现异常检测(参考文献16)主要步骤:
1.选取参与概率计算的特征值,必要时进行处理
2.对于每个特征值,计算均值和方差,进而计算出每个特征值的概率公式P(x)
3.对于一个给定的样本x’,计算P(x’),根据P(x’)与设定阈值之间的关系判定是否为异常。
为什么不能用二分类来解决这个问题?(参考文献4)
4、Pretext tasks和高斯滤波器
Pretext tasks:
1.这种训练不是我们本身的训练任务,并不是本身这次训练需要做的事情。
2.虽然不是这次训练需要做的事情,但是他可以促进我们的训练,达到更好的效
果。
高斯滤波器:
高斯滤波器是一种线性滤波器,能够有效的抑制噪声,平滑图像。其作用原理和均值滤波器类似,都是取滤波器窗口内的像素的均值作为输出。其窗口模板的系数和均值滤波器不同,均值滤波器的模板系数都是相同的为1;而高斯滤波器的模板系数,则随着距离模板中心的增大而系数减小。所以,高斯滤波器相比于均值滤波器对图像个模糊程度较小。
高斯滤波器可以看为一个固定卷积核的卷积操作。
5.SimSiam
该结构是何大神提出的用来解决“崩溃解”问题,同时他使用了对称损失函数和stop-grad来提高模型性能。
所谓崩塌,也就是模型为了偷懒,无论什么图片都会输出同样表示,这样结果 loss 很小,然后却没学到任何东西。
模型伪代码如下
在y.backward()时,如果y是标量,则不需要为backward()传入任何参数;否则,需要传入一个与y同形的Tensor。
如果不想要被继续追踪,可以调用.detach()将其从追踪记录中分离出来,这样就可以防止将来的计算被追踪,这样梯度就传不过去了。还可以用with torch.no_grad()将不想被追踪的操作代码块包裹起来,这种方法在评估模型的时候很常用,因为在评估模型时,我们并不需要计算可训练参数(requires_grad=True)的梯度。
6.图像配准
关于图像配准可以看一下我写的一篇文章:后续写完放链接。
关于本篇文章中用到的图像配准,我觉得和VoxelMorph配准实例结构差不多,该结构是直接将整幅图像放入进行配准,流程图如下:
输入的浮动图像和固定图像在通道(channel)的维度上进行拼接,首先通过仿射配准网络进行仿射配准,然后通过卷积神经网络(通常是类似UNet的编码器-解码器网络)进行 将浮动图像预测为固定图像的位移场,然后根据位移场得到采样网格,并使用空间变换网络(STN)对浮动图像使用采样网格进行重采样以获得配准。 发布图片。
代码如下:VoxelMorph 教程.ipynb
二、论文内容
1.摘要
本文考虑了少镜头异常检测(FSAD),这是一种实用但研究不足的异常检测(AD)设置,其中在训练时仅为每个类别提供有限数量的正常图像。到目前为止,现有的FSAD研究遵循用于标准AD的每类学习范式的一个模型,并且尚未探索类别间的共性。受人类如何检测异常(即将有问题的图像与正常图像进行比较)的启发,我们在这里利用配准,这是一种在类别间具有普遍性的图像对齐任务,作为代理任务,来训练一种类别无关的异常检测模型。在测试过程中,通过比较测试图像及其相应支持(正常)图像的注册特征来识别异常。据我们所知,这是第一个FSAD方法,它训练单个可泛化模型,不需要对新类别进行重新训练或参数微调。实验结果表明,在MVTec和MPDD基准上,提出的方法在AUC方面比最先进的FSAD方法优越3%-8%。
2.配准结构
我觉得这个流程图特别像递归三个VoxelMorph配准网络+SiaSim,引入SiaSim的目的作者在文中写的是防止发生崩溃解。
损失函数如下,该损失函数使用的和SiaSim的损失函数一样,作者解释的是从特征角度出发而不是从像素角度出发。p和z是提取出来的特征。
E 和 P的结构我这里就不画了,直接贴一下Pytroch源码,代码写的比较简单。
def conv3x3(in_planes: int, out_planes: int, stride: int = 1, groups: int = 1, dilation: int = 1) -> nn.Conv2d:
"""3x3 convolution with padding"""
return nn.Conv2d(
in_planes,
out_planes,
kernel_size=3,
stride=stride,
padding=dilation,
groups=groups,
bias=False,
dilation=dilation,
)
def conv1x1(in_planes: int, out_planes: int, stride: int = 1) -> nn.Conv2d:
"""1x1 convolution"""
return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
class Encoder(nn.Module):
def __init__(self):
super(Encoder, self).__init__()
self.conv1 = conv1x1(in_planes=256, out_planes=256)
self.bn1 = nn.BatchNorm2d(256)
self.relu1 = nn.ReLU()
self.conv2 = conv1x1(in_planes=256, out_planes=256)
self.bn2 = nn.BatchNorm2d(256)
self.relu2 = nn.ReLU()
self.conv3 = conv1x1(in_planes=256, out_planes=256)
self.bn3 = nn.BatchNorm2d(256)
self.relu3 = nn.ReLU()
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu1(x)
x = self.conv2(x)
x = self.bn2(x)
x = self.relu2(x)
out = self.conv3(x)
# out = self.relu3(x)
return out
class Predictor(nn.Module):
def __init__(self):
super(Predictor, self).__init__()
self.conv1 = conv1x1(in_planes=256, out_planes=256)
self.bn1 = nn.BatchNorm2d(256)
self.relu1 = nn.ReLU()
self.conv2 = conv1x1(in_planes=256, out_planes=256)
self.relu2 = nn.ReLU()
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu1(x)
out = self.conv2(x)
# out = self.relu2(x)
return out
3.训练过程
训练过程中,作者提出了一个创新点即将多种类别的图片输入进去进行混合训练,每次训练随机选取某个类别中的图像对。
训练数据集均为normal样本
4.测试过程
测试过程分为两步,因为作者要希望模型能够预测其它类别的异常,即训练得到的模型不需要微调等操作直接可以拿来使用预测出新的类别的高斯分布,故第一步需要把新的类别的normal数据集输入训练好的模型得到特征值,计算均值和方差得到新类别的高斯分布。第二步则需要输入新类别的测试数据图片,然后利用一定的度量手段来度量该数据输入进网络得到特征图是否满足新类别的高斯分布。
在测试时,作者对新类别的数据进行了数据增强。
这里便涉及两个问题:1.模型得到的特征值是啥?2.如何度量。
模型得到的特征值
论文中写的是合并三个STN模块输出的特征得到的特征值。注意,因为该特征需要保留原图像的空间信息,所以STN模块输出的特征图需要进行一个逆仿射变换,这样便可以检测出异常像素所在位置。
如何度量:
论文中写的是利用如下公式进行度量,fij是测试图片通过训练好模型得到的特征,均值和方差是测试过程计算得到的均值和方差。经过计算便可以得到对应测试图片每一个像素点的异常分数值,这张地图上的高分表示异常区域。整个图像的最终异常得分是异常图最大值。
三、实验结果
数据集——MVTec和MPDD
对比实验
我们考虑了两种最先进的FSAD方法,TDG[36]和DiffNet[29]。这两种方法都是针对每个类别分别训练模型(设置(ii))。使用官方源代码复制结果。
考虑到我们的方法使用来自多个类别的数据,为了公平比较,我们将它们扩展为利用相同数量的数据(设置(i))。
这些方法中添加了一个预训练程序,其中来自多个类别的数据用于预训练TDG的转换分类器或初始化DiffNet的基于归一化流的估计器。相应的方法是TDG+和DiffNet+。我们还评估了个体训练设置下的RegAD,并将相应的方法表示为RegAD-L。我们比较了一些最先进的普通AD方法,如GANomaly[1]、ARNet[42]、MKD[33]、CutPaste[21]、FYD[45]、PaDiM[8]、PatchCore[28]和CflowAD[14]。这些方法使用整个正常数据集进行训练,因此可以将其视为FSAD性能的上限。
消融实验
T-SNE 的可视化也显示出,基于配准的训练可以使得同类别的正常图像特征变得更加紧凑,从而有利于异常数据的检出。
参考文献
1.什么是pretext tasks?
2.few-shot learning/one-shot learning 小样本/零样本学习 学习笔记(持续更新)
3.异常检测(anomaly detection)
4.【入门】异常检测Anomaly Detection
5.ECCV 2022 Oral | 无需微调即可推广,上交大、上海人工智能实验室等提出基于配准的少样本异常检测框架
6.CV实践教程|生产线上的异常检测
7.Feature Embedding
8.详细解读Spatial Transformer Networks(STN)-一篇文章让你完全理解STN了
9.单应性Homograph估计:从传统算法到深度学习
10.图像处理基础(4):高斯滤波器详解
11.基于深度学习的单模医学图像配准综述(附 VoxelMorph 配准实例和代码)
12.Few-Shot Learning (FSL): 小样本学习简介及其应用
13.小样本学习Few-Shot Learning——孪生网络Siamese Networks、匹配网络Matching Networks、原型网络Prototypical Networks 的简单总结
14.探索孪生神经网络:请停止你的梯度传递!
15.Pytorch学习笔记-梯度与反向传播
16.机器学习(二十一) ——高斯密度估计实现异常检测
17.少样本 N-way K-shot