1.为什么需要残差神经网络?
现在,目前有个通识就是,只要神经网络的层次足够,那么实际是可以表示任何事物的,但是在通常的情况下,深层次的网络会遇到一个很令人厌烦的问题:梯度消失,即当神经网络足够深的情况下,那么它的梯度值最终会趋向于0。那么怎么解决这个问题呢?比如之前我们可以使用BN
或者更换激活函数为Relu
,但是这样会导致深层次的网络的误差变大,如原文中作者给出的图:
通过在一个浅层网络基础上叠加y=x的层(称identity mappings
,恒等映射),可以让网络随深度增加而不退化。这反映了多层非线性网络无法逼近恒等映射网络。
但是,不退化不是我们的目的,我们希望有更好性能的网络。 resnet学习的是残差函数
F(x) = H(x) - x
这里如果F(x) = 0, 那么就是上面提到的恒等映射。事实上,resnet
是“shortcut connections”
的在connections
是在恒等映射下的特殊情况,它没有引入额外的参数和计算复杂度。 假如优化目标函数是逼近一个恒等映射, 而不是0映射, 那么学习找到对恒等映射的扰动会比重新学习一个映射函数要容易。从下图可以看出,残差函数一般会有较小的响应波动,表明恒等映射是一个合理的预处理。
2.残差块(Residual block)
在介绍残差网络之前,还需要介绍一下残差块(残差块是残差神经网络的基础),下面给出残差块的结构:
仔细一看,这不就是多了一条线么,就是将x
连接到+
这个位置的一条线,这条线我们可以称为skip connection
,那么具体是怎么工作的呢?
通过下面的残差块的展开结构,我们更加容易发现与常规的网络连接的不同的部分,那么就以下面的内容讲解残差块:首先是 a [ l ] a^{[l]} a[l]作为输入,先是经过下面的线性变换
z [ l + 1 ] = W [ l + 1 ] a [ l ] + b [ l + 1 ] z^{[l+1]}=W^{[l+1]}a^{[l]}+b^{[l+1]} z[l+1]=W[l+1]a[l]+b[l+1]
然后使用Relu
激活函数进行非线性变换(这里的g代表是激活函数):
a [ l + 1 ] = g ( z [ l + 1 ] ) a^{[l+1]}=g(z^{[l+1]}) a