📒
OpenMMLab Book
  • 前言
  • Image Classification
    • 概述
      • LeNet-5
      • 数据集
      • 评价指标
    • 早期方法
      • AlexNet
      • VGGNet
      • Inception
    • 主流模型及技术
      • BN
      • ResNet
      • ResNeXt
      • SENet
    • 移动端模型
      • MobileNet
      • MobileNet v2
      • ShuffleNet
      • ShuffleNet v2
  • Object Detection
    • 概述
      • 问题定义
      • 朴素方法
      • 一些概念
      • 算法评价
    • 早期方法
      • RCNN
      • YOLO
    • 两阶段方法
      • Fast R-CNN
      • RPN
      • Faster R-CNN
      • Mask R-CNN
    • FPN
    • 单阶段方法
      • SSD
      • YOLO v2
      • YOLO v3
      • RetinaNet
    • 新的方向
      • Cascade R-CNN
      • FCOS
  • Semantic Segmentation
    • 概述
    • FCN
    • PSPNet
Powered by GitBook
On this page
  • 基本思路
  • 使用分组卷积实现多路残差
  • ResNeXt 的 PyTorch 实现

Was this helpful?

  1. Image Classification
  2. 主流模型及技术

ResNeXt

PreviousResNetNextSENet

Last updated 4 years ago

Was this helpful?

ResNeXt 是 2017 年 FAIR 提出的一个图像分类网络。ResNeXt 是基于 ResNet 的整体结构提出的一种改进结构。 受启发于 Inception 模块“分离-变换-合并”的思路,把 ResNet 中 BottleNeck 模块中的 64 通道的卷积替换为独立的 32 路 4 通道卷积运算,并在最后按通道合并起来。 这也等价为将 ResNet 的 BottleNeck 结构中的第二个卷积层替换为分组卷积层。 这种修改在保持参数和计算量基本不变的情况下,进一步提高了网络分类精度。 ResNeXt 在 2016 年的 ILSVRC 竞赛图像分类项目中取得了第二名的成绩。

基本思路

ResNet 的 BottleNeck 结构如下图左图所示,其残差分支由三个卷积层串联而成,输入通道数、卷积核大小、输出通道数从左到右标注在图中。 这三个卷积层分别负责压缩特征图的通道数、扩展感受野以及恢复特征图的通道数。

可以看出,中间 3x3 的卷积层占据了主要的参数量。

经过这种改造后,残差分支的参数总量变为为

使用分组卷积实现多路残差

ResNeXt 中的多路残差结构可以由分组卷积实现。为了理解这一点,让我们先来看一下分组卷积是如何计算的。

如果我们将空间维度也考虑进去,则分组卷积的前传计算为:

分组卷积在 AlexNet 中就有所应用。受到当时 GPU 显存的限制,AlexNet 在实现时使用了模型并行的技术,将同一层的特征图按通道切分成两部分,分别放在不同的 GPU 上,即组数为 2 。 在前传时,只有中间一个卷积层和最后的两个全连接层是全连接的,需要 GPU 间进行数据通信,其余卷积层均为组数为 2 的分组卷积,即使用各自 GPU 上的通道数减半的卷积核。

接下来,我们再考察如何使用分组卷积实现 ResNeXt 的多路残差结构。 辅助论文中的图示可以更好的理解。

经过这种替换,ResNeXt 的多路残差结构就可以等效变换为一个单路结构。这也是诸多深度学习框架所采用的实现方式。

ResNeXt 的 PyTorch 实现

由于 ResNeXt 的整体结构与 ResNet 完全相同,只要将残差分支中的普通卷积替换为分组卷积即可。由于 Pytorch 的 Conv2d类型直接支持了group参数,因此基于 ResNet 的代码实现 ResNeXt 是非常直接的。

我们知道,一个卷积层所包含的参数总数为 Nparam=CinCoutK2N_\text{param} = C_\text{in} C_\text{out} K^2Nparam​=Cin​Cout​K2 ,计算量正比于参数量 Nops=HoutWoutNparamN_\text{ops} = H_\text{out} W_\text{out} N_\text{param}Nops​=Hout​Wout​Nparam​ 。 因而 BottleNeck 结构的的参数总数为

256×64×2+64×64×9256\times 64 \times 2 + 64\times 64 \times 9256×64×2+64×64×9

为了降低计算量,ResNeXt 结构对 ResNet 的 BottleNeck 结构进行了改进。 ResNeXt 将残差分支扩展到 C=32C=32C=32 个,并将每个分支中中间层的输入和输出通道数降低至 d=4d=4d=4。 在 ResNeXt 结构中,CCC 称为 cardinality,ddd 称为 width。

C⋅(2×256×d+9×d×d)C \cdot (2 \times 256 \times d + 9 \times d\times d)C⋅(2×256×d+9×d×d)

如果我们控制 Cd=64Cd=64Cd=64 ,则中间层的参数量仅有 ResNet 结构的 1/C1/C1/C 。

如果我们控制参数量和 ResNet 相近,则可以得到如下 CCC 和 ddd 的配置。

其中,(C,d)=(32,4)(C, d)=(32, 4)(C,d)=(32,4) 是 ResNeXt 的常见配置,而 (C,d)=(64,1)(C, d)=(64, 1)(C,d)=(64,1) 时退化为 ResNet 。

在标准的卷积中,卷积核的通道数与输入特征图的通道数相同,我们记其为 CinC_\text{in}Cin​,卷积核的记为 CoutC_\text{out}Cout​。 在进行卷积运算时,所有 CoutC_\text{out}Cout​ 个卷积核的所有 CinC_\text{in}Cin​ 个通道都需要参与输入特征图的所有 CinC_\text{in}Cin​ 个通道进行内积运算。 形象地说,卷积核和输入特征图在通道维度是一个全连接的结构,如下图所示:

分组卷积则在通道上呈现一种局部连接的状态。 分组卷积将输入特征图按通道分成 GGG 组,每组 Cin/GC_\text{in} / GCin​/G 个通道,再将所有卷积核的通道也由 CinC_\text{in}Cin​ 缩减到 Cin/GC_\text{in} / GCin​/G 个。 在前传计算时,第 ggg 个卷积核只与第 ggg 组中的通道进行内积运算,如下图所示:

不难得出,分组卷积的参数量和计算量仅有普通卷积的1/G1/G1/G

y[h,w,c]=∑h′,w′=0K∑c′=0Cin/G−1x[h+h′,w+w′,gCinG+c′]⋅kc[h′,w′,c′]y[h,w,c]=\sum_{h',w'=0}^{K}\sum_{c'=0}^{C_\text{in} / G-1} x[h+h',w+w',g\frac{C_\text{in}}{G}+c'] \cdot k_c[h', w', c']y[h,w,c]=h′,w′=0∑K​c′=0∑Cin​/G−1​x[h+h′,w+w′,gGCin​​+c′]⋅kc​[h′,w′,c′]

其中, x,yx, yx,y 分别为输入和输出的特征图,kck_ckc​ 为第 ccc 个卷积核,其形状为 K×K×CinGK\times K\times \frac{C_\text{in}}{G}K×K×GCin​​ 。

在每个残差分支中,第一个卷积层都以同样的 256 通道特征图为输入,经由 ddd 个卷积核,输出 ddd 个通道的特征图。 我们可以把总共 CdCdCd 个卷积核集合起来,构成一个 CdCdCd 输出通道的卷积层。 这个合并的卷积层输出的 CdCdCd 通道的特征图与原结构中 CCC 分支,每分支 ddd 通道的特征图完全相同。 也就是说,合并的第一个卷积层与原结构中的 CCC 个卷积层等价。

每个分支的第二个卷积层以第一个卷积层输出的 ddd 通道特征为输入,经由 ddd 个卷积核,输出 ddd 通道的特征图,所有分支合计 CdCdCd 通道。 这等价于把合并后的 CdCdCd 个特征拆为 CCC 组,并使用分组卷积输出 CdCdCd 通道的特征图。 因此,所有分支的第二个卷积层可以等效合并为一个 CCC 组的分组卷积层。

每个分支的第三个卷积层以第二个卷积层输出的 ddd 通道特征为输入,经由 CdCdCd 个卷积核,输出 256 通道的的特征图,所有分支的输出求和作为最终结果。 从输出的角度看,每个通道的特征值是 CCC 个内积的和,每个内积是 ddd 通道特征图和卷积核对应通道相乘求和而得。 如果我们将所有卷积核按通道拼接,将所有输入特征图按通道拼接,则一个 CdCdCd 通道的内积操作就可以等效替代上述分别内积再求和的操作。 因此,所有分支的第三个卷积层可以合并为一个 CdCdCd 输入通道的卷积层。

在 torchvision 中,ResNeXt 也实现在 中,传入匹配的group和width参数给工厂函数_resnet,就可以实现分组卷积。

在 mmclassification 中,ResNeXt 实现在一个单独的文件 中。与 torchvision 不同 mmclassification 通过继承 ResNet 的 BottleNeck 残差模块和 ResNet 结构,在增加了对分组卷积的实现。

resnet.py
resnext.py
renset block vs resnext block
64通道的卷积
64通道16组的分组卷积