1.网络简介
ResNet网络是在2015年由微软实验室何凯明等人提出的,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名。获得COCO数据集中目标检测第一名,图像分割第一名。各项名誉加身,引领了深度学习发展潮流。
在ResNet网络提出之前,传统的卷积神经网络都是通过将一系列卷积层与下采样层进行堆叠得到的。但是当堆叠到一定网络深度时,就会出现两个问题。1)梯度消失或梯度爆炸。 2)退化问题(degradation problem)。在ResNet论文中说通过数据的预处理以及在网络中使用BN(Batch Normalization)层能够解决梯度消失或者梯度爆炸问题。但是对于退化问题(并没有很好的解决办法。
ResNet论文提出了residual结构(残差结构)来减轻退化问题。
亮点:
(1)解决深度网络退化问题:
- 随着神经网络深度的增加,传统的网络结构会出现训练误差增大、性能下降的问题,这被称为深度网络退化。ResNet 的核心思想是引入了残差学习(residual learning)来解决这个问题。
- 残差学习的基本思想是让网络学习输入和输出之间的残差,而不是直接学习输出。这样可以使网络更容易优化,即使网络非常深,也能有效地训练。
(2)残差块结构:
- ResNet 的基本构建块是残差块(residual block)。一个典型的残差块由两部分组成:
- 主路径(identity path):也称为直连路径,直接将输入传递到输出。这部分通常包含一些卷积层和批量归一化层(Batch Normalization),用于提取特征。
- 残差路径(residual path):由几个卷积层和批量归一化层组成,用于学习输入和输出之间的残差。残差路径的输出与主路径的输入相加,得到最终的输出。
- 这种结构使得网络可以更容易地学习输入和输出之间的微小变化,从而提高了网络的性能和训练效率。
下面是网络的整体结构:
2.网络搭建
网络包含两种残差结构,较浅层的网络采用两个3x3卷积模块和一个residual分支,此浅层模块定义为BasicBlock。
注意,此结构的conv1和conv2 stride的区别,conv2_x上s=1,但是后面的conv3_x,4_x,5_x上的两个3x3卷积,第一个3x3卷积s=2。
# 18,34基础残差块
class BasicBlock(nn.Module):
expansion = 1 # 18,34层第一层卷积核个数是一样的,更深层的卷积核个数不一样,对应expansion=4
def __init__(self, in_channel, out_channel, stride=1, downsample=None):
super(BasicBlock, self).__init__()
# 第一层卷积输入输出维度一样,由于采取了BN,故不需要bias
self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,
kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channel)
self.relu = nn.ReLU()
self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,
kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channel)
self.downsample = downsample # 下采样操作,如果输入输出通道数不同,需要下采样调整
def forward(self, x):
identity = x # 跳层连接
if self.downsample is