Advertisement

python残差神经网络_卷积神经网络之残差网络ResNet详解

阅读量:

卷积神经网络之残差网络ResNet详解

理论上,在网络中添加新的层得到的新模型可能会更好地拟合训练数据集,因此添加层似乎更容易降低训练误差。然而在事件中,添加过多的层后训练误差反而会升高。针对这一问题,何凯明团队于2015年提出了残差网络(ResNet)在一定程度上解决了这一问题。

残差块

如下图所示,输入为x,理想映射为f(x)。

左图需要直接拟合出该映射f(x),右图则需要拟合出残差映射f(x)-x。残差映射在实际中往往更容易优化。

右图是ResNet的基础块(残差块Residual block)。残差块中,输入可通过跨层的数据线路更快向前传播。
745804bb4c9cddb6c8bb696b12a8bcb9.png
f6f842db8a09e1df116106757d54be71.png

残差块的组成:

两个有相同输出通道的卷积层,将输入跳过这两个卷积运算后直接加在最后的Relu前。

现在我们会得到一个H(x)=f(x)+x,我们需要f(x)=H(x)-x,

通过训练参数,得到H(x)-x,即残差,这样要比学习H(x)简单得多。

瓶颈(BottleNeck)模块
267ba1211a8bc0d2e5a23142bf678476.png

瓶颈是指block的输入和输出的通道数一样,再block中间的通道数是小于输入或输出,即采用先降维再升维。

比如右图的带瓶颈模块共使用参数个数:1125664+336464+1164*256=69632

未使用瓶颈共需要参数:332562562=1179648

很明显数据量减少了很多。

代码

import d2lzh as d2l

from mxnet import gluon, init, nd

from mxnet.gluon import nn

class Residual(nn.Block): # 本类已保存在d2lzh包中方便以后使用

def init(self, num_channels, use_1x1conv=False, strides=1, **kwargs):

super(Residual, self).init(**kwargs)

self.conv1 = nn.Conv2D(num_channels, kernel_size=3, padding=1,

strides=strides)

self.conv2 = nn.Conv2D(num_channels, kernel_size=3, padding=1)

if use_1x1conv:

self.conv3 = nn.Conv2D(num_channels, kernel_size=1,

strides=strides)

else:

self.conv3 = None

self.bn1 = nn.BatchNorm()

self.bn2 = nn.BatchNorm()

def forward(self, X):

Y = nd.relu(self.bn1(self.conv1(X)))

Y = self.bn2(self.conv2(Y))

if self.conv3:

X = self.conv3(X)

return nd.relu(Y + X)

残差网络的背后原理

其他经典网络结构:

本文地址:

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

全部评论 (0)

还没有任何评论哟~