目录
1 残差块(Residual block)
ResNet沿用了VGG全 3 × 3 3\times 3 3×3卷积层的设计。残差块里首先有2个有相同输出通道数的 3 × 3 3\times 3 3×3卷积层。每个卷积层后接一个批量归一化层和ReLU激活函数。然后我们将输入跳过这两个卷积运算后直接加在最后的ReLU激活函数前。这样的设计要求两个卷积层的输出与输入形状一样,从而可以相加。如果想改变通道数,就需要引入一个额外的 1 × 1 1\times 1 1×1卷积层来将输入变换成需要的形状后再做相加运算。
2 代码实现
import time
import torch
from torch import nn, optim
import torch.nn.functional as F
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, kernal_size=3, padding=1, stride=stride)
self.conv2=nn.Conv2d(out_channels, out_channels, kernal_size=3, padding=1)
if use_1x1conv:
self.conv3=nn.Conv2d(out_channels, out_channels, kernal_size=1, stride=stride)
else:
self.conv3=None
self.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(X)
return F.relu(Y+X)
3 ResNet模型
ResNet的前两层为:在输出通道数为64、步幅为2的
7
×
7
7\times 7
7×7卷积层后接步幅为2的
3
×
3
3\times 3
3×3的最大池化层。
ResNet在后面接了4个由残差块(Residual block)组成的模块,每个模块使用若干个同样输出通道数的残差块。第一个模块的通道数同输入通道数一致。由于之前已经使用了步幅为2的最大池化层,所以无须减小高和宽。之后的每个模块在第一个残差块里将上一个模块的通道数翻倍,并将高和宽减半。