# 一、Residual Block

``````import torch
from torch import nn
import torch.nn.functional as F

class Residual(nn.Module):

def __init__(self, in_channels, out_channels, stride=1, conv_1x1=False):
super().__init__()
self.block = nn.Sequential(
nn.BatchNorm2d(out_channels),
nn.ReLU(),
nn.BatchNorm2d(out_channels),
)
self.conv_1x1 = nn.Conv2d(in_channels, out_channels, kernel_size=1,
stride=stride) if conv_1x1 else None

def forward(self, x):
y = self.block(x)
if self.conv_1x1:
x = self.conv_1x1(x)
return F.relu(y + x)
``````

# 二、ResNet 架构

ResNet-18 的实现如下：

``````class ResNet(nn.Module):

def __init__(self):
super().__init__()
self.block_1 = nn.Sequential(
nn.BatchNorm2d(64),
nn.ReLU(),
)
self.block_2 = nn.Sequential(
Residual(64, 64),
Residual(64, 64),
Residual(64, 128, stride=2, conv_1x1=True),
Residual(128, 128),
Residual(128, 256, stride=2, conv_1x1=True),
Residual(256, 256),
Residual(256, 512, stride=2, conv_1x1=True),
Residual(512, 512),
)
self.block_3 = nn.Sequential(
nn.Flatten(),
nn.Linear(512, 10),
)

def forward(self, x):
x = self.block_1(x)
x = self.block_2(x)
x = self.block_3(x)
return x
``````

# 三、训练/测试 ResNet

``````Epoch 20
--------------------------------------------------
Train Avg Loss: 0.000445, Train Accuracy: 1.000000
Test  Avg Loss: 0.759453, Test  Accuracy: 0.824000

--------------------------------------------------
3163.0 samples/sec
--------------------------------------------------

Done!
``````

# 附录一：完整代码

``````import torchvision
import torch.nn.functional as F
from torch import nn
from torchvision.transforms import ToTensor, Resize
from Experiment import Experiment as E

class Residual(nn.Module):

def __init__(self, in_channels, out_channels, stride=1, conv_1x1=False):
super().__init__()
self.block = nn.Sequential(
nn.BatchNorm2d(out_channels),
nn.ReLU(),
nn.BatchNorm2d(out_channels),
)
self.conv_1x1 = nn.Conv2d(in_channels, out_channels, kernel_size=1,
stride=stride) if conv_1x1 else None

def forward(self, x):
y = self.block(x)
if self.conv_1x1:
x = self.conv_1x1(x)
return F.relu(y + x)

class ResNet(nn.Module):

def __init__(self):
super().__init__()
self.block_1 = nn.Sequential(
nn.BatchNorm2d(64),
nn.ReLU(),
)
self.block_2 = nn.Sequential(
Residual(64, 64),
Residual(64, 64),
Residual(64, 128, stride=2, conv_1x1=True),
Residual(128, 128),
Residual(128, 256, stride=2, conv_1x1=True),
Residual(256, 256),
Residual(256, 512, stride=2, conv_1x1=True),
Residual(512, 512),
)
self.block_3 = nn.Sequential(
nn.Flatten(),
nn.Linear(512, 10),
)

def forward(self, x):
x = self.block_1(x)
x = self.block_2(x)
x = self.block_3(x)
return x

def init_net(m):
if type(m) == nn.Linear or type(m) == nn.Conv2d:
nn.init.xavier_uniform_(m.weight)

transformer = torchvision.transforms.Compose([Resize(224), ToTensor()])
train_data = torchvision.datasets.CIFAR10('/mnt/mydataset',
train=True,
transform=transformer,
test_data = torchvision.datasets.CIFAR10('/mnt/mydataset',
train=False,
transform=transformer,

resnet = ResNet()
resnet.apply(init_net)
e.main()
e.show()
``````

# 附录二：ResNet 在 FashionMNIST 数据集上的表现

``````Epoch 10
--------------------------------------------------
Train Avg Loss: 0.018614, Train Accuracy: 0.995433
Test  Avg Loss: 0.285646, Test  Accuracy: 0.920600

--------------------------------------------------
5093.3 samples/sec
--------------------------------------------------

Done!
``````

THE END