一、背景介绍
随着层数的堆叠,网络的深度会不断增加,特征的level
也会提升,很多CV方向的任务也因此取得更好的成绩。但是,一个问题随之出现:通过层数堆叠不断加深网络的同时,可以学习到更好的网络吗?答案是否定的,梯度消失/爆炸是最大的阻碍。不过随着normalized initialization
和Batch normalizaiton
的应用,很大程度上已经解决了这个问题。
但是退化问题(degradation
)依然没有解决:随着网络的加深,网络的精度会饱和,甚至会下降。这也不是过拟合,因为随着深度增加,训练误差会上升。退化问题显然是不符合常理的,举个例子,假设我们现在有一个浅层网络,以及一个在它的基础上无脑堆叠了一些恒等映射(identity mapping
,
F
(
x
)
=
x
F(x) = x
F(x)=x)的深度网络,那么对于同一输入后者的训练误差不会比前者更差。而实际上当时已有网络的效果却比不上它。换句话说就是,从某一层开始,我对输入什么都不处理,都比你花里胡哨地加一堆东西强。
这反映出的问题是:已有的神经网络或许因为非线性层的原因难以拟合恒等映射。因此,可以认为Residual Learning的初衷,其实是让模型的内部结构至少有恒等映射的能力。以保证在堆叠网络的过程中,网络至少不会因为继续堆叠而产生退化!
二、思路提出
在作者们研究了前人的工作如VLAD
、highway network
之后,发现residual representations
和shortcut connection
这两种理论的效果不错,鉴于此提出了Deep Residual Learning
的概念:既然没办法拟合恒等映射,那就改为拟合残差,而且拟合残差更容易优化。
原本神经网络的目的是拟合一个输入到输出的未知映射
H
(
x
)
H(x)
H(x),现在重构
H
(
x
)
=
F
(
x
)
+
x
H(x) = F(x) + x
H(x)=F(x)+x,那么现在实质上就是要学习残差函数
F
(
x
)
=
H
(
x
)
−
x
F(x) = H(x) - x
F(x)=H(x)−x,即输入减输出。如果真的需要拟合恒等映射,那么只需要将各层的权重置零,从而使得残差为零即可。
实现方案如图所示,这是ResNet
的核心架构shortcut connecion
,在激活函数之前将前几层的输入与本层的输出相加,用公式表示就是:
y
=
F
(
x
,
{
W
i
}
)
+
x
y = F(x, \left\{ W_i\right\}) + x
y=F(x,{Wi})+x。
F
(
x
,
{
W
i
}
)
F(x, \left\{ W_i\right\})
F(x,{Wi})可以是全连接,也就是卷积层。像图上这样有两层的Residual Block
,应该表示为:
F
=
W
2
σ
(
W
1
x
)
F = W_2\sigma(W_1x)
F=W2σ(W1x)
其中,
σ
\sigma
σ表示ReLU
。注意,Residual Block
至少得有两层,不然
y
=
F
(
x
)
+
x
=
W
x
+
x
=
(
W
+
1
)
x
y = F(x) + x = Wx + x = (W + 1)x
y=F(x)+x=Wx+x=(W+1)x,这个毫无意义,就一普通的线性函数。另外,shortcut connection
不会引入额外的参数,也不会增加计算的复杂度。
三、网络架构
ResNet
除了shortcut connection
,其他设计基本上都是按照vgg
的架构,比如feature map
的尺寸减半而通道数翻倍。由此也会引出
x
x
x和
F
(
x
,
{
W
i
}
)
F(x, \left\{ W_i \right\})
F(x,{Wi})的特征图尺寸以及通道数不一致的问题,这时候需要对
x
x
x通过kernel_size = 1, stride = 2
的卷积将两者尺寸和通道数调整一致。
另外,如上图所示,随着ResNet的深度增加,到了50/101/152层的时候,为了减少模型的参数和计算量,可以将原先左侧的两个
3
∗
3
3 * 3
3∗3卷积改为右侧
1
∗
1
,
3
∗
3
,
1
∗
1
1 * 1, 3 * 3, 1*1
1∗1,3∗3,1∗1卷积这样的bottleneck
结构。我们可以简单计算一下输入通道数相同时两者的计算量,假设通道数为256,那么左侧building block
的参数量为
3
∗
3
∗
256
∗
256
∗
2
=
1179648
3 * 3 * 256 * 256 * 2 = 1179648
3∗3∗256∗256∗2=1179648,右侧bottleneck
的参数量为
256
∗
1
∗
1
∗
64
+
64
∗
3
∗
3
∗
64
+
64
∗
1
∗
1
∗
256
=
69632
256 * 1 * 1 * 64 + 64 * 3 * 3 * 64 + 64 * 1 * 1 * 256 = 69632
256∗1∗1∗64+64∗3∗3∗64+64∗1∗1∗256=69632,差了16.94倍。
那为什么bottleneck
可以将building block
的两个
3
∗
3
3 * 3
3∗3卷积只保留一个呢? 前面已经说了至少用两个
3
∗
3
3 * 3
3∗3卷积是因为非线性拟合能力不够,但是bottleneck
引入了两个
1
∗
1
1 * 1
1∗1的卷积,可以弥补这方面的不足。
既然1x1有这个优点,为什么ResNet18和ResNet34不采用 1 ∗ 1 1 * 1 1∗1的卷积来设计呢? 这是因为前面的网络相对深度小,要求每个模块能够胜任提取更抽象特征的能力,因此需要用 3 ∗ 3 3 * 3 3∗3卷积来提取到更抽象的特征。
总结一下bottleneck
的优势:
- 增加了网络深度,深层网络能提取出更抽象的特征。
- 减少了参数和计算量,使得模型更好地收敛。
- 增加了非线性。
四、补充
4.1 为什么更容易拟合残差
假设我们要学习一种从输入
x
x
x到输出
H
(
x
)
H(x)
H(x)的映射,如果是非ResNet的情况,那么给定
H
(
5
)
=
5.1
H(5)=5.1
H(5)=5.1和
H
(
5
)
=
5.2
H(5)=5.2
H(5)=5.2这两个样本,我们可能学习到的映射就是
H
1
(
x
)
=
w
1
x
=
5.1
5
x
H_1(x) = w_1x = \frac{5.1}{5}x
H1(x)=w1x=55.1x和
H
2
(
x
)
=
w
2
x
=
5.2
/
5
∗
x
H_2(x) = w_2x = 5.2/5* x
H2(x)=w2x=5.2/5∗x,这两个函数的权重都近似等于1, 或者说
W
2
W_2
W2是
W
1
W_1
W1的1.0196倍. 也就是说,给这样的两个样本,让网络学习出对应的权重,用SGD
的话,容易导致训练慢,甚至学错。 但是ResNet就不同了,原输入输出数据相当于变成了
F
(
5
)
=
0.1
,
F
(
5
)
=
0.2
F(5)=0.1, F(5)=0.2
F(5)=0.1,F(5)=0.2, 这两个对应的潜在函数变成了
H
1
(
x
)
=
w
1
x
=
0.1
5
x
H_1(x) = w_1x = \frac{0.1}{5}x
H1(x)=w1x=50.1x和
H
2
(
x
)
=
w
2
x
=
0.2
5
x
H_2(x) = w_2x = \frac{0.2}{5}x
H2(x)=w2x=50.2x,
w
2
w_2
w2是
w
1
w_1
w1的两倍,所以
w
w
w对于数据集非常敏感了,ResNet 里面的参数
w
w
w会更加"准确"反映数据的细微变化。
4.2 为什么残差这么有效
这个有不少解释:
shortcut connections
可以实现不同分辨率特征的组合,因为浅层容易有高分辨率但是低级语义的特征,而深层的特征有高级语义,但分辨率就很低了。- 即使BN过后梯度的模稳定在了正常范围内,但梯度的相关性实际上是随着层数增加持续衰减的。而经过证明,ResNet可以有效减少这种相关性的衰减。
- 引入
shortcut connections
实际上让模型自身有了更加“灵活”的结构,即在训练过程本身,模型可以选择在每一个部分是“更多进行卷积与非线性变换”还是“更多倾向于什么都不做”,抑或是将两者结合。模型在训练便可以自适应本身的结构。
4.3 为什么是加 x x x不是加 1 2 x \frac{1}{2}x 21x
假如不是
x
x
x而是
λ
x
\lambda x
λx的话梯度里会有一项
∏
i
=
l
L
−
1
λ
i
\prod_{i = l}^{L - 1}\lambda_i
∏i=lL−1λi,就是从输出到当前层之间经过的shortcut
上的所有
λ
i
\lambda_i
λi相乘,假如
λ
i
\lambda_i
λi都大于 1 那经过多层之后就会爆炸,都小于 1 就会趋向于 0 而变得和没有shortcut
一样了。