使用的resnet-18的源代码来源于 PyTorch1.0, torchvision0.2.2
ResNet-18网络结构简图
ResNet(Residual Neural Network)来源于微软研究院的Kaiming He等人的论文《Deep Residual Learning for Image Recognition》。ResNet-18的网络简图如下图(假设网络的输入的张量的形状为 3 × 64 × 64 3\times 64\times 64 3×64×64)
如图resnet的结构分为四个stage,完整的ResNet-18的结构图在最后。
ResNet-18的代码结构
pytorch中定义了resnet-18,resnet-34,resnet-50,resnet-101,resnet-152,在pytorch中使用resnet-18的方法如下:
from torchvision import models
resnet = models.resnet18(pretrained=True)
其中pretrained
参数表示是否载入在ImageNet上预训练的模型。通过models.resnet18
函数载入网络模型,该函数的定义如下
def resnet18(pretrained=False, **kwargs):
"""构建一个ResNet-18模型
参数:
pretrained (bool): 若为True则返回在ImageNet上预训练的模型
"""
model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs)
if pretrained:
model.load_state_dict(model_zoo.load_url(model_urls['resnet18']))
return model
使用其他的ResNet模型时,使用对应的名字的函数就行,函数返回的是一个ResNet
类型的实例,这个类定义了resnet网络的结构,ResNet
类的结构如下:
class ResNet(nn.Module):
def __init__(self, block, layers, num_classes=1000, zero_init_residual=False):
"""定义ResNet网络的结构
参数:
block (BasicBlock / Bottleneck): 残差块类型
layers (list): 每一个stage的残差块的数目,长度为4
num_classes (int): 类别数目
zero_init_residual (bool): 若为True则将每个残差块的最后一个BN层初始化为零,
这样残差分支从零开始每一个残差分支,每一个残差块表现的就像一个恒等映射,根据
https://arxiv.org/abs/1706.02677这可以将模型的性能提升0.2~0.3%
"""
super(ResNet, self).__init__()
# __init__
def _make_layer(self, block, planes, blocks, stride=1):
# _make_layer function
def forward(self, x):
# forward function
残差块结构
注意上面的ResNet类的代码中的block
参数,这个参数定义了残差块的结构,分为两种:
BasicBlock
:resnet-18和resnet-34的残差块结构;Bottleneck
:resnet-50,resnet-101和resnet-152的残差块结构;
这里仅关注resnet-18因此我们只关注BasicBlock类,这个类的结构如下:
def conv3x3(in_planes, out_planes, stride=1):
"""3x3 convolution with padding"""
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
padding=1, bias=False)
def conv1x1(in_planes, out_planes, stride=1):