ResNet是神经网络中非常著名的网络结构,其中引入了残差连接和批标准化(BN层,Batch Normalization),使得网络深度能够达到百层甚至千层(但上千层的网络效果并不好),实现优良的网络效果。
1、 残差连接( Residual)
残差连接如图:
这里有两个细节:
(1)F(x)与x是直接相加的,而不是在某个维度拼接;所以F(x)与x的shape完全相同。
(2)残差块的输出结果是在 F(x)+x 之后再加relu激活函数,而不是对 F(x) 进行激活函数之后再加x.
2、 不同深度的ResNet结构
不同深度(层数)的ResNet结构如上图所示,每个网络均有5个卷积块,每个卷积块里面包含数量不同的残差块。
可以发现resnet-18和resnet-34中的残差块(res1)中都是有两个3x3的卷积,但更深层的网络中的残差块(res2)是有2个1x1的卷积和一个3x3的卷积。这是因为1x1的卷积可以减少参数量,使得res2的参数量远少于res1的参数量,这样就可以减缓深层网络参数量太大导致难以训练的问题。
3、 两种不同的残差连接
从论文中可以看到resnet-34网络结构的一部分:
这三个残差块对应1.2的表格中的conv2_x的最后一个残差块和conv3_x的前两个残差块,可以发现conv3_x的第一个残差块的残差连接是虚线,这是为什么呢?
实线的残差连接就是正常的直接相加,如图所示:
虚线表示在侧边分支加了一个 1*1 卷积核的卷积操作,图中虚线连接的残差块结构如下:
从1.2的表格中可以看到,resnet-34经过 conv2_x 的输出shape是 [56,56,64],但 conv3_x 中tensor的shape是 [28,28,128]。我们知道,一般的残差连接中卷积操作之后的NCHW都不变(所以卷积的步长和padding都是1),这样才可以直接相加。所以conv2_x 中所有tensor的shape都是[56,56,64],conv3_x 中所有tensor的shape都是 [28,28,128]。
那么问题来了,如何从conv2_x过渡到conv3_x呢?
这就是虚线形式的残差连接实现的功能了。
从上面的图可以看到,虚线连接的残差块结构有一个1x1卷积的分支,总共有三个卷积,并且其中两个卷积的步长是2,而不是一般残差块中的stride=1。步长为2就可以将 conv2_x 中大小为56的H和W缩小为28,三个卷积的channel=128可以将 conv2_x 输出的 channel=64的tensor拓展为 channel=128。这样就实现了从conv2_x([56,56,64]) 到conv3_x( [28,28,128])的过渡了,这就是虚线残差块的作用。
所以在从conv3_x开始的每一个卷积块中,第一个残差块都是特殊的虚线残差块,因为要完成shape转换的功能。