残差网络结构及理解
输入为 x ,需要拟合的结果(输出)为 H(x) 。
那么我们把输出差分为 x+y ,也就是 H(x)=x+y,再令 y=F(x) ,意思是 y 也是由 x 拟合而来,那么最后的输出就变为 H(x)=x+F(x),x 本来就是输入,所以我们就只需要拟合 F(x) 就好了。
其实也很明显,通过求偏导我们就能看到:
∂XL∂Xl=∂Xl+F(Xl,Wl,bl)∂Xl=1+∂F(XL,WL,bL)∂XL
这样就算深度很深,梯度也不会消失了。
举个例子:
输入 x = 2.9 , 经过拟合后的输出为 H(x)=3.0
那么残差就是 F(x)=H(X)-x=0.1
如果拟合的是恒等变换,即输入 x=2.5 ,输出还是 H(x)=2.5
那么残差就是 F(x)=H(X)-x=0.0
而如上图所示,假设 x 从 2.9 经过两层卷基层(conv)之后变为 3.1 ,
平原网络的变化率Δ=3.1−3.03.0=3.3%
而残差模块的变化率为Δ=0.2−0.10.1=100%
残差的引入去掉了主体部分,从而突出了微小的变化。
通过在输出个输入之间引入一个shortcut connection,而不是简单的堆叠网络,这样可以解决网络由于很深出现梯度消失的问题,从而可可以把网络做的很深。
另一种理解
残差网络单元其中可以分解成右图的形式,从图中可以看出,残差网络其实是由多种路径组合的一个网络,直白了说,残差网络其实是很多并行子网络的组合,整个残差网络其实相当于一个多人投票系统(Ensembling)。
关于bottleneck
论文中有两种residual block的设计,如下图所示:
在训练浅层网络的时候,我们选用前面这种,而如果网络较深(大于50层)时,会考虑使用后面这种(bottleneck),这两个设计具有相似的时间复杂度。
同样举个例子:
对于ImageNet而言,进入到第一个residual block的input为 (56,56,64)
采用左侧的两个 3×3 conv的卷积层:
参数量为(3×3×64)×64+(3×3×64)×64
化简一下:params:(18×64)×64=73728
采用右侧的bottleneck:
参数量为 (1×1×64)×64+(3×3×64)×64+(1×1×64)×256+(1×1×64)×256
化简一下: params:(18×64)×64=73728
可以看到它们的参数量属于同一个量级,
但是这里bottleneck占用了整个network的「三层」,而原本只有「两层」,
所以这样就节省了大量的参数,
在大于50层的resnet中,他们使用了bottleneck这种形式。
层数较高时减少了3x3卷积个数,并用1x1卷积控制了3x3卷积的输入输出特征图数量,称这种结构为“瓶颈”(bottleneck)。
Identity mapping 改进
这便是这篇paper的改进,把原本的ReLU,放到Residual Unit的conv前面去,而不是放在addition之后。
可以看到,在上图作者对cifar10进行的多组实验中,使用full pre-activation这种Residul Unit效果最佳,个人认为这张表格还是挺重要的,我们简单分析一下!
(a)original:原始的结构
(b)BN after addition:这是在做相反的实验,本来我们的目的是把ReLU移到旁路上去,这里反而把BN拿出来,这进一步破坏了主路线上的恒等关系,阻碍了信号的传递,从结果也很容易看出,这种做法不ok
(c)ReLU before addition:将 f 变为恒等变换,最容易想到的方法就是将ReLU直接移动到BN后面,但这会出现一个问题,一个 \mathcal{F} (残差函数)的输出应该可以是 (-\infty,\infty) ,但是经过ReLU之后就会变为 (0,\infty) ,这种做法的结果,也比(a)要差。
直接提上来似乎不行,但是问题反过来想, 在addition之后做ReLU,不是相当于在下一次conv之前做ReLU吗?
(d)ReLU-only pre-activation:根据刚才的想法,我们把ReLU放到前面去,然而我们得到的结果和(a)差不多,原因是什么呢?因为这个ReLU层不与BN层连接使用,因此无法共享BN所带来的好处。
(e)full pre-activation:啊,那要不我们也把BN弄前面去,惊喜出现了,我们得到了相当可观的结果,是的,这便是我们最后要使用的Unit结构!!!