论文名称:Densely Connected Convolutional Networks
作者:Gao Huang \ Zhuang Liu\ Laurens van der Maaten\Kilian Q. Weinberger
论文地址:http://openaccess.thecvf.com/content_cvpr_2017/papers/Huang_Densely_Connected_Convolutional_CVPR_2017_paper.pdff
发表年份:CVPR 2017
本文发表在CVPR2017,当年的best paper!提出的Dense Connectivity
把特征利用到了极致,达到了比Resnet参数更少、计算量更小,但性能更好的效果。也有缺点,训练需要耗费大量内存,虽然官方也给出了节省内存的实现方式,但目标检测实例分割的高层模型中很少见到有人用它作为主干网络(backbone)。
1 动机
Resnet的成功证明了shortcut
的有效性,但Resnet有两个缺点:
- 随机深度网络[1]证明了Resnet网络层的冗余性
- 每一层的输入(out_last_layer+x)使用的仍然只是少数层的特征,有大量的特征闲置
Resnet网络的冗余性主要因为这些冗余层会逐渐变成恒等映射(Identity Mapping),与其不停地学习到相同的特征,为什么不直接把原来的特征拿过来用呢。
2 贡献
- 跳出Resnet加深网络和Googlenet加宽网络的思维框架,提出
Dense Connectivity
,把每一层网络层特征利用到极致 - 提出
growth rate
,有效降低参数量和计算量 - 本文中的思想简单易于实现,但十分有效,大道至简的又一实例
3 方法
记:
- 网络的初始输入是一张图像 x 0 x_0 x0
- 网络包含 L L L层,每一层实现的映射是 F l ( ∗ ) F_l(*) Fl(∗),其中 l l l表示第 l l l层, F l ( ∗ ) F_l(*) Fl(∗)可以是包含BN/ReLU/Conv的复合映射。(原文中是使用的 H l ( ∗ ) H_l(*) Hl(∗),但Resnet中使用 H H H表示期望映射,使用 F F F表示网络层实现的映射,并且本文中实现的映射也只是逼近期望映射,故用 F F F更为恰当)
- 第
l
l
l层的输出是
x
l
x_l
xl,输入是
i
n
l
in_l
inl
(注意这里的层是广义上的网络层,可以是指一个bottleneck,或者说本文中的 l l l就是第 l l l个bottleneck)
3.1 Resnet
传统网络层使用
x
l
=
F
l
(
x
l
−
1
)
x_l=F_l(x_{l-1})
xl=Fl(xl−1),导致了梯度弥散和模型退化问题,Resnet中使用
x
l
=
F
l
(
x
l
−
1
)
+
x
l
−
1
(1)
x_l=F_l(x_{l-1})+x_{l-1} \tag{1}
xl=Fl(xl−1)+xl−1(1),有效缓解了上述问题,但它的
x
l
−
1
x_{l-1}
xl−1只包含了一个层的特征,这样会浪费掉大量的特征信息。
此外,公式(1)使用的逐元素直接相加,作者认为这样会导致数据信息的流动受到阻碍。
3.2 Dense Connectivity
Resnet的问题是特征利用不充分进而导致网络层冗余,作者提出Dense Connectivity
充分利用特征:每一层的输出都作为它后面所有层输入的一部分,即每一层的输入都是前面所有层输出的结合,结合方式也吸取Resnet的经验,使用矩阵拼接的方式,公式表示为:
i
n
l
=
[
x
0
,
x
1
,
x
2
,
.
.
.
,
x
l
−
1
]
x
l
=
F
l
(
i
n
l
)
(2)
in_l=[x_0,x_1,x_2,...,x_{l-1}]\\x_l=F_l(in_l)\tag{2}
inl=[x0,x1,x2,...,xl−1]xl=Fl(inl)(2)
Fig1中密集的shortcut
就是公式(2)的直接实现。Pytorch源码的实现方式是第
l
l
l层输入是第
l
−
1
l-1
l−1层的输入和它输出的拼接,即
i
n
l
=
[
i
n
l
−
1
,
x
l
−
1
]
x
l
=
F
l
(
i
n
l
)
(3)
in_l=[in_{l-1},x_{l-1}] \\ x_l=F_l(in_l) \tag{3}
inl=[inl−1,xl−1]xl=Fl(inl)(3)
(建议使用公式(3)理解,虽然(2,3)本质一样)。
3.3 Bottleneck
ResnetV2[原文][论文阅读博客]中Kaiming He已经证明了一种更好的网络映射方式,本文中也使用这种构造
[
B
N
−
R
e
L
U
−
C
o
n
v
]
[BN-ReLU-Conv]
[BN−ReLU−Conv]。
另外,受ResnetV1的启发,本文中也使用Bottleneck
的结构来减少计算增加性能,但与原文中不同,本文中的bottleneck结构如下:
F
l
=
B
N
+
R
e
L
U
+
C
o
n
v
(
1
,
1
)
+
B
N
+
R
e
L
U
+
C
o
n
v
(
3
,
3
)
F_l=BN+ReLU+Conv(1,1)+BN+ReLU+Conv(3,3)
Fl=BN+ReLU+Conv(1,1)+BN+ReLU+Conv(3,3)
3.4 Growth rate
本文设定每个
F
l
(
∗
)
F_l(*)
Fl(∗)输出
k
k
k个特征,那么
i
n
l
in_l
inl应该有
k
0
+
(
l
−
1
)
k
k_0+(l-1)k
k0+(l−1)k个特征。与从前VGG/Googlenet/Resnet动不动就1024的输出特征个数不同的是,这里的
k
k
k可以设置的很小但是效果却比从前512/1024的效果还要好(见下图)。作者给出的解释是,虽然
k
k
k很小,但是每一层的输入中都有来自其他层的特征,这种特征可以看做全局特征,正是因为这种全局特征使得网络性能很好。而
k
k
k本身可以解释为当前层对网络中其他层有多少贡献。
另外
k
k
k设置的小,那卷积计算量就小很多,再加上Bottleneck
,就使得整体参数量和计算量更小。
3.5 Transition Layer
公式(3)中,要把
i
n
l
−
1
in_{l-1}
inl−1和
x
l
−
1
x_{l-1}
xl−1拼接起来的前提是它们的shape完全一样,但是直接生成的
x
l
−
1
x_{l-1}
xl−1的
H
,
W
H,W
H,W很可能跟
i
n
l
−
1
in_{l-1}
inl−1的不一致,比如第
l
l
l层做了一个stride=2
的卷积,所以需要对
i
n
l
−
1
in_{l-1}
inl−1做shape变换以匹配
x
l
−
1
x_{l-1}
xl−1。
本文把整个网络分成若干个Dense Blocks
,在两个Dense Blocks
中添加一个Transitin Layer
。本文使用的无敌的
C
o
n
v
(
1
,
1
)
Conv(1,1)
Conv(1,1)和average pool,
C
o
n
v
(
1
,
1
)
Conv(1,1)
Conv(1,1)用来融合特征和调整维度,average pool用来更改
H
,
W
H,W
H,W。
3.6 Compression
除了把
k
k
k设置的较小之外,作者还在Transition Layer中采取了压缩手段。
比如,对于Fig 2中的Dense Block2,假设它传给Transition Layer时有
m
m
m个特征,在经过
C
o
n
v
(
1
,
1
)
Conv(1,1)
Conv(1,1)之后的特征数是
θ
∗
m
θ*m
θ∗m。假设
θ
=
1
θ=1
θ=1,那就是正常的网络结构,如果
θ
<
1
θ<1
θ<1,那么经过Transition Layer之后的特征数就进一步减少了,也就实现了进一步的模型压缩。
3.7 实现细节
ImageNet数据集
- 输入图像尺寸 224 x 224
- 第一个卷积层输出特征数是 2 k 2k 2k,其余各层输出特征数 k k k
- 4个Dense Block,特征输出尺寸分别是56x56,28x28,14x14,7x7
- 不压缩
- 网络结构
对于除ImageNet的所有数据集:
- 输入图像尺寸 32x32
- 第一个卷积层输出特征数是16,其余各层输出特征数 k k k
- 3个Denseblock,特征输出分别是 ( 32 , 32 ) , ( 16 , 16 ) , ( 8 , 8 ) (32,32),(16,16),(8,8) (32,32),(16,16),(8,8)
- 网络结构设计类似对于ImageNet的结构,修改上述三点不同的参数值即可。
4 实验
4.1 训练细节
- 数据增强
- 在保持图片宽高比的前提下把图片短的一个边缩放到[256,480] ,称为尺度增强;
- 在上一步基础上水平翻转图像;
- 在上一步生成的图像上随机裁剪出224x224的图像块;
- 每个图像减掉ImageNet中图像的平均值,以减少训练时的计算量,同时还有助于提升模型性能;
- 使用标准颜色增强
- 在整个ImageNet上做图像RGB通道上的PCA
- 对训练集的每张RGB图片都加上下面的一个值,其中
p
和λ
是PCA中3x3的协方差矩阵的特征向量和特征值,α
是从一个均值为0标准差为0.1的高斯分布中提取出的随机向量。 - Alexnet中提到,使用这种颜色增强后是最终分类误差降低1%
- 训练参数
- 权重初始化使用Delving Deep into Rectifiers中提出的初始化方法(其中的n代表输入的数量,比如y=w’x,其中x是h-w-c那么n=h*w*c),从0开始训练 w = n p . r a n d o m . r a n d n ( n ) / s q r t ( 2.0 / n ) w=np.random.randn(n)/sqrt(2.0/n) w=np.random.randn(n)/sqrt(2.0/n)
- 优化器:SGD(Stochastic Gradient Descent,随机梯度下降)
- 学习率 初始0.1,ImageNet上每隔30个epoch减小10倍,其他数据集50%,75%的epoch时减小10倍
- 权重衰减因子1e-4
- 动量 0.9
- 迭代次数
- ImageNet 90 epoch
- CIFAR-10 300 epoch
- SVHN 40 epoch
- 其余Trick
- ImageNet 使用BN,不适用Dropout
- CIFAR-10和SVHN在除第一个卷积之外的其他所有卷积之后使用Dropout
- 测试方法
- 标准
10-crop testing
- 截取原图四个角和中心的224x224的图像,得到5张子图
- 把原图水平翻转之后,做同样的操作,又得到5张子图
- 一共裁剪得到5+5=10张子图,这就是
10-crop
- 分别对10张子图做预测,最终结果取平均值
- 标准
4.2 实验结果
配置说明:
- Densenet :正常情况
- Densenet-BC:使用bottleneck,压缩系数 θ = 0.5 θ=0.5 θ=0.5
ImageNet结果
CIFAR/SVHN
5 思考
1.实际训练时,除去内存消耗,Resnet50比Densenet121快很多,而前者要比后者的参数更多才对。参数个数与FLOPs没有必然的正相关关系。