AI智能
改变未来

ResNet残差网络(pyTorch)

Contents

  • 1 Intorduction
  • 2 残差块
  • 3 ResNet模型
  • 4 获取数据和训练模型

1 Intorduction

ResNet在2015年的ImageNet图像识别挑战赛夺魁。

由于存在梯度消失和梯度爆炸问题,深度很深的神经网络是很难训练的。解决方法之一是人为地让神经网络某些层跳过下一层神经元的连接,隔层相连,弱化每层之间的强联系,即跳跃连接(skip connection)。用它可以构建能够训练深度网络的ResNets,这种神经网络被称为Residual Networks(ResNets)。Residual Networks由许多隔层相连的Residual block组成。

2 残差块

ResNet沿用了VGG全3×3卷积层的设计。残差块里首先有2个有相同输出通道数的3×3卷积层。每个卷积层后接一个批量归一化层和ReLU激活函数。然后我们将输入跳过这两个卷积运算后直接加在最后的ReLU激活函数前。这样的设计要求两个卷积层的输出与输入形状一样,从而可以相加。如果想改变通道数,就需要引入一个额外的1×1卷积层来将输入变换成需要的形状后再做相加运算。

# 残差块的实现如下,它可以设定输出通道数、是否使用额外的1×1卷积层来修改通道数以及卷积层的步幅import timeimport torchfrom torch import nn, optimimport torch.nn.functional as Fimport syssys.path.append(\"..\")import d2lzh_pytorch as d2ldevice = torch.device(\'cuda\' if torch.cuda.is_available() else \'cpu\')class Residual(nn.Module):def __init__(self, in_channels, out_channels, use_1x1conv = False, stride = 1):super(Residual, self).__init__()self.conv1 = nn.Conv2d(in_channels, out_channels,kernel_size = 3, padding = 1, stride=stride)self.conv2 = nn.Conv2d(out_channels, out_channels,kernel_size = 3, padding = 1)if use_1x1conv:self.conv3 = nn.Conv2d(in_channels, out_channels,kernel_size = 1, stride=stride)else:self.conv3 = Noneself.bn1 = nn.BatchNorm2d(out_channels)self.bn2 = nn.BatchNorm2d(out_channels)def forward(self, X):Y = F.relu(self.bn1(self.conv1(X)))Y = self.bn2(self.conv2(Y))if self.conv3:X = self.conv3(Y)return F.relu(Y+X)

其中卷积操作、批量归一化BN、激活函数ReLU操作顺序可参考下图:

3 ResNet模型

net = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
# ResNet使用4个由残差块组成的模块,每个模块使用若干个同样输出通道数的残差块。def resnet_block( in_channels, out_channels, num_resduals, first__block = False):assert in_channels==out_channelsblk=[]for i in range(num_residuals):if i == 0 and not first_block:blk.append(Residual(in_channels, out_channels, use_1x1conv=True, stride=2))else:blk.append(Residual(out_channels, out_channels))return nn.Sequential(*blk)net.add_module(\"resnet_block1\", resnet_block(64, 64, 2, first_block=True))net.add_module(\"resnet_block2\", resnet_block(64 128, 2))net.add_module(\"resnet_block3\", resnet_block(128, 256, 2))net.add_module(\"resnet_block4\", resnet_block(256, 512, 2))# 加上全局平均池化层后接上全连接输出层net.add_module(\"global_avg_pool\", d2l.GlobalAvgPool2d()) # GlobalAvgPool2d的输出: (Batch, 512, 1, 1)net.add_module(\"fc\", nn.Sequential(d2l.FlattenLayer(), nn.Linear(512, 10)))

每个模块里有4个卷积层(不计算1×1卷积层),加上最开始的卷积层和最后的全连接层,共计18层。这个模型通常也被称为ResNet-18。
以上的模型参数是ResNet-18中的模型参数,也可按照下图修改其参数:

4 获取数据和训练模型

# 硬件限制,不跑结果了……batch_size = 256# 如出现“out of memory”的报错信息,可减小batch_size或resizetrain_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)lr, num_epochs = 0.001, 5optimizer = torch.optim.Adam(net.parameters(), lr=lr)d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)

参考原文:《动手学深度学习(pyTorch)》

欢迎关注【OAOA】

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » ResNet残差网络(pyTorch)