目录
前言
原论文名称:Designing Network Design Spaces
原论文下载地址:https://arxiv.org/abs/2003.13678.pdf
论文中提供的源码: https://github.com/facebookresearch/pycls
自己使用Pytorch实现的RegNet代码: Test10_regnet/model.py
近些年来,NAS(Neural Architecture Search)网络搜索技术非常火,但这对计算资源要求也比较高(都是大厂玩的东西)。包括这篇论文中的RegNet也有使用到NAS技术。但在论文中作者一再强调这篇论文与之前的一些NAS论文不同(例如MobileNetv3,EfficientNet),之前的一些有关NAS的论文都是在给定的设计空间(designed search space)中通过搜索算法去搜索出一组最佳参数组合。但在这篇论文中作者要探究的是如何去设计设计空间
(design design spaces)并发现一些网络的通用设计准则(network design principles),而不是仅仅去搜索出一组参数。原论文中有这么一段话:
The majority of work in NAS focuses on the search algorithm, i.e., efficiently finding the best network instances within a fixed, manually designed search space (which we call a design space). Instead, our focus is on a paradigm for designing novel design spaces. The two are complementary: better design spaces can improve the efficiency of NAS search algorithms and also lead to existence of better models by enriching the design space.
那RegNet的性能到底如何呢,参考原论文给出的一些指标:
- 在轻量级网络领域,低FLOPs的RegNet模型也能达到很好的效果,和MobileNetV2以及ShuffleNetV2性能有的一比。
- 与当时分类网络的天花板EfficientNet对比,可以看到
RegNetY-8.0GF
的错误率比EfficientNet-B5
更低,且推理速度(infer)快五倍。
设计设计空间
这篇论文中的主要内容基本都是在讲,如何从一个给定的原始设计空间AnyNet
一步步探索出最终的RegNet
空间。如下图所示,从最开始的设计空间A
到设计空间B
再到设计空间C
,随着加入的限制越来越多搜索范围越来越小,通过右侧的error-cumulative prob.
曲线可以看出,设计空间B
内的模型效果总体是要好于设计空间A
,而设计空间C
内的模型效果总体是要好于设计空间B
。这就是这篇论文在探索的事情。如果不想看论文中的设计过程,可以直接跳到后面的网络结构解析部分。
AnyNet Design Space
AnyNet设计空间是这篇论文中提出的最原始的设计空间,如下图所示:
在该设计空间中,网络的主体就是由三部分组成(stem
,body
,head
)。其中stem
和head
是固定不变的,stem
就是一个普通的卷积层(默认包含bn
以及relu
),卷积核大小为3x3
,步距为2,卷积核个数为32,head
就是分类网络中常见的分类器,由一个全局平均池化层和全连接层构成。所以网络中最主要的就是body
部分,body
是由4个stage
堆叠组成,而stage
是由一系列block
堆叠组成。但block
的详细结构以及参数并没有做任何限制,这就是AnyNet。
AnyNetX(A)Design Space
论文作者说,根据他们的经验将block
设计为standard residual bottlenecks block with group convolution
即带有组卷积的残差结构(和ResNext的block
类似),如下图所示,左图为block
的stride=1
的情况,右图为block
的stride=2
的情况:
由图可知,主分支都是一个1x1
的卷积(包括bn
和relu
)、一个3x3
的group卷积(包括bn
和relu
)、再接一个1x1
的卷积(包括bn
)。shortcut
捷径分支上当stride=1
时不做任何处理,当stride=2
时通过一个1x1
的卷积(包括bn
)进行下采样。图中的r
代表分辨率简单理解为特征矩阵的高、宽,当步距s
等于1时,输入输出的r
保持不变,当s
等于2时,输出的r
为输入的一半。w
代表特征矩阵的channel
(注意当s=2
时,输入的是
w
i
−
1
w_{i-1}
wi−1输出的是
w
i
w_i
wi即chennel
会发生变化)。g
代表group卷积中每个group的group width
,b
代表bottleneck ratio即输出特征矩阵的channel
缩减为输入特征矩阵channel的
1
b
\frac1b
b1.
此时就从AnyNet的设计空间缩小到AnyNetX空间了,该空间也称为
A
n
y
N
e
t
X
A
AnyNetX_A
AnyNetXA。此时的设计空间依旧很大,接着论文中说为了获得有效的模型,又加了些限制:
d
i
≤
16
d_i \leq 16
di≤16(有16种可能),
w
i
≤
1024
w_i \leq 1024
wi≤1024且取8的整数倍(有128种可能),
b
i
∈
{
1
,
2
,
4
}
b_i \in \left\{1, 2, 4\right\}
bi∈{1,2,4}(有3种可能),
g
i
∈
{
1
,
2
,
4
,
8
,
16
,
32
}
g_i \in \left\{1, 2, 4, 8, 16,32\right\}
gi∈{1,2,4,8,16,32}(有6种可能),其中
d
i
d_i
di表示stage
中重复block
的次数,由于body
中由4个stage
组成。那么现在还有大约
1
0
18
10^{18}
1018种模型配置参数(想要在这么大的空间去搜索基本不可能):
(
16
⋅
128
⋅
3
⋅
6
)
4
≈
1
0
18
(16\cdot128\cdot3\cdot6)^4\approx10^{18}
(16⋅128⋅3⋅6)4≈1018
AnyNetX(B)Design Space
接着作者又尝试将所有stage
中的block
的
b
i
b_i
bi都设置为同一个参数
b
b
b(shared bottleneck ratio
),此时的设计空间记为
A
n
y
N
e
t
X
B
AnyNetX_B
AnyNetXB,然后在
A
n
y
N
e
t
X
A
AnyNetX_A
AnyNetXA和
A
n
y
N
e
t
X
B
AnyNetX_B
AnyNetXB中通过log-uniform sampling
采样方法分别采样500的模型,并在imagenet
上训练10个epochs,绘制的error-cumulative prob.
对比如下图所示:
通过上图可以发现,将所有stage
中的block
的
b
i
b_i
bi都设置为同一个参数
b
b
b(shared bottleneck ratio
)后并没有什么明显的变化。
AnyNetX(C)Design Space
接着作者又尝试将所有stage
中的block
的
g
i
g_i
gi都设置为同一个参数
g
g
g(shared group width
),此时的设计空间记为
A
n
y
N
e
t
X
C
AnyNetX_C
AnyNetXC,和之前同样采样500个模型样本并进行训练接着与
A
n
y
N
e
t
X
B
AnyNetX_B
AnyNetXB进行比较,如下图所示:
通过上图可以发现,将所有stage
中的block
的
g
i
g_i
gi都设置为同一个参数
g
g
g(shared group width
)后并没有什么明显的变化。并且作者发现了一个有趣的现象当
g
>
1
g > 1
g>1时,效果会更好。
AnyNetX(D)Design Space
作者进一步分析了 A n y N e t X C AnyNetX_C AnyNetXC空间中效果好的模型以及效果差的模型,发现在好的模型中 w i w_i wi是呈现递增的趋势。如下图所示,第一行是效果好的模型 w i w_i wi的变化趋势,第二行是效果差的模型 w i w_i wi的变化趋势:
然后在
A
n
y
N
e
t
X
C
AnyNetX_C
AnyNetXC空间的基础上加上
w
i
+
1
≥
w
i
w_{i+1} \geq w_i
wi+1≥wi限制得到
A
n
y
N
e
t
X
D
AnyNetX_D
AnyNetXD空间。下图展示了不对
w
i
w_i
wi做限制以及对
w
i
w_i
wi做不同限制的对比,明显加上
w
i
+
1
≥
w
i
w_{i+1} \geq w_i
wi+1≥wi限制后效果更好:
AnyNetX(E)Design Space
作者在
A
n
y
N
e
t
X
D
AnyNetX_D
AnyNetXD空间中进一步分析,发现对于好的模型
d
i
d_i
di同样有递增的趋势(注意,这个趋势仅指stage1
到stage3
,不包括stage4
). 然后在
A
n
y
N
e
t
X
D
AnyNetX_D
AnyNetXD空间基础上加上
d
i
+
1
≥
d
i
d_{i+1} \geq d_i
di+1≥di的限制得到
A
n
y
N
e
t
X
E
AnyNetX_E
AnyNetXE空间。下图展示了不对
d
i
d_i
di做限制以及对
d
i
d_i
di做不同限制的对比,可以发现加上
d
i
+
1
≥
d
i
d_{i+1} \geq d_i
di+1≥di限制后效果更好:
RegNet Design Space
如下图所示,作者在
A
n
y
N
e
t
X
E
AnyNetX_E
AnyNetXE空间采样的一系列模型中选取了Top-20
,并绘制了他们每个block
输出特征矩阵的width
变化趋势。图中每一条灰色实线就代表一个模型。图中的黑色实线是作者通过一个线性函数来拟合的(注意图中的纵坐标刻度不是线性的,所以黑色的实线看着是一条曲线)。
w
j
=
48
⋅
(
j
+
1
)
f
o
r
0
≤
j
≤
20
w_j = 48 \cdot (j+1) \ \ \ \ \ {\rm for} \ \ \ 0 \leq j \leq 20
wj=48⋅(j+1) for 0≤j≤20
刚刚提到作者是用一个线性函数来拟合的,也就是说每个block
的width
都是不一样的,但在我们实际搭建网络过程中,每个stage
中的所有block
的width
应该是一样的,即应该是分段常数函数形式(piecewise constant function
)。所以接下来的工作就是去想办法获得这个分段常数函数(To see if a similar pattern applies to individual models, we need a strategy to quantize a line to a piecewise constant function.
)。接下来就是作者给出的关于获取分段常数函数的流程:
-
首先引入一个线性参数化函数,其中 j j j为
block
的索引, d d d为block
的总数量论文中称depth
,初始化 w 0 > 0 w_0 > 0 w0>0(线性函数中的 y = a x + b y=ax+b y=ax+b的 b b b),斜率 w a > 0 w_a > 0 wa>0, u j u_j uj为对应block
的width
:
u j = w 0 + w a ⋅ j f o r 0 ≤ j < d ( 2 ) u_j = w_0 + w_a \cdot j \ \ \ \ {\rm for} \ \ 0 \leq j < d \ \ \ \ (2) uj=w0+wa⋅j for 0≤j<d (2) -
为了量化 u j u_j uj,作者引入了一个新的参数 w m > 0 w_m > 0 wm>0,根据下面的公式(3)以及上面的公式(2)可以计算得到每个 u j u_j uj对应的 s j s_j sj:
u j = w 0 ⋅ w m s j ( 3 ) u_j = w_0 \cdot w_m^{s_j} \ \ \ \ \ (3) uj=w0⋅wmsj (3) -
接着将上一步计算得到的每个 u j u_j uj对应的 s j s_j sj进行四舍五入(记为 ⌈ s j ⌋ \left\lceil s_j \right\rfloor ⌈sj⌋),并根据下面的公式(4)可以得到量化后的 w j w_j wj:
w j = w 0 ⋅ w m ⌈ s j ⌋ ( 4 ) w_j = w_0 \cdot w_m^{\left\lceil s_j \right\rfloor} \ \ \ \ \ (4) wj=w0⋅wm⌈sj⌋ (4) -
其实在源码实现中还有两个小细节,一个是将刚刚计算得到的 w j w_j wj给调整到离他最近的8的整数倍。还有一个是会根据传入的参数 g g g(
Group Conv
中每个group
的group width
)进一步调整,将 w j w_j wj给调整到离他最近的 g g g的整数倍(详情可看下源码)。
通过上面公式我们就能对每个block
的width
进行量化,量化后相同的width
就属于同一stage
,如下图所示,作者也说了,该论文只讨论stage
的个数4的情况,所以使用论文中给的参数计算得到的stage
数肯定等于4:
通过以上分析,我们在
A
n
y
N
e
t
X
E
AnyNetX_E
AnyNetXE空间基础上指定
d
,
w
0
,
w
a
,
w
m
,
b
,
g
d,w_0, w_a, w_m, b, g
d,w0,wa,wm,b,g的值(通过上面的公式(2)-(4)可以得到block
的width
和depths
),那么整个网络的结构就固定了。所以作者称在
A
n
y
N
e
t
X
E
AnyNetX_E
AnyNetXE空间基础上使用
d
,
w
0
,
w
a
,
w
m
,
b
,
g
d,w_0, w_a, w_m, b, g
d,w0,wa,wm,b,g这6个自由变量来控制网络结构的空间为RegNet空间。接着我们再看论文中的一张表,下表展示了从
A
n
y
N
e
t
X
a
AnyNetX_a
AnyNetXa到
R
e
g
N
e
t
RegNet
RegNet空间的变化过程(记录了限制条件,自由度以及空间内所有可能的组合的数):
后面还有一些内容,大家可以去看下原论文,这里就不在赘述了。对于论文中给的每个网络的
d
,
w
0
,
w
a
,
w
m
,
b
,
g
d,w_0, w_a, w_m, b, g
d,w0,wa,wm,b,g参数在RegNetX/Y模型详细参数章节有给出,可通过本文目录跳转至相应章节。
RegNet网络结构详解
RegNet结构框架
首先看下下面这幅图,这幅图是原论文中给出的General Network structure
,Regnet的框架结构也是一样的。
(a)图中展示了网络主要由三部分组成,stem
、body
和head
。
- 其中
stem
就是一个普通的卷积层(默认包含bn
以及relu
),卷积核大小为3x3
,步距为2,卷积核个数为32. - 其中
body
就是由4个stage
堆叠组成,如图(b)所示。每经过一个stage
都会将输入特征矩阵的height和width缩减为原来的一半。而每个stage
又是由一系列block
堆叠组成,每个stage
的第一个block
中存在步距为2的组卷积(主分支上)和普通卷积(捷径分支上),剩下的block
中的卷积步距都是1,和ResNet类似。 - 其中
head
就是分类网络中常见的分类器,由一个全局平均池化层和全连接层构成。
RegNet block详解
接下来再看下论文中关于block
的结构图,(a)图为步距stride=1
的情况,(b)图是步距stride=2
的情况。
通过上图可知,文中的block
和ResNext
网络中的block
基本一致。主分支都是一个1x1
的卷积(包括bn
和relu
)、一个3x3
的group卷积(包括bn
和relu
)、再接一个1x1
的卷积(包括bn
)。shortcut
捷径分支上当stride=1
时不做任何处理,当stride=2
时通过一个1x1
的卷积(包括bn
)进行下采样。图中的r
代表分辨率简单理解为特征矩阵的高、宽,当步距s
等于1时,输入输出的r
保持不变,当s
等于2时,输出的r
为输入的一半。w
代表特征矩阵的channel
(注意当s=2
时,输入的是
w
i
−
1
w_{i-1}
wi−1输出的是
w
i
w_i
wi即chennel
会发生变化)。g
代表group卷积中每个group的group width
,b
代表bottleneck ratio即输出特征矩阵的channel
缩减为输入特征矩阵channel的
1
b
\frac1b
b1.
而在论文章节四中,作者给出了一个结论:
We also observe that the best models use a bottleneck ratio b of 1.0 (top-middle), which effectively removes the bottleneck (commonly used in practice).
就是说当b
取1时效果最好(感觉和ShuffleNetV2
中G1准则相似)。下面这副图是我重绘的,比原图要更清楚点。
这里还要注意一点,论文中有RegNetX和RegNetY,两者的区别仅在于RegNetY在block中的Group Conv后接了个SE(Squeeze-and-Excitation)模块。 自从SENet的提出,近些年的网络基本都会使用SE模块。在RegNet中的SE模块与EfficientNet中的SE模块类似。如下图所示,SE模块一般是由一个全局平均池化层和两个全连接层组成。在RegNet中,全连接层1(FC1)的节点个数是等于输入该block
的特征矩阵channel
的四分之一(不是Group Conv
输出特征矩阵channal
的四分之一),并且激活函数是ReLU。全连接层2(FC2)的节点个数是等于Group Conv
输出特征矩阵的channal
,并且激活函数是Sigmoid。
RegNetX模型详细参数
下图为论文中给出的不同FLOPs下的RegNetX模型详细参数。搭建网络我们仅需使用
d
i
d_i
di,
w
i
w_i
wi,
g
g
g这三个参数,加上刚刚讲的内容就能搭建网络了(
b
b
b参数都是1)。其中
d
i
d_i
di代表每个stage
重复block
的次数(前面说了body
都是由4个stage
堆叠组成的,所以
d
i
d_i
di中都是4个元素)。
w
i
w_i
wi代表每个stage
输出特征矩阵的channel
。
g
g
g代表block
中Group Conv
每个group的group width
。
至于
w
a
w_a
wa,
w
0
w_0
w0,
w
m
w_m
wm这三个参数是用来计算
d
i
d_i
di,
w
i
w_i
wi这两个参数的(在上文RegNet Design Space章节有讲,有兴趣的可以看下),在源码实现中都是通过
w
a
w_a
wa,
w
0
w_0
w0,
w
m
w_m
wm来计算
d
i
d_i
di,
w
i
w_i
wi的。但如果嫌麻烦,可以直接使用图中标注好的
d
i
d_i
di,
w
i
w_i
wi参数。
下表展示了RegNetX这一系列网络在ImegeNet上训练100epoch后的top-1 error
。
RegNetY模型详细参数
下图为论文中给出的不同FLOPs下的RegNetY模型详细参数(刚刚也说了,RegNetY和RegNetX在结构上的唯一不同就是在Group Conv
后加上了Squeeze-and-Excitation
模块)。同样我们仅需使用
d
i
d_i
di,
w
i
w_i
wi,
g
g
g这三个参数即可搭建出网络。其中
d
i
d_i
di代表每个stage
重复block
的次数。
w
i
w_i
wi代表每个stage
输出特征矩阵的channel
。
g
g
g代表block
中Group Conv
每个group的group width
。
下表展示了RegNetY这一系列网络在ImegeNet上训练100epoch后的top-1 error
。