ResNet 网络中的残差单元

今晚看《深度学习推荐系统实战》这本书,读到这样一句话,残差单元中的两层 ReLU 网络其实拟合的是输出和输入之间的“残差” x o − x i x^o-x^i xoxi ,想看看微信读书的 AI 问书新功能对这句话怎么理解,原以为会像其他大模型一样,弹出一个对话窗口输入问题,没想到它直接给出了答案,而且还给出了书籍引源、可能想问的问题,我刚好在问题列表中找到想继续深入问的问题,虽然最后给出的答案不太满意,我用它给出的相关问题去 GPT 深入了解了残差单元,但这个用户体验设计很棒。

下面我们来看一下残差单元是什么回事。

残差单元是一种常见的神经网络架构组件,在 ResNet 架构中首次提出。考虑一个图像识别的任务,在带有残差单元的网络(如 ResNet )中,残差单元的工作流程如下:

  • 输入:残差单元接收一个输入 x 。
  • 主路径:输入 x 首先通过两个卷积层进行处理,这两个卷积层尝试学习输入和输出之间的残差(即变化)。假设这两个卷积层之间还有激活函数 ReLU 。
  • 跳跃连接:残差单元包含一个“跳跃连接”(或称为快捷连接),它允许输入 x 直接跳过这两个卷积层,与卷积层的输出相加。
  • 输出:最终的输出是主路径上卷积层的输出(残差)与输入 x 直接相加的结果。这意味着如果没有必要的变化,即如果一个残差单元的输入已经足够接近最终的目标输出,那么该单元可以学习输出一个接近于零的残差。这样,该单元的输出几乎等于其输入,从而实现了仅将输入“传递”到输出,而无需进一步的复杂变换。

残差单元的操作可以被视为:

y = x + F ( x ) y = x + F(x) y=x+F(x)

其中 x 是输入, F(x) 是经过卷积层的变换后得到的残差, y 是输出。

  • 如果 F(x) 接近于零,那么 $ y \approx x $。这意味着残差单元基本上是在做恒等变换,即直接传递输入到输出。
  • 如果 F(x) 不接近于零,说明输入 x 需要通过 F(x) 进行变换以达到理想的输出 y 。

我们来看一段 PyTorch 实现残差单元的代码,

import torch
import torch.nn as nn
import torch.nn.functional as F

class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super(ResidualBlock, self).__init__()
        # 第一个卷积层,使用3x3卷积核,改变通道数和尺寸
        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)
        # 维度匹配层,使用1x1卷积调整输入的通道数和尺寸
        self.downsample = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
            nn.BatchNorm2d(out_channels)
        )

    def forward(self, x):
        identity = x

        # 主路径
        out = self.conv1(x)
        out = self.bn1(out)
        out = F.relu(out)
        out = self.conv2(out)
        out = self.bn2(out)

        # 调整原始输入的尺寸和通道数以匹配主路径输出
        identity = self.downsample(x)

        # 将调整后的输入与主路径输出相加
        out += identity
        out = F.relu(out)

        return out

如果步长不为 1 或输入输出通道不一致,可以通过维度匹配层,调整输入以便能加到输出上。维度匹配层(通常是一个包含 1x1 卷积的层)在残差单元中的作用是调整输入的维度,使其与残差路径的输出尺寸匹配,从而可以将两者相加。这是在残差网络(如 ResNet )中处理输入和输出通道数不匹配或步长改变导致的尺寸变化时常用的技术。它通常有两个作用:

  • 通道数调整:当输入和输出的通道数不一致时,1x1 卷积可以用来改变通道数,以匹配残差路径的输出。
  • 空间维度调整:当步长不为 1 时,卷积操作通常会改变特征图的高度和宽度。使用 1x1 卷积和适当的步长可以相应地调整输入的空间维度,使其与输出的高度和宽度匹配。

例如,假设我们有一个输入特征图,其尺寸为 56 × 56 × 64(高度56,宽度56,通道数64)。现在我们想通过一个残差块,使输出特征图的尺寸变为 28 × 28 × 128
(即通道数增加,同时特征图大小减半)。

在这个例子中,输入尺寸 56 × 56 × 64 通过设置 stride=2 在 conv1 层被减半到 28 × 28 ,同时通道数增加到 128 。由于原始输入和经过 conv1 和 conv2 后的输出在尺寸和通道数上都不匹配,我们使用一个 1x1 卷积的维度匹配层来调整输入的通道数和尺寸,使之能够与残差路径的输出相加。这样, identity 与 out 的尺寸和通道数均相同,可以直接进行相加操作。


微信公众号「padluo」,分享数据科学家的自我修养,既然遇见,不如一起成长。关注【老罗说AI】公众号,后台回复【文章】,获得整理好的【老罗说AI】文章全集。

数据分析二维码.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值