在当时,计算机的运行速度非常慢,为了减少计算量和参数,经典的LeNet-5网络使用了非常复杂的计算方式,每个过滤器都采用和输入模块一样的通道数量。另外,在当时人们往往使用sigmod函数和tanh函数做非线性函数处理,而不是ReLu函数。LeNet-5是针对灰度图片训练的,所以图片的大小只有 32 32 32× 32 32 32× 1 1 1。下面我们具体讲讲这种网络结构。
这种神经网络与LeNet有很多相似之处,不过AlexNet要大得多。正如前面讲到的LeNet或LeNet-5大约有6万个参数,而AlexNet包含约6000万个参数。当用于训练图像和数据集时,AlexNet能够处理非常相似的基本构造模块,这些模块往往包含着大量的隐藏单元或数据,这一点AlexNet表现出色。AlexNet比LeNet表现更为出色的另一个原因是它使用了ReLu激活函数。下面我们具体讲讲这种网络结构。
VGG-16这里的数字16,指的是在这个网络中包含16个卷积层和全连接层。VGG-16的结构并不复杂,而且网络结构很规整,同时卷积层的过滤器数量变化存在一定的规律,而它的主要缺点是需要训练的特征数量非常巨大。VGG-16网络没有那么多超参数,这是一种只需要专注于构建卷积层的简单网络。下面我们具体讲讲这种网络结构。
一般来说,提升网络性能最直接的办法就是增加网络深度和宽度,但是随着网络的加深,参数也越来越多,很容易产生过拟合且计算复杂度太大。解决以上问题的根本方法是将全连接层甚至一般的卷积层都转化为稀疏连接,为了既能保持网络结构的稀疏性,又能利用密集矩阵的高计算性能,因此提出了一种Inception结构,它能够保留输入信号中更多的特征信息。
其次GoogLeNet使用平均池化(average pooling)来代替全连接层,从而大大减少了参数量。同时为了避免训练过程中的梯度消失问题,在网络中间引入了两个辅助的softmax分类层用于向前传导梯度(辅助分类器),从而避免离末尾softmax较远的层难以训练的问题。
Inception结构的作用是代替人工选择来确定卷积层中的过滤器类型,或者确定是否需要使用卷积层和池化层,因此作者首先提出了下图这样的基本结构:
假设输入图像的尺寸为 28 28 28× 28 28 28× 192 192 192,首先使用64个 1 1 1× 1 1 1卷积,并且为了匹配维度将padding设为1,从而得到的输出图像为 28 28 28× 28 28 28× 64 64 64。其次使用128个 3 3 3× 3 3 3卷积,并且为了匹配维度将padding设为1,从而得到的输出图像为 28 28 28× 28 28 28× 128 128 128。接着再使用32个 5 5 5× 5 5 5卷积,并且为了匹配维度将padding设为2,从而得到的输出图像为 28 28 28× 28 28 28× 32 32 32。然后使用 3 3 3× 3 3 3最大池化窗口,得到的输出图像为 28 28 28× 28 28 28× 32 32 32。最后将这些相同维度的特征拼接起来。
采用不同大小的卷积核意味着不同大小的感受野,最后进行拼接则表示不同尺度特征的融合。但是上面的Inception结构参数太多,导致特征图厚度太大,计算成本过高,因此作者加入了 1 1 1× 1 1 1卷积核,并且提出了下图的Inception v1结构:
其中 3 3 3× 3 3 3卷积和 5 5 5× 5 5 5卷积前面的 1 1 1× 1 1 1卷积的作用是减小特征图的深度,降低计算成本。 3 3 3× 3 3 3池化后面的 1 1 1× 1 1 1卷积的作用是改变特征图的深度,从而与不同尺度的特征进行拼接。
这里以 5 5 5× 5 5 5卷积为例,假设输入图像的尺寸为 28 28 28× 28 28 28× 192 192 192,使用32个维度为 5 5 5× 5 5 5× 192 192 192的卷积核进行卷积操作,并且padding为2,步幅为1,得到的输出图像的维度为 28 28 28× 28 28 28× 32 32 32,因此对于输出图像来说需要计算输出 28 × 28 × 32 28×28×32 28×28×32个数字,每一个数字对应了 5 × 5 × 192 5×5×192 5×5×192次乘法运算,它的计算成本为 28 × 28 × 32 × 5 × 5 × 192 = 120 M 28×28×32×5×5×192=120M 28×28×32×5×5×192=120M,即需要计算机执行1.2亿次乘法运算。
假设输入图像的尺寸为 28 28 28× 28 28 28× 192 192 192,如果使用了16个维度为 1 1 1× 1 1 1× 192 192 192的卷积核,得到的输出图像为 28 28 28× 28 28 28× 16 16 16,则其计算成本为 28 × 28 × 16 × 1 × 1 × 192 = 2.4 M 28×28×16×1×1×192=2.4M 28×28×16×1×1×192=2.4M。然后再使用32个维度为 5 5 5× 5 5 5× 16 16 16的卷积核,得到的输出图像为 28 28 28× 28 28 28× 32 32 32,则其计算成本为 28 × 28 × 32 × 5 × 5 × 16 = 10 M 28×28×32×5×5×16=10M 28×28×32×5×5×16=10M。因此可以得到它的总计算成本为 12.4 M 12.4M 12.4M,远远小于上面的 120 M 120M 120M。
对于非常深的深层神经网络来说,由于梯度消失和梯度爆炸的影响,隐藏层的权重更新缓慢甚至停滞,训练过程中网络的正、反向信息流动不顺畅,网络没有被充分训练,导致深层网络的效果还不如浅层网络。因此我们可以利用跳跃连接(Skip connection)构建能够训练深度网络的ResNets,它可以从某一层网络层获取激活值,然后迅速反馈给后面的一层,甚至是神经网络的更深层。
Resnet通过堆叠残差块(Residual Block)来构建任意深度的神经网络,但是又能避免普通的卷积层堆积存在的信息丢失问题,保证前向信息流的顺畅,同时残差结构又能应对反向传播过程中的梯度消失问题,保证反向信息流的顺畅。另外,Resnet利用了Batch Norm来对抗梯度消失,从而降低网络训练过程对于权重初始化的依赖。
如果没有残差网络,对于一个普通网络来说,深度越深则使用优化算法越难训练,训练错误会越来越多。
ResNets是由残差块(Residual Block)构建的,首先来解释一下什么是残差块。
上图是一个两层神经网络,它的计算过程如下:
换句话说,信息流从 a [ l ] a^{[l]} a[l]到 a [ l + 2 ] a^{[l+2]} a[l+2]需要经过以上所有步骤,即这组网络层的主路径。
而在残差网络中直接将 a [ l ] a^{[l]} a[l]向后拷贝到神经网络的更深层,在ReLU非线性激活函数前加上 a [ l ] a^{[l]} a[l]。这就意味着最后的输出表达式不再是 a [ l + 2 ] = g ( z [ l + 2 ] ) a^{[l+2]}=g(z^{[l+2]}) a[l+2]=g(z[l+2]),取而代之的是另一个ReLU非线性函数,即 a [ l + 2 ] = g ( z [ l + 2 ] + a [ l ] ) a^{[l+2]}=g(z^{[l+2]}+a^{[l]}) a[l+2]=g(z[l+2]+a[l]),也就是加上的这个 a [ l ] a^{[l]} a[l]产生了一个残差块。
上图是一个普通网络(Plain network),把它变成ResNet的方法是加上所有跳跃连接,每两层增加一个捷径,构成一个残差块。如下图所示,5个残差块连接在一起构成一个残差网络。
在解释Resnet网络之前,首先提出一个问题:浅层网络在学习到了有效的分类模式后,如何向上堆积新层来建立更深的网络,使其满足即使不能提升浅层网络的性能,深层网络也不应降低性能?
以上图的残差块为例,假设卷积层学习的变换为 F ( X ) F(X) F(X),残差块的输出为 H ( X ) H(X) H(X),即 H ( X ) = F ( X ) + X H(X)=F(X)+X H(X)=F(X)+X。由于Resnet网络使用的是ReLU激活函数,因此激活函数的输出值 F ( X ) F(X) F(X)均为非负的,包括输入 X X X的非零异常值。
假设上图是Resnet网络的第 l l l层,输入 X X X是第 l − 1 l-1 l−1层的输出。在前向过程中,假设第 l l l层的卷积层什么也没有学习到,即 F ( X ) = 0 F(X)=0 F(X)=0,第 l − 1 l-1 l−1层的输出 X X X依然可以继续传递到下一层中,即 H ( X ) = X H(X)=X H(X)=X。以此类推,即使更深层的网络什么也不学习,它的性能依然可以不输浅层网络,从而使信息在传递过程中不丢失,保证了前向信息流的顺畅。在反向过程中,梯度计算为 ∂ H ( X ) ∂ X = ∂ F ( X ) ∂ X + 1 \frac{\partial H(X)}{\partial X}=\frac{\partial F(X)}{\partial X}+1 ∂X∂H(X)=∂X∂F(X)+1,假设第 l l l层的局部梯度为零,即 ∂ F ( X ) ∂ X = 0 \frac{\partial F(X)}{\partial X}=0 ∂X∂F(X)=0,那么反向梯度也可以从另一条路径上传播,从而保证了反向梯度流的通畅。
残差网络性能如此优越的原因除了上述的解释之外,更重要的是残差网络相当于一个集成模型。它可以看作是许多子网络的求和结果,其冗余性能更好,即使中间去掉了几个卷积层或神经单元,依旧能保持不错的性能,因此分类性能优越。
High-Resoultion Net(HRNet)由微软亚洲研究院和中科大提出,发表在CVPR2019。传统的网络结构,如VGGNet等,采用串联结构,其特征图feature map的分辨率逐渐降低,虽然减小了计算成本,但同时也损失了大量的特征信息。而获取高分辨率的方式大部分如UNet等,采用的方法是先降低分辨率,再增大分辨率,但仍然会导致大量的有效信息在不断的上下采样过程中丢失。
HRNet最大的创新点在于能够始终保持高分辨率,通过并行多个分辨率的分支,加上不断进行不同分支之间的信息交互,减少信息损耗,同时达到强语义信息和精准位置信息的目的。
首先介绍一下HRNet中的两个基础模块:瓶颈块(BottleNeck)和残差块(BasicBlock)。
上图是瓶颈块(BottleNeck)的结构图,通过 1 1 1× 1 1 1卷积块压缩特征通道,降低计算成本,同时使用了残差网络中的跳跃连接,在这过程中特征图feature map的分辨率始终保持不变。
上图是残差块(BasicBlock)的结构图,使用 3 3 3× 3 3 3卷积块来提取特征,并且通过跳跃连接传递特征信息,在这过程中分辨率始终保持不变。
在HRNet的源代码中,首先连续使用两个 3 3 3× 3 3 3卷积块,将输入图片的分辨率减小了 1 4 \frac{1}{4} 41,从而降低计算成本。
然后经过4个瓶颈块(BottleNeck),其中经过第一个瓶颈块,特征图的通道数从64增加到256,而后面3个瓶颈块中通道数保持不变。
接下来产生两个并行的分支(branch),其中第一个分支经过一个步长和padding均为1的 3 3 3× 3 3 3卷积操作,特征图的分辨率保持不变,通道数减少为32,第二个分支经过一个步长为2,padding为1的 3 3 3× 3 3 3卷积操作,特征图的分辨率缩小为原来的 1 2 \frac{1}{2} 21,通道数减少为64。在HRNet的源代码中,作者将这部分称为TransitionLayer。
接下来每个分支中的特征图feature map经过4个残差块(BasicBlock),提取特征的同时保持分辨率和通道数不变(上图仅以其中一部分为例)。
接下来是不同分辨率的特征信息进行融合与交互部分,它分为FuseLayer和TransitionLayer。
将FuseLayer拆分成如下部分,便于理解其网络结构:
不同分辨率的特征图feature map之间完成信息交互后,再将融合之后的特征图输入到TransitionLayer,经过下采样产生一个新的分支(branch)。
最后HRNet用于图像分类的检测头(Head)如下图。不同分辨率的特征图feature map经过一个瓶颈块(BottleNeck)增加通道数,并且通过相加进行融合。然后使用一个 3 3 3× 3 3 3卷积块将通道数增加到2048,再给到分类器(Classifier)中进行图像分类。
另外HRNet用于目标检测和人体关键点检测的Head和Backbone如下图。
上图是一个 6 6 6× 6 6 6的单通道图片,使用 1 1 1× 1 1 1的过滤器进行卷积,结果相当于把这个图片乘以数字2。因此对于单通道的图片来说,1×1卷积效果不佳。
如果输入的是一张 6 6 6× 6 6 6× 32 32 32的图片,那么使用 1 1 1× 1 1 1过滤器进行卷积效果更好。具体来说,1×1卷积所实现的功能是遍历这36个单元格,分别计算每个单元格中32个通道的数字和过滤器中对应的32个数字的乘积之和,然后应用ReLU非线性函数。如果过滤器不止一个,而是多个,那么输出结果为 6 6 6× 6 6 6×过滤器数量。这种方法通常称为1×1卷积,有时也被称为Network in Network。
假设这是一个 28 28 28× 28 28 28× 192 192 192的输入,池化层只能压缩它的高度和宽度,而假设使用32个大小为 1 1 1× 1 1 1× 192 192 192的过滤器,则输出的维度为 28 28 28× 28 28 28× 32 32 32,这就是压缩通道数的方法。当然如果要想保持通道数为192不变,这也是可行的。
1×1卷积的作用可以总结为如下几点: