社区计算机视觉课程文档

ResNet (残差网络)

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

ResNet (残差网络)

拥有更多层的神经网络被认为更有效,因为添加更多层可以提高模型性能。

随着网络变得更深,提取的特征可以进一步丰富,例如 VGG16 和 VGG19 所展示的那样。

一个问题出现了:“学习网络是否像堆叠更多层一样容易”? 归一化初始化和中间归一化层解决了回答这个问题的一个障碍:梯度消失问题。

然而,一个新的问题出现了:退化问题。 随着神经网络变得更深,准确率饱和并迅速下降。 一项比较浅层和深层普通网络的实验表明,更深的模型表现出更高的训练和测试误差,这表明有效训练更深层架构存在根本性挑战。 这种退化不是因为过拟合,而是因为当网络变得更深时,训练误差反而增加。 增加的层没有近似恒等函数。

Degradation-error

ResNet 的残差连接释放了极深网络的潜力,与之前的架构相比,大大提高了准确率。

ResNet 架构

  • 一个残差块。 来源:ResNet 论文 residual

ResNet 引入了一个称为残差学习的概念,它允许网络学习残差(即学习到的表示与输入之间的差异),而不是尝试直接将输入映射到输出。 这是通过跳跃连接(或快捷连接)实现的。

让我们分解一下

1. 基本构建块:残差块

在典型的神经网络层中,我们的目标是学习一个映射 F(x),其中 x 是输入,F 是网络应用的变换。 如果没有残差学习,则一层的变换为:y = F(x)。 在 ResNet 中,网络不是直接学习 F(x),而是设计为学习残差 R(x),其中:R(x) = F(x) − x。 因此,残差块中的变换可以写成:y = F(x) + x。

这里,x 是残差块的输入,F(x) 是该块堆叠层(通常是卷积、批量归一化和 ReLU)的输出。 恒等映射 x 直接添加到 F(x) 的输出(通过跳跃连接)。 因此,该块正在学习残差 R(x) = F(x),最终输出为 F(x) + x。 与原始映射相比,此残差函数更容易优化。 如果最佳变换接近恒等变换(即,不需要变换),则网络可以轻松地将 F(x) ≈ 0 设置为按原样传递输入。

  • ResNet 的构建块可以在图片中显示,来源 ResNet 论文。

resnet_building_block

2. 学习残差和梯度流

ResNet 在非常深的网络中表现良好的主要原因是反向传播期间梯度流的改善。 让我们从数学上分析反向传播过程。 假设您有残差块 y = F(x) + x。 当通过链式法则计算梯度时,我们计算损失 𝐿 相对于输入 x 的导数。 对于标准块(没有残差),梯度为

∂x/∂L = ∂F(x)/∂L * ∂F(x)/∂x

但是,对于残差块,其中 y = F(x) + x,梯度变为

∂L/∂x = ∂L/∂F(x) * ∂F(x)/∂x + ∂L/∂F(x) ⋅1

请注意,我们现在在梯度计算中有一个额外的项 1。 这意味着每层梯度都有直接返回到较早层的路径,从而改善梯度流并减少梯度消失的机会。 梯度更容易在网络中流动,从而使更深的网络能够训练而不会退化。

3. 为什么现在可以实现更深的网络:

ResNet 使训练具有数百甚至数千层的网络成为可能。 以下是更深的网络从中受益的原因

  • 恒等快捷连接:快捷连接执行恒等映射,其输出被添加到堆叠层的输出。 恒等快捷连接既不增加额外的参数,也不增加计算复杂性,这些连接绕过层,为信息流创建直接路径,并使神经网络能够学习残差函数 (F)。
  • 更好的梯度流:如前所述,残差有助于梯度在反向传播期间更好地传播,从而解决非常深的网络中的梯度消失问题。
  • 更易于优化:通过学习残差,网络本质上是将学习过程分解为更简单、渐进的步骤。 网络学习残差 R(x) = F(x) − x 比直接学习 F(x) 更容易,尤其是在非常深的网络中。

总结:

我们可以得出结论,ResNet 网络 -> 普通网络 + 快捷连接!

对于运算 (F(x) + x),(F(x)) 和 (x) 应该具有相同的维度。 ResNet 采用两种技术来实现这一点

  • 零填充快捷连接,添加具有零值的通道,在不引入要学习的额外参数的情况下保持维度。
  • 投影快捷连接,在必要时使用 1x1 卷积来调整维度,涉及一些额外的可学习参数。

在更深的 ResNet 架构中,如 ResNet 50、101 和 152,采用了一种专门的“瓶颈构建块”来管理参数复杂性并保持效率,同时实现更深层次的学习。

ResNet 代码

在 ImageNet 上预训练的深度残差网络

下面您可以看到如何使用 transformers 库加载具有图像分类头的预训练 ResNet。

from transformers import ResNetForImageClassification

model = ResNetForImageClassification.from_pretrained("microsoft/resnet-50")

model.eval()

所有预训练模型都期望输入图像以类似的方式进行归一化,即形状为 (3 x H x W) 的 3 通道 RGB 图像的小批量,其中 H 和 W 预计至少为 224。 图像必须加载到 [0, 1] 的范围内,然后使用 mean = [0.485, 0.456, 0.406] 和 std = [0.229, 0.224, 0.225] 进行归一化。

这是一个示例执行。 此示例可在 Hugging Face 文档中找到。

from transformers import AutoFeatureExtractor, ResNetForImageClassification
import torch
from datasets import load_dataset

dataset = load_dataset("huggingface/cats-image")
image = dataset["test"]["image"][0]

feature_extractor = AutoFeatureExtractor.from_pretrained("microsoft/resnet-50")
model = ResNetForImageClassification.from_pretrained("microsoft/resnet-50")

inputs = feature_extractor(image, return_tensors="pt")

with torch.no_grad():
    logits = model(**inputs).logits

# model predicts one of the 1000 ImageNet classes
predicted_label = logits.argmax(-1).item()
print(model.config.id2label[predicted_label])

参考文献

< > 在 GitHub 上更新