Tensorflow实现网络—Resnet
一、什么残差网格
对于传统的深度学习网络,我们普遍认为网络深度越深(参数越多)非线性的表达能力越强,该网络所能学习到的东西就越多。我们凭借这一基本规则,经典的CNN网络从LetNet-5(5层)和AlexNet(8层)发展到VGGNet(16-19),再到后来GoogleNet(22层)。
根据VGGNet的实验结果可知,在某种程度上网络的深度对模型的性能至关重要,当增加网络层数后,网络可以进行更加复杂的特征模式的提取,所以当模型更深时理论上可以取得更好的结果,从图1中也可以看出网络越深而效果越好的一个实践证据。
vgg为例子如图:
但是更深的网络其性能一定会更好吗?
我们后来发现传统的CNN网络结构随着层数加深到一定程度之后,越深的网络反而效果更差,过深的网络竟然使分类的准确率下降了(相比于较浅的CNN而言)。比较结果如图:
为什么CNN网络层数增加分类的准确率却下降了呢?难道是因为模型参数过多表达能力太强出现了过拟合?难道是因为数据集太小出现过拟合?
过拟合就是模型在训练数据上的损失不断减小,在测试数据上的损失先减小再增大,这才是过拟合现象。根据图2 的结果可以看出:56层的网络比20层网络在训练数据上的损失还要大。这可以肯定不会是过拟合问题。因此,我们把这种问题称之为网络退化问题(Degradation problem)。
我们知道深层网络存在着梯度消失或者爆炸的问题,这使得深度学习模型很难训练。但是现在已经存在一些技术手段如BatchNorm来缓解这个问题。因此,出现深度网络的退化问题是非常令人诧异的。
考虑一个训练好的网络结构,如果加深层数的时候,不是单纯的堆叠更多的层,而是堆上去一层使得堆叠后的输出和堆叠前的输出相同,也就是恒等映射/单位映射(identity mapping),然后再继续训练。
这种情况下,按理说训练得到的结果不应该更差,因为在训练开始之前已经将加层之前的水平作为初始了,然而实验结果结果表明在网络层数达到一定的深度之后,结果会变差,这就是退化问题。这里至少说明传统的多层网络结构的非线性表达很难去表示恒等映射(identity mapping),或者说你不得不承认目前的训练方法或许有点问题,才使得深层网络很难去找到一个好的参数去表示恒等映射(identitymapping)。
据此提出了残差学习来解决退化问题。
残差单元
对于一个堆积层结构(几层堆积而成)当输入为x时其学习到的特征记为H(x),现在我们希望其可以学习到残差F(x) = H(x) - x,这样其实原始的学习特征是H(x)。之所以这样是因为残差学习相比原始特征直接学习更容易。当残差为F(x) = 0时,此时堆积层仅仅做了恒等映射,至少网络性能不会下降,实际上残差不会为0,这也会使得堆积层在输入特征基础上学习到新的特征,从而拥有更好的性能。残差学习的结构如图3所示。这有点类似与电路中的“短路”,所以是一种短路连接(shortcut connection)。
那么怎么在代码中完成Basic Block
class BasicBlock(layers.Layer):
def __init__(self, filter_num, stride=1):
super(BasicBlock, self).__init__(