Lightweight Backbones

Apr 25, 2024
1 views
Computer Vision

💡 轻量级网络系列

Introduction

Inception

在最初的版本 Inception/GoogleNet,其核心思想是利用多尺寸卷积核去观察输入数据。举个栗子,我们看某个景象由于远近不同,同一个物体的大小也会有所不同,那么不同尺度的卷积核观察的特征就会有这样的效果。于是就有了如下的网络结构图:

image

于是我们的网络就变胖了,通过增加网络的宽度,提高了对于不同尺度的适应程度。但这样的话,计算量有点大了。

Point-wise Conv

为了减少在上面结构的参数量并降低计算量,于是在 Inception V1 的基础版本上加上了 1x1 卷积核,这就形成了 Inception V1 的最终网络结构,如下图。

image

这个 1x1 卷积就是 Pointwise Convolution,简称 PW。利用它的目的主要是为了减少维度,还用于引入更多的非线性。

我们来简单计算下:假定上一层输出的 feature map 维度为 100x100x128,经过256个大小为 5x5 的卷积后,输出的 feature map 大小为 100x100x256。这里卷积参数为 \(256∗5∗5∗128=819,200\)。而假如上一层的输出先经过 32 个大小为 1x1 的卷积后,再经过256个大小为 5x5 的卷积,那么输出维度保持不变的情况下,卷积参数减少为 \(128∗1∗1∗32 + 32∗5∗5∗256=204,800\),降低为原来的 \(204800/819200=1/4\)

PW 主要用于数据降维,减少参数量。也有使用 PW 做升维的,在 MobileNet v2 中就使用 PW 将 feature map 的宽度扩张了6倍,丰富输入数据的特征。

Kernel Replace

Inception V2 和 V3 版本为了进一步降低卷积参数采用小卷积来替换大卷积,同 VGG 套路。

image

大尺寸的卷积核可以带来更大的感受野,但也意味着会产生更多的参数,比如 5x5 卷积核的参数有 25 个,3x3 卷积核的参数有 9 个,前者是后者的 25/9=2.78 倍。因此,GoogLeNet 团队提出可以用 2 个连续的 3x3 卷积层组成的小网络来代替单个的 5x5 卷积层,即在保持感受野范围的同时又减少了参数量。除了规整的的正方形,还有分解版本的 3x3 = 3x1 + 1x3,这个效果在深度较深的情况下比规整的卷积核更好(feature map 大小建议在 12 到 20 之间)。

Feature Map Downsample

一般情况下,如果想让图像缩小,可以有如下两种方式:

image

先 pooling 再作 Inception 卷积,或者先作 Inception 卷积再作 Pooling。前者先作 Pooling 会导致特征缺失遇到 bottleneck,后者则相对来说计算量更大。为了同时保持特征表示且降低计算量,将网络结构改为下图,使用两个并行化的模块来降低计算量(卷积、池化并行执行,再进行合并)。

image

Bottleneck

Bottleneck 三步走:先 PW 对数据进行降维,再进行常规卷积,最后 PW 对数据进行升维,形如沙漏。

image

这就是所谓的 Bottleneck 结构,上图中后者的计算量 \(256∗1∗1∗64+64∗3∗3∗64+64∗1∗1∗256=69,632\) 远小于前者$ 256∗3∗3∗256=589,824$。

Inception + ResNet

image

Group Conv Depthwise Separable Conv

Group Convolution 分组卷积,最早见于AlexNet,当时受限于硬件,Group Convolution被用来切分网络,使其在2个GPU上并行运行。

让我们先来回顾下常规卷积。对于输入为 𝐼x𝐻x𝑊 大小的 Input Features,经过 𝑂 个 𝐾x𝐾x𝐼 大小的卷积核后,输出 Output Features 的通道数也是 𝑂。这里的卷积参数量为 𝑂∗𝐾∗𝐾∗𝐼,输入和输出 map 的连接方式如下图左所示,输出的每个通道都和输入的所有通道相关联:

image

Group Conv 顾名思义,则是对输入 feature map 进行分组,然后每组分别卷积。假设输入 feature map 的尺寸仍为 𝐼x𝐻x𝑊,输出 Output Features 的通道数也是 𝑂,如果设定要分成 𝐺 个 groups,则每组的输入 feature map 数量为 \(\frac{I}{G}\),每组的输出 feature map 的数量为 \(\frac{𝑂}{𝐺}\),每个卷积核的尺寸为 \(𝐾\times 𝐾\times \frac{𝐼}{𝐺}\),每组的卷积核数量为 \(\frac{O}{𝐺}\),卷积核的总数仍为 𝑂 个,卷积核只与其同组的输入 map 进行卷积,卷积核的总参数量为 \(𝑂∗𝐾∗𝐾∗\frac{𝐼}{𝐺}\),可见,总参数量减少为原来的 \(\frac{1}{𝐺}\),其连接方式如上图右所示,group1 输出 map 数为 2,有 2 个卷积核,每个卷积核的 channel 数为 4,与 group1 的输入 map 的 channel 数相同,卷积核只与同组的输入 map 卷积,而不与其他组的输入 map 卷积。

Group Conv 的用途包括:

  • 减少参数数量,分成 \(G\)组,则该层的参数量减少为原来的\(\frac{1}{G}\)
  • Group Conv 可以看成是一种 structured sparse,每个卷积核的尺寸由 \(K\times K\times I\) 变成了\(K\times K\times \frac{I}{G}\),这里可以将其余的 \(1-K\times K\times \frac{I}{G}\) 维的参数视为 0。实际中,Group Conv 在减少参数量的同时有可能获得更好的效果(相当于正则)。
    Depthwise Convolution 其实是 Group Conv 的一种特例,简称 DW。当分组数量等于输入 map 数量,输出 map 数量也等于输入 map 数量,即 𝐺=𝑂=𝐼,𝑂 个卷积核每个尺寸为 𝐾x𝐾x1 时,Group Convolution 就成了Depthwise Convolution。Depthwise Separable Convolution 则是DW+PW 的组合体,如图,参见 Xception 等,参数量进一步缩减。

image

更进一步,如果分组数 𝐺=𝑂=𝐼,同时卷积核的尺寸与输入 map 的尺寸相同,即 𝐾=𝐻=𝑊,则输出 map 为 𝐼x1x1 即长度为 𝑂 的向量,此时称之为 Global Depthwise Convolution (GDC),见 MobileFaceNet,可以看成是全局加权池化,与 Global Average Pooling (GAP) 的不同之处在于,GDC 给每个位置赋予了可学习的权重(对于已对齐的图像这很有效,比如人脸,中心位置和边界位置的权重自然应该不同),而 GAP 每个位置的权重相同,全局取个平均,如下图所示:

image

Xception

Xception 实际上就是从另一个角度来思考 Inception 的网络结构,同时在 Inception 的基础上将 Depthwise Separable Conv 发扬光大了!

1. The Inception Hypothesis

初始的 Inception V1 结构考虑从多尺度卷积核角度来观察输入数据的特征,Inception V3 则是从参数量和计算量角度来尝试改进。但我们也可以把 Inception V3 结构理解为:通过显式地将操作分解为一系列独立的通道相关性和空间相关性的学习,从而使得学习的过程变得更加简单和高效。具体来说,Inception V1 里各个卷积核需要同时学习空间上的相关性和通道间的相关性,结合了 spatial dimensions 和 channels dimensions;而 Inception V3 结构,先通过一组 1x1 PW 卷积来学习通道相关性,将输入数据映射到多个单独的小空间(降维了),然后对于所有这些小空间,通过常规的 3×3 卷积,5×5 卷积等来学习空间相关性。因此,Inception 结构背后的基本假设是,通道相关性和空间相关性之间的耦合性已经充分分离,这样的话最好不要将它们联合起来学习。于是便有了 Xception:将通道相关性和空间相关性分开学习的结构设计

2. Extreme Inception

在 Inception 中,特征可以通过 1×1 卷积,3×3 卷积,5×5 卷积,pooling 等进行提取,Inception 结构将特征类型的选择留给网络自己训练,也就是将一个输入同时输给几种提取特征方式,然后做 concat 。Inception-v3的结构图如下:

image

对 Inception-v3 进行简化,去除 Inception-v3 中的 avg pool 后,输入的下一步操作就都是 1×1 PW 卷积了:

image

再进一步假设,3 个 PW 卷积核统一起来变成共用一个 PW 卷积,后面的三个 3x3 卷积核则分别”负责“一部分通道(Group Conv):

image

最后 Extreme Inception 闪亮登场,对 PW 卷积后的每个channel分别进行 3×3 卷积操作(Depthwise Conv, DW}),最后将结果 concat:

image

作者发现,在 Extreme Inception 模块中,用于学习空间相关性的 3×3 的 DW 卷积,和用于学习通道间相关性的 1×1 PW 卷积之间,不使用非线性激活函数时,收敛过程更快、准确率更高。

3. Xception

Xception 常用版本是将 DW 和 PW 交换了个位置:Extreme Inception 先进行 1×1 PW 卷积,再进行 3×3 DW 卷积;Depthwise Separable Conv 先进行 3×3 DW卷积,再进行 1×1 PW 卷积(作者认为这个差异并没有大的影响)。

理论上计算量相比:

\[ \begin{aligned} & P_{DW} = I*K*K + I*O \\ & P_{Normal} = I*K*K*O \\ & \frac{P_{DW}}{P_{Normal}} = \frac{1}{O} + \frac{1}{K^2} \approx \frac{1}{K^2} \end{aligned} \]

其中 𝐼 为输入通道数,𝑂 是输出通道数,𝐾 是标准卷积核大小。我们可以看到,当我们使用 3x3 卷积核的时候,参数量约等于标准卷积核的 1/9,大大减少参数量,从而加快训练速度。

MobileNet v1

MobileNet V1 理解起来就是对 Depthwise Separable Convolution 的加强使用。

结构上同 Xception 的区别在于,这里每个卷积之后都有 BN + ReLU 单元,如下图 所示。

image

由于 DW 的计算量较低,因此几乎所有(95% of the computation time and 75% of the parameters)的计算量都集中于密集的 1×1 PW 里。特别的,与训练大型模型相反,这里使用较少的正则化和数据增强技术,因为小型模型的过拟合问题较少。训练策略基本上同 Inception V3,但作者建议较少甚至不使用 weight decay (l2 regularization) 在 DW 中,因为这个层的参数本来就很少了。

文中引入了两个超参数 \(\alpha\) 和 \(\rho\)

  1. \(\alpha\) 是个 width multiplier, 目的是降低 feature map 的宽度(channel)以减少计算复杂度和参数数量(大概\(\alpha^2\))的作用,其取值范围为 (0,1], 其中 \(\alpha =1\) 代表 baseline MobileNet。Table 6 对比了 width multiplier \(\alpha\) 大小对网络性能的影响:
  2. \(\rho\) 是个 resolution multiplier, 目的是降低 imput image 的尺度以减少计算复杂度(大概\(\rho^2\))和参数数量的作用,其取值范围为 (0,1], 其中 \(\rho =1\) 代表 baseline MobileNet。Table 7 对比了 resolution multipliers \(\rho\) 大小对网络性能的影响:

MobileNet V2

MobileNet V2 则可以理解为 Depthwise Separable Convolution + ResNet。

在最早的 Network in Network 工作中, 1x1 PW 卷积被作为一个降维的操作而引入,后来逐渐发展为 Depthwise Separable Convolution 并被广泛应用,堪称跟 skip-connection 同样具有影响力的网络部件。在 Inception 单元最初提出之时,认为具有较多 channel 的 feature map 是可以压缩的,作者引入 PW  卷积将它们映射到低维(较少 channel 数)空间上并添加多路径处理的范式。之后的 Xception、MobileNet 等工作则将可分离卷积应用到极致:前者指出可分离卷积背后的假设是跨channel相关性和跨spatial相关性的解耦,后者则利用可控的两个超参来获得在效率和精度上取得较好平衡的网络。

Linear Bottlenecks

文中,经过激活层后的张量被称为兴趣流形,具有维HxWxD,其中D即为通常意义的channel数,部分文章也将其称为网络的宽度(width)。

根据之前的研究,兴趣流形可能仅分布在激活空间的一个低维子空间里,利用这一点很容易使用 1x1 PW 卷积将张量降维(即 V1的工作),但由于ReLU的存在,这种降维实际上会损失较多的信息。作者做了一个信息重构的实验,实验结论就是:激活函数在高维空间能够有效的增加非线性,而在低维空间时则会造成较大的信息损失。如下图所示:当原始输入维度数增加到 15 以后再加 ReLU,基本不会丢失太多的信息;但如果只把原始输入维度增加至 2∼5后再加 ReLU,则会出现较为严重的信息丢失。因此执行降维的卷积层后面不会接类似于 ReLU 这样的非线性激活层。

image

Depthwise Separable Convolutions

作者通过下图 描述了深度可分离卷积的演化史:(a) 中普通卷积将 channel 和 spatial 信息同时进行映射,参数量较大;(b) 为可分离卷积,解耦了 channel 和 spatial,有一定比例的参数节省;(c) 中进行可分离卷积后又添加了 bottleneck,映射到低维空间中;(d) 则是从低维空间开始,进行可分离卷积时扩张到较高的维度(前后维度之比被称为expansion factor,扩张系数),之后再通过1x1卷积降到原始维度。

image

继续上面信息损耗的话题,深度可分离卷积大大降低参数量的同时也带来了信息损失的风险。V2 采用了 Figure(d) 的类似结构(区别在于最后一层无激活函数),考虑到 DW 卷积的计算特性决定它自己没有改变通道数的能力,因此,给每个 DW 之前都配备了一个 PW,专门用来升维,定义升维系数 𝑡=6,这样不管输入通道数 𝐶𝑖𝑛 是多是少,经过第一个 PW 升维之后,DW 都是在相对的更高维 (𝑡⋅𝐶𝑖𝑛) 进行工作的。因此可以发现,V2 结构里每个 Bottleneck 的输入通道都很小,并按照 “扩张 - 变换 - 压缩” 的形式搭建模型。

Inverted Residuals

为了提升网络结构的性能,综合上面的两个改进,作者还引入了 ResNet 结构,构成了作者所说的 Inverted Residual,如 (b) 所示。

image

以前大多数的模型结构加速的工作都停留在压缩网络参数量上。其实这是有误导性的:参数量少不代表计算量小;计算量小不代表理论上速度快(带宽限制)。ResNet 的结构其实对带宽不大友好:旁路的计算量很小,eltwise+ 的特征很大,所以带宽上就比较吃紧。而 Inverted residual 由于 eltwise+ 的特征较小的原因,缓解了这一问题。

image

ResNeXt

ResNeXt 这篇文章看到最后你会发现,原来就是 ResNet + Group Conv 的组合罢了。但是,和 Xception 论文套路一样,作者是经过一步步理论证明了的。

论文一开始采用  VGG stacking 的思想和 Inception 的 split-transform-merge 思想,这里有一个超参数 cardinality (the size of the set of transformations),如图所示:

image

论文中表示增加 cardinality 比增加网络的深度和宽度更有效。随后作者展示了三种相同的 ResNeXt blocks: Figure(a) 被称为 aggregated residual transformations。Figure (b) 采用了两层卷积后 concatenate,再卷积,有点类似 Inception-ResNet,只不过这里的 paths 都是相同的拓扑结构。Figure 15(c) 采用的是 grouped convolutions,这个 group 参数就是 caffe 的 convolusion 层的 group,最后把 channels 合并。作者在文中明确说明这三种结构是严格等价的,并且用这三个结构做出来的结果一模一样,在论文中展示的是 Figure (c) 的结果,因为 Figure (c) 的结构比较简洁而且速度更快。

image

实验中,为了控制网络参数量,作者利用 𝐶(cardinality) 和 𝑑(width of bottleneck) 两个超参数来进行平衡(ResNeXt50_32Cx4d≈ResNet50),这里面 \(𝑤𝑖𝑑𝑡ℎ\ 𝑜𝑓\ 𝑏𝑜𝑡𝑡𝑙𝑒𝑛𝑒𝑐𝑘\ ∗\ 𝑐𝑎𝑟𝑑𝑖𝑛𝑎𝑙𝑖𝑡𝑦=𝑤𝑖𝑑𝑡ℎ\ 𝑜𝑓\ 𝑔𝑟𝑜𝑢𝑝\ 𝑐𝑜𝑛𝑣.\)

ShuffeNet V1

1. Shuffe units

ShuffleNet V1 可以理解为进一步加强对 Group Conv 和 DW 的使用程度。该论文认为 Xception 里 DW 之后的 PW 计算量太大了,何不也换成 1x1 的 DW 。但是,如果多个 group convolutions 叠加在一起,就会产生一个副作用:某一通道的输出只来自一小部分输入 channels。下图(a) 为两组叠加卷积层的情况。很明显,某个组的输出只与组内的输入相关。这会阻塞通道组之间的信息流并削弱特征表示。

image

如 Figure(b),如果我们让 Group Conv 的输入来自不同的 group(其实 LeNet5 里就是这样的),那么输入和输出通道间信息就可以完全连接起来了。实际操作时有个效率问题,进行每个 group 计算时都要把整个 input feature 加载进来。因此按照图 Figure 34(c),可以事先将输入的 input feature 通过 reshape, transpose and flatten 操作来进行 Channel Shuffle(借鉴了 AlexNet 训练时候的方法),然后计算输出的 feature map 的时候,只要导入需要的输入的 feature map 而不是进行全局索引。

利用 Channel Shuffle 的特性,本文设计了一个 ShuffleNet Unit。基础网络是ResNet-18,如 F(a),这是一个 residual block,第一个 1x1 的 PW 用来降维,后面的 3x3 是一个 DW,随后跟着一个 1x1 的 PW 升维。我们在设计时,将第一个 1x1 的 PW 替换成 pointwise group conv,随后通过 Channel Shuffle 操作送给 3x3 的 DW,最后一个 pointwise group conv 目的是升维。为了方便,作者没有在第二个 PW layer 后面加上 Channel Shuffle 操作,因为对性能没有提升。其他改动方面,作者没有在 DW 层加上 ReLU。对于 stride=2 的情况下,作者增加了一个 average pooling 和改变了 element wise add 为 concat 操作。

image

虽然 DW 的理论计算量很低,但在实际低功耗硬件上比较难高效实现。因此作者只在 bottleneck feature maps 上使用。