前言
经papers with code网站统计,在MVTec数据集上排名为第五(截止博文发出时间)。
做flow网络的异常检测论文时,可以看看NICE/RealNVP/Glow论文,有帮助的。
模型原理
思想:特征块x输入flow模型拟合成高斯分布与狄拉克分布乘积形式的分布z,z的大小与x完全一致,z中每个像素位置的值与x中每个像素位置的值一一对应,这样将未知的分布x转化为已知的分布z。通过这种分布的似然概率求法来更新网络,并做评价指标。
生成模型还有训练完往回生成图片的功能,这只利用前半部分思想。
架构
整个flow块对应代码及结构如下图所示。
main.py-->train(train_loader,test_loader,i)-->model = get_cs_flow_model()-->def get cs_flow_model(input_dim=c.n_feat)
def get_cs_flow_model(input_dim=c.n_feat):
nodes = list()
nodes.append(InputNode(input_dim, c.map_size[0], c.map_size[1], name='input'))
nodes.append(InputNode(input_dim, c.map_size[0] // 2, c.map_size[1] // 2, name='input2'))
nodes.append(InputNode(input_dim, c.map_size[0] // 4, c.map_size[1] // 4, name='input3'))
#构建4个流块
for k in range(c.n_coupling_blocks):
if k == 0:
node_to_permute = [nodes[-3].out0, nodes[-2].out0, nodes[-1].out0]
else:
node_to_permute = [nodes[-1].out0, nodes[-1].out1, nodes[-1].out2]
#将nodes块的前三个InputNode块由顺序块改为并列块,并列输出
nodes.append(Node(node_to_permute, ParallelPermute, {'seed': k}, name=F'permute_{k}'))
#out0/out1/out2见Node类里的exec函数,为OutputNode输出做区分
nodes.append(Node([nodes[-1].out0, nodes[-1].out1, nodes[-1].out2], parallel_glow_coupling_layer,
{'clamp': c.clamp, 'F_class': CrossConvolutions,
'F_args': {'channels_hidden': c.fc_internal,
'kernel_size': c.kernel_sizes[k], 'block_no': k}},
name=F'fc1_{k}'))
nodes.append(OutputNode([nodes[-1].out0], name='output_end0'))
nodes.append(OutputNode([nodes[-2].out1], name='output_end1'))
nodes.append(OutputNode([nodes[-3].out2], name='output_end2'))
nf = ReversibleGraphNet(nodes, n_jac=3)
return nf
fixed random channel permutation
ParallelPermute
对进入的三个特征块,使用np.random.permutation随机打乱通道,使用seed后,整个网络在不同epoch训练时,所有flow块的随机排列与其他epoch里的所有flow块的随机排列一致(但在1个epoch中训练时,不同flow块的随机排列是不同的)。
even channel split-->cross-scale convolutions-->channel concat
parallel_glow_coupling_layer
将特征块按维度分成两份记为A/B,A完成下图操作后与B进行下面公式形成C,B完成上图操作后与A进行下面公式形成D,C/D在维度层面结合形成与输入特征张量相同的大小的张量。
不过源码中未看到体量系数。
CrossConvolutions
损失函数
原论文中损失函数如下:
上式可对比看似然估计的求法(如下),可参考链接
细水长flow之NICE:流模型的基本概念与实现_PaperWeekly的博客-CSDN博客
原论文将似然估计左项删除,通过负号将最大化似然估计改为最小化,以进行训练目的。神经网络是函数拟合器,这样,降低这个损失函数的值就可将计算得到z的函数回归成最能拟合分布的函数。
源码体现按这个顺序找到:
main.py-->train(train_loader,test_loader,i)-->loss = get_loss(z, jac)
文中提到将梯度的2范数设置为1体现在:
norm = torch.nn.utils.clip_grad_norm_(model.parameters(),c.max_grad_norm)
评价指标
分类:
利用损失函数,由上,损失函数的数值主要体现在第一项,那么便将第一项中所有像素值(平方和乘1/2后的)求均值作为评价参考。
分割:
假设输出的张量[10,304,24,24],值平方后在张量的维度处求平均再➗304得张量[10,24,24],再取第一张未缩小的原图,再上采样得分数图。
除304没搞懂什么意思-_-
实验
对比:MVTec数据集/MT数据集图片级AUC比较。
消融:是否使用三个特征图,是否联合,是否交叉,是否加权联合/flow块的个数。