异常检测(无监督,生成模型)—SimpleNet: A Simple Network for Image Anomaly Detection and Localization

论文:https://arxiv.org/pdf/2303.15140v2.pdf

代码:GitHub - DonaldRR/SimpleNet

异常检测与定位就是在每个像素点进行二分类,0为正常,1为异常 

 网络四大模块:

1.一个预训练(在imageNet上预训练)的特征提取器,生成本地特征

        使用在imageNet上预训练的Resnet来提取特征,此主干一直被冻结,不进行训练

        可以使用从网络中某几层抽取特征,比如从Resnet50的block3,block4抽取特征,抽取的这两层特征大小不一样,但可以将特征进行裁剪,然后拼接

2.一个浅层特征适配器,将本地特征转移到目标域

        代码中使用的是线性层(Projection)映射,将提取出来的特征进行线性映射,使特征转移到目标域。

3.一个简单的异常特征生成器,通过向正常特征添加高斯噪声来伪造异常特征

4.一个二分类异常鉴别器,将异常特征与正常特征区分开来。

此算法优点:

1、不用在目标领域预训练backbone,而是建议使用一个特征适配器(线性层(Projection)映射)来产生面向目标的特征,以减少领域偏差。(liner+BN+LeakyReLU)

2、通过向正常特征添加高斯噪声来伪造异常特征, 在特征空间中合成异常,而不是直接在图像上合成。也就是说训练阶段只使用正常样本,通过高斯噪声产生异常,解决了异常样本不足的问题。

        测试阶段将正常,异常样本一块喂进网络去判断。


代码阅读:(main.py文件中主要为数据集加载,网络结构参数,主要阅读simplenet.py中的train方法)

将图片输入到backbone中,提取出backbone中某一层[参数layers_to_extract_from]的特征,参数中可以是某两层。比如提取出特征如下:
# torch.Size([8, 512, 36, 36])  , torch.Size([8, 1024, 18, 18])(从backbone中某两层提取的)

提取出特征之后将特征切成小片(PatchMaker类实现)特征如下
#torch.Size([8, 1296, 512, 3, 3]),  torch.Size([8, 324, 1024, 3, 3])
分别对应切片大小[36, 36], [18, 18]
变化过程:x: [ bs , c , w ,h]   -> [ bs * w//patchsize * h//patchsize ,c, patchsize, patchsize]


将这些小片特征经过一系列变换,然后将他们堆叠起来(self.forward_modules["preprocessing"])
然后采用池化self.forward_modules["preadapt_aggregator"],池化后的最大值拼接起来形成二维特征,此使特征形状为[bs,n],但是好像代码中是[bs*k,m],


然后将此特征通过全连接层(Projection)(注: pre_proj参数大于0时才有此全连接层,此全连接层的参数要在训练集上训练),此特征记为true_feat

注意:是先将网络输出的特征进行特征映射(Projection,线性层),再去生成噪声合成异常特征

训练Discriminator: 
Discriminator为几个liner+BN+Relu的组合,再加一个输出为一层的线性层
生成和此特征true_feat同样shape的噪声noise,则缺陷特征false_feat = true_feat+noise
将true_feat与false_feat特征拼接cat,送进Discriminator去训练,与真实标签求loss,然后反向传播更新参数

网络预测:
Discriminator输出的特征比如为(10368, 1),其中10368为 bs*图片像素值,根据此tensor按照不同的规则分别生成图像层级的异常置信度scores,与像素层次的异常置信度mask
因此scores 与mask的最优阈值不一样,可视化时要注意

可视化代码参考论文——PaDiM: a Patch Distribution Modeling Framework for Anomaly Detection and Localization

论文:https://arxiv.org/pdf/2011.08785v1.pdf

代码:https://github.com/xiahaifeng1995/PaDiM-Anomaly-Detection-Localization-master 

(main.py中的plot_pig函数,224行) 

  • 6
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 38
    评论
好的,这是一个使用 PyTorch 实现的示例代码,其中包括两个神经网络模型来解决椭圆形界面问题: ```python import torch from torch import nn, optim from torch.utils.data import DataLoader, Dataset import numpy as np import matplotlib.pyplot as plt # 定义一个椭圆形界面的数据集 class EllipseDataset(Dataset): def __init__(self, num_samples=1000, noise=0.05): super().__init__() self.num_samples = num_samples self.noise = noise # 生成随机的椭圆的参数 self.a = np.random.uniform(0.5, 1.5) self.b = np.random.uniform(0.5, 1.5) self.theta = np.random.uniform(0, 2*np.pi) self.center = np.random.uniform(-1, 1, size=2) # 生成随机的样本点 x = np.random.uniform(-2, 2, size=(self.num_samples, 2)) y = ((x[:, 0] - self.center[0]) * np.cos(self.theta) + (x[:, 1] - self.center[1]) * np.sin(self.theta)) ** 2 / self.a ** 2 + ((x[:, 0] - self.center[0]) * np.sin(self.theta) - (x[:, 1] - self.center[1]) * np.cos(self.theta)) ** 2 / self.b ** 2 y += np.random.normal(scale=self.noise, size=y.shape) self.data = torch.from_numpy(np.hstack([x, y.reshape(-1, 1)])).float() def __getitem__(self, index): return self.data[index] def __len__(self): return self.num_samples # 定义一个简单的全连接神经网络模型 class SimpleNet(nn.Module): def __init__(self): super().__init__() self.fc1 = nn.Linear(2, 64) self.fc2 = nn.Linear(64, 32) self.fc3 = nn.Linear(32, 1) def forward(self, x): x = nn.functional.relu(self.fc1(x)) x = nn.functional.relu(self.fc2(x)) x = self.fc3(x) return x # 定义一个深度神经网络模型 class DeepNet(nn.Module): def __init__(self): super().__init__() self.fc1 = nn.Linear(2, 64) self.fc2 = nn.Linear(64, 64) self.fc3 = nn.Linear(64, 64) self.fc4 = nn.Linear(64, 1) def forward(self, x): x = nn.functional.relu(self.fc1(x)) x = nn.functional.relu(self.fc2(x)) x = nn.functional.relu(self.fc3(x)) x = self.fc4(x) return x # 训练模型 def train(model, train_loader, criterion, optimizer, num_epochs=100): losses = [] for epoch in range(num_epochs): epoch_loss = 0 for batch in train_loader: optimizer.zero_grad() output = model(batch[:, :2]) loss = criterion(output, batch[:, 2:]) loss.backward() optimizer.step() epoch_loss += loss.item() epoch_loss /= len(train_loader) losses.append(epoch_loss) print(f"Epoch {epoch+1}/{num_epochs}, Loss: {epoch_loss}") return losses # 生成数据集 train_dataset = EllipseDataset(num_samples=1000, noise=0.05) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) # 定义模型和优化器 simple_net = SimpleNet() deep_net = DeepNet() criterion = nn.MSELoss() simple_optimizer = optim.Adam(simple_net.parameters(), lr=0.01) deep_optimizer = optim.Adam(deep_net.parameters(), lr=0.01) # 训练简单的全连接神经网络模型 simple_losses = train(simple_net, train_loader, criterion, simple_optimizer, num_epochs=50) # 训练深度神经网络模型 deep_losses = train(deep_net, train_loader, criterion, deep_optimizer, num_epochs=50) # 画出损失函数曲线 plt.plot(simple_losses, label="Simple Net") plt.plot(deep_losses, label="Deep Net") plt.legend() plt.xlabel("Epoch") plt.ylabel("Loss") plt.show() # 画出椭圆形界面和模型预测的分割线 x = np.linspace(-2, 2, num=100) y = np.linspace(-2, 2, num=100) xx, yy = np.meshgrid(x, y) z_simple = simple_net(torch.from_numpy(np.hstack([xx.reshape(-1, 1), yy.reshape(-1, 1)])).float()).detach().numpy().reshape(xx.shape) z_deep = deep_net(torch.from_numpy(np.hstack([xx.reshape(-1, 1), yy.reshape(-1, 1)])).float()).detach().numpy().reshape(xx.shape) fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10, 5)) ax1.contourf(xx, yy, (xx - train_dataset.center[0])**2 / train_dataset.a**2 + (yy - train_dataset.center[1])**2 / train_dataset.b**2, levels=20, cmap=plt.cm.Blues) ax1.set_title("Ellipse") ax2.contourf(xx, yy, z_simple, levels=20, cmap=plt.cm.Blues) ax2.set_title("Simple Net") fig.tight_layout() plt.show() fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10, 5)) ax1.contourf(xx, yy, (xx - train_dataset.center[0])**2 / train_dataset.a**2 + (yy - train_dataset.center[1])**2 / train_dataset.b**2, levels=20, cmap=plt.cm.Blues) ax1.set_title("Ellipse") ax2.contourf(xx, yy, z_deep, levels=20, cmap=plt.cm.Blues) ax2.set_title("Deep Net") fig.tight_layout() plt.show() ``` 在这个示例代码中,我们定义了一个 `EllipseDataset` 类来生成一个随机的椭圆形界面数据集。我们还定义了两个神经网络模型,一个是简单的全连接神经网络模型,另一个是深度神经网络模型。我们使用均方误差作为损失函数,使用 Adam 优化器进行优化。 我们首先训练了简单的全连接神经网络模型,然后训练了深度神经网络模型。在训练过程中,我们记录了每个 epoch 的损失函数值,最后画出损失函数曲线。最后,我们将椭圆形界面和两个模型预测的分割线画出来,以便比较它们的效果。 请注意,这个示例代码只是一个简单的示例,用于演示如何使用 PyTorch 实现解决椭圆形界面问题的神经网络模型。您可以根据您的实际需求进行修改和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值