ResNet精读

本文介绍了ResNet残差网络,针对深度网络训练中的梯度问题和性能下降,通过引入残差连接保持深层网络的学习能力。该网络在ImageNet上展现了即使深度翻倍(152层)仍能保持高精度。关键概念包括恒等映射、shortcut和网络架构,如34层的ResNet结构。实验对比了不同深度网络,展示了ResNet的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘要

随着神经网络的深度变深,网络会更加难以学习,作者提出了一种残差连接的网络,使得在模型变深的时候依旧能够学习。网络是在ImageNet上学习的,总共有152层的深度,是VGG的8倍,即便深度增加了这么多,ResNet仍旧获得了很好的结果。

1 引言

深度网络将高中低等级的特征组合在一起,使用端到端的多层结构来分类,并且可以通过增加深度来增加特征。

但是问题也随之而来:深度的增加会出现梯度消失、梯度爆炸的问题,同时,当网络深度增加,可以发现精度会先饱和,然后迅速下降,而这样的下降却不是由过拟合导致的,因为训练误差也在同步增加(如果是过拟合导致的,那么训练误差不会增加)。

可以看到下图中,56层的网络并没有20层的网络表现得好。
在这里插入图片描述
但是,如果我们做这样一个假设:当浅层的网络效果比较好的时候,深度网络训练会逐渐向浅层的网络进行学习。比如我们在一个浅层的网络上加一系列的恒等映射f(x)=x,那么看上去深度增加了,但是实际效果是不会变的,如果深度网络能够逐渐学习到这样的一个恒等映射,那么是不是就不会变差呢?但是,SGD的优化方法容易让学习陷入一个局部最优,所以无法学习到这样的一个恒等映射,于是深度的网络可能会比浅层的更差。

3 残差网络

为了使得深度的网络至少不会比一个对应的浅层网络要差,引入了残差的结构:

假设我们希望网络学习到的是一个H(x)H(x)H(x)的映射,那么本来的浅层网络输出一个xxx,后面加的层假设是F(x)F(x)F(x),我们希望这些加的层学到的是H(x)−xH(x)-xH(x)x,也就是残差。那么换一种写法也就是H(x)=F(x)+xH(x)=F(x)+xH(x)=F(x)+x。极端情况下,如果恒等映射是最优的,那么就更容易将残差部分变成0。同时,这样的恒等映射不会增加计算的复杂度。

具体实现而言就是引入了一个shortcut,可以理解为一个捷径,可以跳过中间的层,直接作用于输出上,如下图所示:
在这里插入图片描述
实验证明,比只是堆加层的网络,残差网络错误率低,并且深度增加的时候也可以有好的准确率。

shortcut的思想很久之前就被提出来了,并不是这篇文章提出来的,同时,但是的一些研究,如highway network,和residual的思想差不多,但是highway的shortcut connection是有参数的,所以可能这样的参数会变成0,于是就变成了没有残差的网络。

3.2 恒等映射

当然,还有个问题要解决,如何保证xxxF(x)F(x)F(x)可以加呢,也就是说,要保证这两个的维度是相同的。

如果F(x)F(x)F(x)对输入xxx有维度上的改变,那么我们也需要在shortcut的xxx上做一些映射,使得维度匹配,也就是:
在这里插入图片描述
当然,这样的记号是对于全连接层而言的,但是卷积层也是类似的,我们实际上使用的映射就是1×1的卷积作为这里的WsW_sWs,因为1×1的卷积只会改变输入输出的维度,或者说通道数。

3.3 网络架构

一个34层的ResNet架构如下(右),其中实线是中间的卷积层F(x)F(x)F(x)没有改变输入的维度,虚线则是有维度的改变,这里维度的改变就是通道数的改变。

保证维度相等的方式有两种:

  • 使用零进行填充
  • 使用1×1的卷积核来改变维度。
    在这里插入图片描述

3.4 实现

实现中,参考了Alexnet,但是又有些不同,将图片的短边随机变成256-480的数值,作为数据增强,然后随机裁出224×224的,也包括了它们的水平镜像,同时减去了均值做中心化。

同时,使用了批量归一化BN层在每一个卷积层之后和激活之前。训练的批量大小batch-size=256,learning-rate开始0.1,当误差稳定(plateau)的时候,就除以10。

和AlexNet意义,也用了权重衰减,但是衰减率是0.0001,还有动量梯度下降,动量为0.9。

测试的时候也和AlexNet一样,裁出10个224×224的然后取平均。

4 实验

实验中尝试了18、34、50、101、152层的不同网络结构。
在这里插入图片描述
可以看到,所有结构最前面都是一个7×7的卷积和3×3的最大池化,和AlexNet是类似的,然后不同的是后面的架构,其中18层和34层的都差不多,就是残差块的数量多少有变化,而到了50层或者更深的网络,则采用了一种不同的架构——bottleneck。

采用这种架构的起因是,由于网络更加深了,于是输入通道数变得更多了,如果还想和本来保持差不多的复杂度,那么先使用1×1的卷积层把通道数降低,然后中间3×3和之前一样,最后再用1×1的卷积层映射回去,保证输入输出的通道数是一样的。中间的那个3×3的卷积被称为bottleneck。

对比18层和34层的网络,细的是训练误差,粗的是验证误差,一开始可以看到验证的误差反而要低,这是因为用了数据增强,所以训练的时候会有许多的噪音。在使用了残差连接之后,深层的网络比浅层的网络效果要好:
在这里插入图片描述
作者还比较了使用0填充和使用1×1卷积核来保证维度的效果,下图中间的A、B、C分别表示了用零填充、用1×1卷积来增加维度和所有都用投影,虽然C的效果比B还要好,但是作者认为C会增加额外的计算复杂度,而且B的效果依旧很不错了。
在这里插入图片描述

### ResNet在数学图像识别中的应用与实现方法 ResNet(Residual Network)是一种深度卷积神经网络,通过引入残差块(Residual Block),解决了深网络训练过程中梯度消失和模型退化的问题。以下是ResNet在数学图像识别中的实现方法及其相关细节。 #### 1. 核心原理 ResNet的核心思想是通过引入残差学习机制,使网络能够更容易地优化深次结构。假设目标函数为 \( H(x) \),传统网络直接学习 \( H(x) \),而ResNet学习的是残差函数 \( F(x) = H(x) - x \),然后通过恒等映射将 \( F(x) + x \) 输出[^1]。这种设计使得深网络的训练更加稳定。 #### 2. 数学建模 ResNet的基本结构可以表示为: \[ y = F(x, W) + x \] 其中,\( F(x, W) \) 表示残差函数,\( W \) 是权重参数,\( x \) 是输入,\( y \) 是输出。如果输入和输出的维度不匹配,则可以通过线性投影 \( W_s \) 转换输入维度[^4]。 #### 3. 实现方法 以下是基于PyTorch的ResNet实现代码示例: ```python import torch import torch.nn as nn class BasicBlock(nn.Module): expansion = 1 def __init__(self, in_channels, out_channels, stride=1, downsample=None): super(BasicBlock, self).__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(out_channels) self.relu = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(out_channels) self.downsample = downsample self.stride = stride def forward(self, x): identity = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) if self.downsample is not None: identity = self.downsample(x) out += identity out = self.relu(out) return out class ResNet(nn.Module): def __init__(self, block, layers, num_classes=1000): super(ResNet, self).__init__() self.in_channels = 64 self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False) self.bn1 = nn.BatchNorm2d(64) self.relu = nn.ReLU(inplace=True) self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) self.layer1 = self._make_layer(block, 64, layers[0]) self.layer2 = self._make_layer(block, 128, layers[1], stride=2) self.layer3 = self._make_layer(block, 256, layers[2], stride=2) self.layer4 = self._make_layer(block, 512, layers[3], stride=2) self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) self.fc = nn.Linear(512 * block.expansion, num_classes) def _make_layer(self, block, out_channels, blocks, stride=1): downsample = None if stride != 1 or self.in_channels != out_channels * block.expansion: downsample = nn.Sequential( nn.Conv2d(self.in_channels, out_channels * block.expansion, kernel_size=1, stride=stride, bias=False), nn.BatchNorm2d(out_channels * block.expansion), ) layers = [] layers.append(block(self.in_channels, out_channels, stride, downsample)) self.in_channels = out_channels * block.expansion for _ in range(1, blocks): layers.append(block(self.in_channels, out_channels)) return nn.Sequential(*layers) def forward(self, x): x = self.conv1(x) x = self.bn1(x) x = self.relu(x) x = self.maxpool(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = self.avgpool(x) x = torch.flatten(x, 1) x = self.fc(x) return x ``` #### 4. 论文精读 ResNet论文的核心贡献在于提出了残差学习的概念,验证了其在深网络中的有效性。论文中详细描述了不同数的ResNet模型(如ResNet-18、ResNet-34、ResNet-50等)在ImageNet数据集上的表现。这些模型不仅显著提高了分类准确率,还降低了训练难度。 #### 5. 应用场景 ResNet在图像分类、目标检测、语义分割等多个领域得到了广泛应用。例如,在图像分类任务中,ResNet通过堆叠更多的残差块,实现了更高的准确率;在目标检测任务中,ResNet作为主干网络,结合Faster R-CNN等算法,进一步提升了检测性能[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值