如上图所示,人类可以根据同一幅图像回答不同问题,及可以从不同的角度来分析同一个目标。
但是在训练卷积神经网络CNN时,只是给予了一个角度,如只是做检测或者识别等,也就是说针对某一个任务得到的CNN特征很难适用于其他问题(训练的检测任务,做识别就不可以)。
作者认为造成上述问题的主要原因是:
模型只取得了神经元特征(即只是获取了卷积核的参数信息),但是丢弃了隐式知识的学习运用;而对于人脑而言,隐式知识对分析各种各样的任务是非常有用的,那么什么是隐式知识呢?在神经网络中隐式知识又是什么呢?
(1)隐式知识与显式知识
在神经网络中,字面意思中,浅层特征定义为显示知识,深层特征定义为隐式知识;本文将直接可观察的知识定义为显式知识,隐藏在神经网络中无法观察的知识定义为隐式知识。
期间读论文真是读的头都大了,因为论文的风格以及绘制的图片与以往所读的有很大的不同,读起来云里雾里,概括最后一句话:YOLOR引入了隐性知识,该隐性知识可以是向量、矩阵等,感觉有点注意力的意思,但是论文解释的更加高深,能力有限,不知道理解的是不是到位,这里真心希望大家指正,共同修正。
最后通过阅读代码并结合Netron软件对网络结构进行研究后,按照YOLOV3、V4、V5的风格对几个版本进行的绘制,这里以YOLOR-P6为例:
二、不同版本的网络结构
(1)YOLOR_P6
(2)YOLOR_W6
(3)YOLOR_CSP
(4) YOLOR_CSP_X
重点关注一下输出层OutProcess中的隐性知识向量、Shift-Channels、Control-Channels:
(1)隐性知识向量
所谓的隐性知识向量,就是单独初始化一个向量shape[1,C,1,1], 其中C与前一层的输出outchannels一直,有点类似于通道注意力的意思,然后在训练过程中,参数随着训练一点一点更新。
# 隐性知识向量-初始化方法
# 第一个隐性知识向量
class ImplicitA(nn.Module):
'''
用于ShiftChannels
'''
def __init__(self,out_channels):
super(ImplicitA,self).__init__()
# 生成向量并初始化
self.implicit = nn.Parameter(torch.zeros(1,out_channels,1,1))
nn.init.normal_(self.implicit,mean=1,std=0.02)
def forward(self):
return self.implicit
# 第二个隐性知识向量
class ImplicitM(nn.Module):
'''
用于ControlChannels
'''
def __init__(self,out_channels):
super(ImplicitM,self).__init__()
# 生成向量并初始化
self.implicit = nn.Parameter(torch.ones(1,out_channels,1,1))
nn.init.normal_(self.implicit,mean=1,std=0.02)
def forward(self):
return self.implicit
(2)ShifChannels
生成的隐性知识向量与前一层的特征通过相加Add的方式进行融合。
class ShiftChannel(nn.Module):
def __init__(self,out_channels):
super(ShiftChannel,self).__init__()
self.implicit_a = ImplicitA(out_channels)
def forward(self,x):
a = self.implicit_a()
out = a.expand_as(x) + x
return out
(3)ControlChannels
生成的隐性知识向量与前一层的特征通过相乘Mul的方式进行融合。
class ControlChannel(nn.Module):
def __init__(self,out_channels):
super(ControlChannel,self).__init__()
self.implicit_m = ImplicitM(out_channels)
def forward(self,x):
m = self.implicit_m()
out = m.expand_as(x)*x
return out