ResNet详解
关键要点
- ResNet(残差神经网络)是一种深度学习架构,研究表明它通过残差学习解决了深度网络的“退化”问题。
- 它似乎通过残差块设计支持训练非常深的网络(如152层),在图像分类任务中表现优异。
- 证据倾向于表明ResNet通过捷径连接缓解了梯度消失问题,影响了后续模型如DenseNet。
ResNet简介
ResNet(Residual Neural Network,残差神经网络)是一种深度学习模型,旨在解决深度神经网络中随着层数增加,训练和测试误差反而上升的“退化”问题。它通过引入残差学习和残差块设计,成功训练了非常深的网络,并在2015年ImageNet竞赛中取得了突破性成果。
问题与解决方案
研究表明,深度网络的“退化”问题不是由过拟合或梯度消失/爆炸引起的,而是优化难度增加导致的。ResNet通过学习残差映射 (F(x) := H(x) – x),而不是直接学习映射 (H(x)),使得网络更容易学习恒等映射,从而支持更深的网络结构。
网络结构
ResNet的网络结构包括基本块和瓶颈块,通过堆叠残差块实现深度可调。不同变体如ResNet-18、ResNet-50等,适用于不同复杂度的任务。
应用与影响
ResNet不仅在图像分类中表现优异,还被广泛应用于目标检测和语义分割等领域,深刻影响了深度学习的发展。
详细报告
以下是对ResNet(残差神经网络)的全面分析,基于网络搜索和页面浏览获取的信息,旨在为用户提供完整的讲解。
引言
ResNet(Residual Neural Network,残差神经网络)是一种深度学习架构,由何凯明等人于2015年提出,发表于论文《Deep Residual Learning for Image Recognition》(https://arxiv.org/abs/1512.03385)。它通过引入残差学习和残差块设计,解决了深度神经网络中随着层数增加,训练和测试误差反而上升的“退化”问题。ResNet在2015年ImageNet Large Scale Visual Recognition Challenge(ILSVRC)中获得第一名,Top-5错误率为3.57%,并在2016年获得CVPR最佳论文奖。其设计深刻影响了后续深度学习模型,如DenseNet、ResNeXt等。
背景:深度神经网络的“退化”问题
在深度学习中,通常认为增加网络深度可以提高模型的表现力,因为更深的网络可以提取更复杂的特征。然而,研究表明,当网络层数超过一定深度时,模型的训练和测试误差反而会增加,这种现象被称为“退化”问题。例如,CSDN博客(https://blog.csdn.net/sunny_yeah_/article/details/89430124)提到,34层普通卷积网络(plain network)的训练误差高于20层网络,这表明深度增加并不总是带来性能提升。
这种退化问题不是由过拟合或梯度消失/爆炸引起的,而是因为更深的网络更难优化,其误差曲面更复杂。知乎文章(https://zhuanlan.zhihu.com/p/31852747)指出,梯度消失/爆炸问题可以通过Batch Normalization(BN)层解决,但退化问题仍存在,原因在于优化难度增加。
解决方案:残差学习
ResNet通过引入残差学习(Residual Learning)来解决退化问题。传统的深度网络试图直接学习从输入到输出的映射函数 (H(x)),但ResNet改为学习残差映射 (F(x) := H(x) – x)。这样,网络只需要学习输入和输出的差值,而不是整个映射关系。
这种设计使得网络更容易学习恒等映射(即 (F(x) = 0)),这对于很深的网络至关重要。CSDN博客(https://www.cnblogs.com/shine-lee/p/12363488.html)解释道,通过残差学习,网络可以轻松地训练非常深的网络,而不会出现退化问题。这是因为,当网络无法学习到更好的映射时,它可以简单地学习恒等映射,从而保持性能不下降。
残差块设计
残差块(Residual Block)是ResNet的核心组成部分,它由两个路径组成:
- 残差路径(Residual Path):通过卷积层计算残差函数 (F(x))。
- 捷径路径(Shortcut Path):直接将输入 (x)传递到输出。
残差块的输出为 (F(x) + x),即残差函数与输入的和。知乎文章(https://zhuanlan.zhihu.com/p/54289848)提到,这种设计通过捷径连接将反向传播(backpropagation)转化为加法操作,避免了梯度消失或爆炸问题。
残差块的类型:
- 基本块(Basic Block):由两个 (3 \times 3) 卷积层组成,通常用于较浅的变体如ResNet-18和ResNet-34。
- 瓶颈块(Bottleneck Block):由 (1 \times 1)、(3 \times 3) 和 (1 \times 1) 卷积层组成,用于减少计算量,尤其在ResNet-50及更深的变体中使用。瓶颈块通过 (1 \times 1) 卷积降低维度,减少参数量。
捷径路径的处理:
- 如果 (F(x)) 和 (x) 的维度相同,直接使用恒等映射。
- 如果维度不同(如降采样时),使用 (1 \times 1) 卷积调整维度。例如,在ResNet-50中,当通道数翻倍时,捷径路径也会通过 (1 \times 1) 卷积匹配维度。
网络结构
ResNet的网络结构可以通过堆叠多个残差块来实现深度可调。不同变体包括:
- ResNet-18:18层,仅使用基本块。
- ResNet-34:34层,仅使用基本块。
- ResNet-50:50层,使用瓶颈块。
- ResNet-101:101层,使用瓶颈块。
- ResNet-152:152层,使用瓶颈块。
网络结构特点(基于https://www.cnblogs.com/shine-lee/p/12363488.html):
- 初始卷积层:通常为 (7 \times 7) 卷积,步长为2,输出通道数为64。
- 残差块组:网络分为多个阶段,每个阶段包含多个残差块。
- 每个阶段的输出通道数翻倍(如从64到128、256等)。
- 降采样(downsampling)通过卷积层的步长实现,而不是池化层。
- 全局平均池化:代替全连接层,减少参数量。
- 分类层:Softmax分类器。
以下是ResNet各变体的层数和块数对比表:
模型 | 层数 | 基本块数 | 瓶颈块数 | 参数量(百万) |
---|---|---|---|---|
ResNet-18 | 18 | 16 | 0 | ~11.7 |
ResNet-34 | 34 | 33 | 0 | ~21.8 |
ResNet-50 | 50 | 0 | 16 | ~25.6 |
ResNet-101 | 101 | 0 | 33 | ~44.5 |
ResNet-152 | 152 | 0 | 50 | ~60.2 |
误差曲面与优化
ResNet的误差曲面比普通网络更平滑,优化更容易。CSDN博客(https://www.cnblogs.com/shine-lee/p/12363488.html)提到,通过捷径连接,网络可以更容易地学习恒等映射,使得训练更稳定。研究表明,残差块的引入使得网络的损失函数更加平滑,避免了深度网络中常见的优化困难。
改进与扩展
后续工作对ResNet进行了改进,例如:
- 预激活(Pre-activation):将BN(Batch Normalization)和ReLU激活函数放在卷积层之前,而不是之后。这进一步提高了优化效率并减少了过拟合(基于https://arxiv.org/abs/1603.05027)。
- 保持捷径路径“纯净”:尽可能避免在捷径路径上使用 (1 \times 1) 卷积,除非必要(如维度不匹配)。这使得网络更易于优化。
这些改进使得ResNet可以训练超过1000层的网络,而性能仍能持续提升。例如,改进后的ResNet可以在CIFAR-10上训练1000层网络,性能优于浅层网络。
理论见解
捷径连接将反向传播(backpropagation)转化为加法操作,避免了梯度消失或爆炸问题。具体来说,在反向传播中,捷径连接确保了梯度可以通过 (F(x) + x) 的形式直接传递,而不会被稀释或放大。知乎文章(https://zhuanlan.zhihu.com/p/42706477)提到,这使得ResNet能够无损地传播损失信号(loss),从而支持非常深的网络结构。
应用与影响
ResNet不仅在图像分类任务中表现出色,还被广泛应用于目标检测、语义分割等任务。例如,Faster R-CNN中使用ResNet-101替换VGG-16,观察到28%的相对性能提升(基于https://zhuanlan.zhihu.com/p/31852747)。其残差块设计已成为深度学习架构的标准组件,影响了后续模型如DenseNet、ResNeXt等。
代码示例
以下是一个简化的ResNet-18代码示例,使用PyTorch实现,展示其基本结构(基于https://www.cnblogs.com/xfuture/p/17795430.html):
import torch
import torch.nn as nn
import torch.nn.functional as F
class BasicBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1):
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.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
self.shortcut = nn.Sequential()
if stride != 1 or in_channels != out_channels:
self.shortcut = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(out_channels)
)
def forward(self, x):
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += self.shortcut(x)
out = F.relu(out)
return out
class ResNet(nn.Module):
def __init__(self, block, num_blocks, num_classes=10):
super(ResNet, self).__init__()
self.in_channels = 64
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
self.linear = nn.Linear(512, num_classes)
def _make_layer(self, block, out_channels, num_blocks, stride):
strides = [stride] + [1]*(num_blocks-1)
layers = []
for stride in strides:
layers.append(block(self.in_channels, out_channels, stride))
self.in_channels = out_channels
return nn.Sequential(*layers)
def forward(self, x):
out = F.relu(self.bn1(self.conv1(x)))
out = self.layer1(out)
out = self.layer2(out)
out = self.layer3(out)
out = self.layer4(out)
out = F.avg_pool2d(out, 4)
out = out.view(out.size(0), -1)
out = self.linear(out)
return out
def ResNet18():
return ResNet(BasicBlock, [2, 2, 2, 2])
# 示例使用
model = ResNet18()
print(model)
总结
ResNet通过残差学习和残差块设计成功地训练了非常深的网络(如152层),在ImageNet竞赛中取得了突破性成果,并深刻影响了深度学习领域。其关键在于深度可调性和优化效率,适合图像分类、目标检测等计算机视觉任务。
参考资料:
- ResNet详解与分析
- ResNet详解——通俗易懂版
- [1512.03385] Deep Residual Learning for Image Recognition: https://arxiv.org/abs/1512.03385
- [1603.05027] Identity Mappings in Deep Residual Networks: https://arxiv.org/abs/1603.05027