从ResNet开始,InceptionV4、Xception、ResNext、MobileNet、ShuffleNet,EfficientNet,以及2017CVPR的best paper的DenseNet都是借用了ResNet的思想,是被称之为“神来之笔”的一种思想。
ResNeXt:https://arxiv.org/pdf/1611.05431.pdf
pytorch 代码:https://github.com/prlz77/ResNeXt.pytorch
可以参考ResNeXt网络讲解。
从此篇之后不再给出代码,只是各种网络的思想。
贡献
网络结构简明,模块化
需要手动调节的超参少
与 ResNet 相比,相同的参数个数,结果更好:一个 101 层的 ResNeXt 网络,和 200 层的 ResNet 准确度差不多,但是计算量只有后者的一半
ResNeXt网络思想
ResNeXt主要借鉴了VGG和Inception网络的思想,VGG在设计时采用堆叠的方式,同一模块中的像filter_size, filter_channel等超参数都保持一致; Inception网络采用split-transform-merge 策略,首先利用1×1卷积将输入映射到嵌入空间,之后再利用像3×3、5×5等卷积对嵌入空间的特征进行转换,最后将不同分支的特征利用concatenation进行融合。但是Inception网络每个分支的超参数较多,需要进行特别的设计。因此,作者借鉴了VGG堆叠的思想和Inception网络split-transform-merge 的结构,在增加准确率的同时基本不改变或降低模型的复杂度。结构如下图所示。
图1 左图为基本残差单元,右图为ResNeXt中的残差单元
提出的残差单元与Inception的结构类似,但是该结构每个分支的超参数都是相同的(这也是和 Inception 的差别,减轻设计负担),相当于进行了一个横向的堆叠,这样可以避免繁重的超参数调节工作。其中作者称分支的数量(图中为32)为 cardinality, 文中解释为 the size of the set of transformations, 作者也在实验中证明了增加cardinality比增加网络的深度和宽度更加有效。
提出的残差单元
对于一个简单的神经元,其计算过程可以用如下公式表示, 输入
x
x
x是一个
D
D
D维的向量。如图1所示, 可以看出神经元的计算过程就是一个split-transform-merge的策略,它首先将输入split到一个低纬度的嵌入式空间,然后利用简单的缩放:
w
i
x
i
w_{i}x_{i}
wixi对低纬度的嵌入式 特征进行transform,最后利用用
∑
i
=
1
D
\sum_{i=1}^{D}
∑i=1D将嵌入特征进行整合。作者借鉴该模板,提出的block可以用公式2进行表示,式中
T
i
\mathcal{T}_{i}
Ti 可以是一个任意的函数,
C
C
C为cardinality,
C
C
C可以不等于
D
D
D,可以为任意数字,同时作者在设计时保证了
T
i
\mathcal{T}_{i}
Ti是相同的,
T
i
\mathcal{T}_{i}
Ti采用了如图1右面所示的bottleneck-shaped的结构,公式2可以改写为公式3。与Inception-ResNet不同的是这里在每个分支采用了相似的结构。
公式1:
∑
i
=
1
D
w
i
x
i
\sum_{i=1}^{D}w_{i}x_{i}
∑i=1Dwixi
公式2:
F
(
x
)
=
∑
i
=
1
C
T
x
F(x)=\sum_{i=1}^{C}\mathcal{T}_{x}
F(x)=∑i=1CTx
公式3:
y
=
x
+
∑
i
=
1
C
T
x
y=x+\sum_{i=1}^{C}\mathcal{T}_{x}
y=x+∑i=1CTx
ResNeXt block结构
作者展示了三种相同的 ResNeXt blocks。fig3.a 就是前面所说的aggregated residual transformations。 fig3.b 则采用两层卷积后 concatenate,再卷积,有点类似 Inception-ResNet,只不过这里的 paths 都是相同的拓扑结构。fig 3.c采用的是grouped convolutions,这个 group 参数就是 caffe 的 convolusion 层的 group 参数,用来限制本层卷积核和输入 channels 的卷积。关于分组卷积可以参考:Group Convolution分组卷积,以及Depthwise Convolution和Global Depthwise Convolution
在实际应用中也是采用的fig3.c的结构。这里 fig 3.c 采用32个 group,每个 group 的输入输出 channels 都是4,最后把channels合并。作者在文中明确说明这三种结构是严格等价的,并且用这三个结构做出来的结果一模一样,在本文中展示的是 fig3.c 的结果,因为 fig3.c 的结构比较简洁而且速度更快。
网络参数
可以看出两者的参数量基本一致。另外,每个卷积也是采用ResNet v1中BN和RELU放在卷积后面的形式,并没有采用ResNet v2结构。
以上图为例,中括号内就是 split-transform-merge,通过 cardinality© 的值控制 repeat layer。
output 在上下相邻的格子不断减半,中括号内的逗号后面卷积核的个数不断翻倍。
实验
Cardinality vs. Width
cardinality与
d
d
d之间的关系如下图所示, 第二行的
d
d
d表示每个path的中间channels数量,最后一行则表示整个block的宽度,是第一行
C
C
C和第二行
d
d
d的乘积。对于原始残差单元,也就是图1左图,每个block的参数量为
256
⋅
64
+
3
⋅
3
⋅
64
⋅
64
+
64
⋅
256
≈
70
k
256 ⋅ 64 + 3 ⋅ 3 ⋅ 64 ⋅ 64 + 64 ⋅ 256 ≈ 70k
256⋅64+3⋅3⋅64⋅64+64⋅256≈70k, 而提出的block参数量可以用
C
⋅
(
256
⋅
d
+
3
⋅
3
⋅
d
⋅
d
+
d
⋅
256
)
C⋅(256⋅d+3⋅3⋅d⋅d+d⋅256)
C⋅(256⋅d+3⋅3⋅d⋅d+d⋅256) 表示,为了保证两者的参数量近似相等,在
C
=
32
C = 32
C=32时,
d
=
4
d = 4
d=4。
作者在上图的设置下进行了实验, 增加cardinality相当于降低分支宽度d, 可以看出增加cardinality模型准确率得到提升。同时可以看出4d 相对于 14d并没有提升很多,所以作者就没有继续减小d。
Increasing Cardinality vs. Deeper/Wider
增加宽度就是简单地增加filter channels。第一个是基准模型,增加深度和宽度的分别是第三和第四个,可以看到误差分别降低了0.3%和0.7%。但是第五个加倍了Cardinality,则降低了1.3%,第六个Cardinality加到64,则降低了1.6%。显然增加Cardianlity比增加深度或宽度更有效。
本质: ResNeXt和ResNet相比,本质上是引入了group操作同时加宽了网络(在不增加complixity的情况下,通过增加cardinility达到间接增加width的效果),可以看Figure1,每个block的前两个卷积层宽度和原来ResNet相比增加了一倍。宽度增加应该是效果提升的主要来源。但是如果不用group操作,单纯增加宽度的话,显然计算量和参数要增加不少,因此采用group操作可以减少计算量和参数量。
普通卷积和组卷积的参数量计算(组卷积的参数量是普通卷积的g分之一):