# 【从零开始学习深度学习】31. 卷积神经网络之残差网络（ResNet）介绍及其Pytorch实现

### 1. 残差块介绍

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

import time
import torch
from torch import nn, optim
import torch.nn.functional as F
import sys
import d2lzh_pytorch as d2l
device = 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 = 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)

blk = Residual(3, 3)
X = torch.rand((4, 3, 6, 6))
blk(X).shape # torch.Size([4, 3, 6, 6])

blk = Residual(3, 6, use_1x1conv=True, stride=2)
blk(X).shape # torch.Size([4, 6, 3, 3])

### 2. 构建ResNet残差模型

net = nn.Sequential(
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

def resnet_block(in_channels, out_channels, num_residuals, first_block=False):
if first_block:
assert in_channels == out_channels # 第一个模块的通道数同输入通道数一致
blk = []
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_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))) 

X = torch.rand((1, 1, 224, 224))
for name, layer in net.named_children():
X = layer(X)
print(name, ' output shape:\t', X.shape)

0  output shape:   torch.Size([1, 64, 112, 112])
1  output shape:   torch.Size([1, 64, 112, 112])
2  output shape:   torch.Size([1, 64, 112, 112])
3  output shape:   torch.Size([1, 64, 56, 56])
resnet_block1  output shape:   torch.Size([1, 64, 56, 56])
resnet_block2  output shape:   torch.Size([1, 128, 28, 28])
resnet_block3  output shape:   torch.Size([1, 256, 14, 14])
resnet_block4  output shape:   torch.Size([1, 512, 7, 7])
global_avg_pool  output shape:   torch.Size([1, 512, 1, 1])
fc  output shape:  torch.Size([1, 10])

### 3. 获取数据和训练ResNet模型

batch_size = 256
# 如出现“out of memory”的报错信息，可减小batch_size或resize
lr, num_epochs = 0.001, 5
d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)

training on  cuda
epoch 1, loss 0.0015, train acc 0.853, test acc 0.885, time 31.0 sec
epoch 2, loss 0.0010, train acc 0.910, test acc 0.899, time 31.8 sec
epoch 3, loss 0.0008, train acc 0.926, test acc 0.911, time 31.6 sec
epoch 4, loss 0.0007, train acc 0.936, test acc 0.916, time 31.8 sec
epoch 5, loss 0.0006, train acc 0.944, test acc 0.926, time 31.5 sec

### 4. 总结

• 残差块通过跨层的数据通道从而能够训练出有效的深度神经网络。

|
1月前
|

121 7
|
24天前
|

【乐器识别系统】图像识别+人工智能+深度学习+Python+TensorFlow+卷积神经网络+模型训练

36 0
|
20小时前
|

【YOLOv8改进- Backbone主干】BoTNet：基于Transformer，结合自注意力机制和卷积神经网络的骨干网络
【YOLOv8改进- Backbone主干】BoTNet：基于Transformer，结合自注意力机制和卷积神经网络的骨干网络
11 3
|
6天前
|

【YOLOv8改进- Backbone主干】YOLOv8更换主干网络之ConvNexts，纯卷积神经网络，更快更准，，降低参数量！
YOLOv8专栏探讨了针对目标检测的ConvNet创新，提出ConvNeXt模型，它挑战Transformer在视觉任务中的主导地位。ConvNeXt通过增大卷积核、使用GeLU激活、切换到LayerNorm和改进下采样层，提升了纯ConvNet性能，达到与Transformer相当的准确率和效率。论文和代码已公开。
25 4
|
6天前
|

【YOLOv8改进- Backbone主干】YOLOv8 更换主干网络之 PP-LCNet，轻量级CPU卷积神经网络，降低参数量
21 2
|
1月前
|

【昆虫识别系统】图像识别Python+卷积神经网络算法+人工智能+深度学习+机器学习+TensorFlow+ResNet50

186 7
|
11天前
|

25 9
|
6天前
|

【YOLOv8改进- Backbone主干】YOLOv8 更换主干网络之EfficientNet，高效的卷积神经网络，降低参数量
YOLOv8专栏探讨了目标检测的创新改进，包括模型扩展和神经架构搜索。提出的新方法使用复合系数平衡网络的深度、宽度和分辨率，产生了EfficientNets系列，其在准确性和效率上超越了先前的ConvNets。EfficientNet-B7在ImageNet上达到84.3%的顶级准确率，同时保持较小的模型大小和更快的推理速度。文章提供了论文和代码链接，以及核心的EfficientNet模型构建Python代码。
25 1
|
1月前
|

【球类识别系统】图像识别Python+卷积神经网络算法+人工智能+深度学习+TensorFlow

120 7
|
14天前
|

**神经网络与AI学习概览** - 探讨神经网络设计，包括MLP、RNN、CNN，激活函数如ReLU，以及隐藏层设计，强调网络结构与任务匹配。 - 参数初始化与优化涉及Xavier/He初始化，权重和偏置初始化，优化算法如SGD、Adam，针对不同场景选择。 - 学习率调整与正则化，如动态学习率、L1/L2正则化、早停法和Dropout，以改善训练和泛化。
10 0