DenseNet详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DenseNet详解相关的知识,希望对你有一定的参考价值。
参考技术A作为CVPR2017年的Best Paper, DenseNet 脱离了 加深网络层数(ResNet) 和 加宽网络结构(Inception)来提升网络性能的定式思维 ,从特征的角度考虑,通过 特征重用和旁路(Bypass)设置 ,既大幅度减少了网络的参数量,又在一定程度上缓解了gradient vanishing问题的产生.结合信息流和特征复用的假设,DenseNet当之无愧成为2017年计算机视觉顶会的年度最佳论文.
卷积神经网络在沉睡了近20年后,如今成为了深度学习方向最主要的网络结构之一.从一开始的只有五层结构的LeNet, 到后来拥有19层结构的VGG, 再到首次跨越100层网络的Highway Networks与ResNet, 网络层数的加深成为CNN发展的主要方向之一.
随着CNN网络层数的不断增加, gradient vanishing和model degradation问题 出现在了人们面前, BatchNormalization的广泛使用在一定程度上缓解了gradient vanishing的问题 ,而 ResNet和Highway Networks通过构造恒等映射设置旁路,进一步减少了gradient vanishing和model degradation的产生 .Fractal Nets通过将不同深度的网络并行化,在获得了深度的同时保证了梯度的传播,随机深度网络通过对网络中一些层进行失活,既证明了ResNet深度的冗余性,又缓解了上述问题的产生. 虽然这些不同的网络框架通过不同的实现加深的网络层数,但是他们都包含了相同的核心思想,既将feature map进行跨网络层的连接.
何恺明在提出ResNet时做出了这样的假设:若某一较深的网络多出另一较浅网络的若干层有能力学习到恒等映射,那么这一较深网络训练得到的模型性能一定不会弱于该浅层网络.通俗的说就是如果对某一网络中增添一些可以学到恒等映射的层组成新的网路,那么最差的结果也是新网络中的这些层在训练后成为恒等映射而不会影响原网络的性能.同样DenseNet在提出时也做过假设:与其多次学习冗余的特征,特征复用是一种更好的特征提取方式.
ResNet的一个最主要的优势便是梯度可以流经恒等函数来到达靠前的层.但恒等映射和非线性变换输出的叠加方式是相加, 这在一定程度上破坏了网络中的信息流.
为了进一步优化信息流的传播,DenseNet提出了图示的网络结构
如图所示,第i层的输入不仅与i-1层的输出相关,还有所有之前层的输出有关.记作:
由于在DenseNet中需要对不同层的feature map进行cat操作,所以需要不同层的feature map保持相同的feature size,这就限制了网络中Down sampling的实现.为了使用Down sampling,作者将DenseNet分为多个Denseblock,如下图所示:
在同一个Denseblock中要求feature size保持相同大小,在不同Denseblock之间设置transition layers实现Down sampling, 在作者的实验中transition layer由BN + Conv(1×1) +2×2 average-pooling组成.
在Denseblock中,假设每一个非线性变换H的输出为K个feature map, 那么第i层网络的输入便为K 0 +(i-1)×K, 这里我们可以看到DenseNet和现有网络的一个主要的不同点:DenseNet可以接受较少的特征图数量作为网络层的输出,如下图所示
原因就是在同一个Denseblock中的每一层都与之前所有层相关联,如果我们把feature看作是一个Denseblock的全局状态,那么每一层的训练目标便是通过现有的全局状态,判断需要添加给全局状态的更新值.因而每个网络层输出的特征图数量K又称为Growth rate,同样决定着每一层需要给全局状态更新的信息的多少.我们之后会看到,在作者的实验中只需要较小的K便足以实现state-of-art的性能.
虽然DenseNet接受较少的k,也就是feature map的数量作为输出,但由于不同层feature map之间由cat操作组合在一起,最终仍然会是feature map的channel较大而成为网络的负担.作者在这里使用1×1 Conv(Bottleneck)作为特征降维的方法来降低channel数量,以提高计算效率.经过改善后的非线性变换变为BN-ReLU-Conv(1×1)-BN-ReLU-Conv(3×3),使用Bottleneck layers的DenseNet被作者称为DenseNet-B.在实验中,作者使用1×1卷积生成channel数量为4k的feature map.
为了进一步优化模型的简洁性,我们同样可以在transition layer中降低feature map的数量.若一个Denseblock中包含m个feature maps,那么我们使其输出连接的transition layer层生成⌊θm⌋个输出feature map.其中θ为Compression factor, 当θ=1时,transition layer将保留原feature维度不变.
作者将使用compression且θ=0.5的DenseNet命名为DenseNet-C, 将使用Bottleneck和compression且θ=0.5的DenseNet命名为DenseNet-BC
由于DenseNet对输入进行cat操作,一个直观的影响就是每一层学到的feature map都能被之后所有层直接使用,这使得特征可以在整个网络中重用,也使得模型更加简洁.
从上图中我们可以看出DenseNet的参数效率:左图包含了对多种DenseNet结构参数和最终性能的统计,我们可以看出当模型实现相同的test error时,原始的DenseNet往往要比DenseNet-BC拥有2-3倍的参数量.中间图为DenseNet-BC与ResNet的对比,在相同的模型精度下,DenseNet-BC只需要ResNet约三分之一的参数数量.右图为1001层超过10M参数量的ResNet与100层只有0.8M参数量的DenseNet-BC在训练时的对比,虽然他们在约相同的训练epoch时收敛,但DenseNet-BC却只需要ResNet不足十分之一的参数量.
解释DenseNet为何拥有如此高性能的另一个原因是 网络中的每一层不仅接受了原始网络中来自loss的监督 ,同时由于 存在多个bypass与shortcut,网络的监督是多样的 .Deep supervision的优势同样在deeply-supervised nets (DSN)中也被证实.(DSN中每一个Hidden layer都有一个分类器,强迫其学习一些有区分度的特征).与DSN不同的是,DenseNet拥有单一的loss function, 模型构造和梯度计算更加简易.
在设计初,DenseNet便被设计成让一层网络可以使用所有之前层网络feature map的网络结构,为了探索feature的复用情况,作者进行了相关实验.作者训练的L=40,K=12的DenseNet,对于任意Denseblock中的所有卷积层,计算之前某层feature map在该层权重的绝对值平均数.这一平均数表明了这一层对于之前某一层feature的利用率,下图为由该平均数绘制出的热力图:
从图中我们可以得出以下结论:
a) 一些较早层提取出的特征仍可能被较深层直接使用
b) 即使是Transition layer也会使用到之前Denseblock中所有层的特征
c) 第2-3个Denseblock中的层对之前Transition layer利用率很低,说明transition layer输出大量冗余特征.这也为DenseNet-BC提供了证据支持,既Compression的必要性.
d) 最后的分类层虽然使用了之前Denseblock中的多层信息,但更偏向于使用最后几个feature map的特征,说明在网络的最后几层,某些high-level的特征可能被产生.
作者在多个benchmark数据集上训练了多种DenseNet模型,并与state-of-art的模型(主要是ResNet和其变种)进行对比:
由上表我们可以看出,DenseNet只需要较小的Growth rate(12,24)便可以实现state-of-art的性能,结合了Bottleneck和Compression的DenseNet-BC具有远小于ResNet及其变种的参数数量,且无论DenseNet或者DenseNet-BC,都在原始数据集和增广数据集上实现了超越ResNet的性能.
DenseNet详解
详解和对比ResNet和DenseNet和MobileNet
经典的Backbone,如ResNet50、DenseNet121、MobileNetV2,三类框架,参考 Keras Applications :
ResNet50 | DenseNet121 | MobileNetV2 | |
---|---|---|---|
时间 | CVPR 2015 | CVPR 2017 | CVPR 2018 |
模型 | 98M | 33M | 14M |
Top1(ImageNet) | 0.749 | 0.750 | 0.713 |
参数 | 25,636,712(约2500w) | 8,062,504(约800w) | 3,538,984(约350w) |
推理速度CPU | 58.20ms | 77.14ms | 25.90ms |
推理速度GPU | 4.55ms | 5.38ms | 3.83ms |
ResNet50
ResNet50,参考 PyTorch-ResNet 和论文 Deep Residual Learning for Image Recognition - CVPR2015:
-
ResNet模型的核心,通过建立前面层与后面层之间的“短路连接”(shortcuts,skip connection),进行残差学习,这有助于训练过程中梯度的反向传播,从而能训练出更深的CNN网络。
-
conv1:7x7是卷积核尺寸、64通道、步长是2
-
ResNet50:
1 + 3*3 + 4*3 + 6*3 + 3*3 + 1 = 50
-
conv2_x:不执行下采样操作。
-
conv3_x:
-
4组卷积操作,第1组的第1次1x1卷积的stride是2,做下采样操作,其他次的stride是1。
-
其余组的每次都是stride为1的卷积操作。
-
每组执行一次,shortcut的残差操作,共执行3+4+6+3=16次残差操作。
-
每1层执行卷积+BN+激活操作,残差学习,在最后一层激活之前。
-
其余conv4_x和conv5_x类似。
-
-
最后,执行全局均值池化(GlobalAveragePooling2D),再加上全连接层(Dense)。
网络结构:
DenseNet121
DenseNet121,参考 PyTorch-DenseNet,论文 Densely Connected Convolutional Networks - CVPR2017 :
- DenseBlock(密集块)和TransitionLayer(过渡层)
- DenseNet121:
1 + 6*2 +1 + 12*2 + 1 + 24*2 + 1 + 16*2 + 1 = 121
- 起始:卷积7x7,64通道、步长是2,再进行步长为2的最大池化,输入图像由224 -> 56
growth_rate
是32,DenseBlock1的通道数:64 + 6*32 = 256个- DenseBlock1:1x1卷积先扩大通道数4*32=128,3x3卷积再缩小通道数128->32,再和输入相加,即每次增加32个通道。
- TransitionLayer1:通过1x1卷积,降低一半的通道,如256降低为128,再通过stride(步长)为2的均值池化,降低一半输入尺寸。
通道数变化:
网络结构:
原型:
MobileNet v1、v2、v3
MobileNet v1 和 v2 和 v3的对比:
参数:
- v1: 参数4.2M,模型大小16M,
- v2,CVPR-2018: 参数3.5M(对比v1,下降17%),模型大小9.4M(对比v1,下降41%)
- v3,ICCV-2019: Large 参数5.4M,模型大小16.2M;Small 参数2.9M(对比v2,下降17%),模型大小7.9M(对比v2,下降16%)
MobileNet v1
MobileNet v1的特点是Depthwise Separable卷积:
-
Pointwise卷积 + Depthwise卷积 -> Depthwise Separable卷积,参考 深度可分离卷积
-
Depthwise Separable卷积,可以降低计算量
例如:卷积核:KxK,输入通道M,输出通道N,图像尺寸WxH,普通卷积Depthwise Separable卷积的具体计算量如下:
Depthwise Separable:M*N*W*H + K*K*M*W*H
原始:K*K*M*N*W*H
MobileNet v1中使用的Depthwise Separable Convolution是模型压缩的一个最为经典的策略,通过将跨通道的3x3卷积换成单通道的3x3卷积+跨通道的1x1卷积来达到此目的。
MobileNet v2
MobileNet v2的特点是Linear Bottleneck(线性瓶颈) 和 Inverted Residuals(反向残差),参考 详解MobileNetV2、MobileNet v1 和 MobileNet v2:
-
Linear Bottlenecks(参考V3) + ReLU6 + Residual
-
Inverted Residual Block,在bottleneck层使用残差结构;
-
MobileNetV2是在v1的Depthwise Separable的基础上引入了残差结构。并发现了ReLU的在通道数较少的Feature Map上有非常严重信息损失问题,由此引入了Linear Bottlenecks和Inverted Residual。
网络参考:
MobileNet v3
MobileNet v3的特点是:
- NAS(Neural Architecture Search) for block 和 NetAdapt for layer,创建网络结构;
- h-swish和ReLU混合使用,增强效果;在SE结构中,h-sigmoid代替sigmoid;速度较快;
- 堆叠bottleneck单元:瓶颈结构、SE结构、残差(Residual)结构;
- 重新设计高效的last stage
网络结构:
h-swish & h-sigmoid:h表示Hard
h-sigmoid = ReLU6(x+3)/6
h-swish = x*(ReLU6(x+3)/6)
swish = x*sigmoid(x)
bottleneck单元:bneck:瓶颈单元;exp size:expand尺寸;
- 1x1的卷积,input通道,exp通道,stride是1;BN,激活;Pointwise卷积
- 3x3,5x5的卷积,exp通道,exp通道,stride是1或2;BN;Depthwise卷积
- 可选:SE结构:线性压缩,乘以权重;
- 1x1的卷积,exp通道,output通道,stride是1,BN,激活;
- bottleneck,stride是1,同时输入和输出相同;
Last Stage:输入是7x7x960
Old:
- 3x3的卷积,通道数960不变;
- 1x1的卷积,降低通道320;
- 1x1的卷积,提升通道1280;
- Avg Pooling池化;
- 1x1的卷积预测类别1000;
New:
- Avg Pooling池化,960;
- 1x1的卷积, 提升通道1280;
- 1x1的卷积,预测类别1000;
降低15%的计算时间,同时没有精度损失。
SE结构:
SE:Squeeze and Excite,压缩和刺激;
例如输入:16x112x112
- Avg Pooling:16x1x1,reshape为16;
- 压缩和刺激:压缩比例是4
- 压缩:16 x [16x4] = 4,
- ReLU
- 刺激:4 x [4x16] = 16,
- H-Sigmoid:ReLU6(x+3)/6
- reshape:16x1x1,权重
- 权重与源矩阵相乘:
16x112x112 * 16x1x1 = 16x112x112
class SqueezeBlock(nn.Module):
def __init__(self, exp_size, divide=4):
super(SqueezeBlock, self).__init__()
self.dense = nn.Sequential(
nn.Linear(exp_size, exp_size // divide),
nn.ReLU(inplace=True),
nn.Linear(exp_size // divide, exp_size),
h_sigmoid()
)
def forward(self, x):
batch, channels, height, width = x.size()
out = F.avg_pool2d(x, kernel_size=[height, width]).view(batch, -1)
out = self.dense(out)
out = out.view(batch, channels, 1, 1)
return out * x
卷积公式:
- 输入:MxM
- 卷积核:KxK
- 步长:S
- adding:P
- 输出:NxN
公式: N = (M - K + 2P) // S + 1
1x1 卷积的优势:
- 进行卷积核通道数的降维和升维,修改channel数量,同时,在升维和降维过程中,实现跨通道的交互和信息整合;
- 最后连接的激活函数,增加非线性激励;
- 在预测时,避免全连接层的固定参数,接受任意尺度输入;
- 用于Depthwise Separable卷积,降低计算量:Pointwise卷积 + Depthwise卷积 -> Depthwise Separable卷积。
That’s all.
以上是关于DenseNet详解的主要内容,如果未能解决你的问题,请参考以下文章
详解和对比ResNet和DenseNet和MobileNet
详解和对比ResNet和DenseNet和MobileNet
DenseNet——CNN经典网络模型详解(pytorch实现)