欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

DenseNet:密集连接的卷积网络

最编程 2024-05-12 09:07:49
...

论文:Densely Connected Convolutional Networks

众所周知,最近一两年卷积神经网络提高效果的方向,要么深(比如ResNet,解决了网络深时候的梯度消失问题)要么宽(比如GoogleNet的Inception),而作者则是从特征图入手,通过对特征图的极致利用达到更好的效果和更少的参数。

DenseNet的优点

在深度学习网络中,随着网络深度的加深,梯度消失问题会愈加明显,目前很多论文都针对这个问题提出了解决方案,比如ResNet,Highway Networks,Stochastic depth,FractalNets等,尽管这些算法的网络结构有差别,但是核心都在于:在前面的层和后面的层之间创建短路连接。那么作者是怎么做呢?延续这个思路,那就是——在保证网络中层与层之间最大程度的信息传输的前提下,直接将所有层连接起来。为了能够保证前馈的特性,每一层将之前所有层的输入进行拼接,之后将输出的特征图传递给之后的所有层。

先放一个dense block的结构图。在传统的卷积神经网络中,如果你有L层,那么就会有L个连接,但是在DenseNet中,会有L(L+1)/2个连接。与ResNets不同的是,DenseNets不是在特征传递给某一层之前将其进行相加(combine),而是将其进行拼接(concatenate)。因此,第 l 层有 l 个输入,这些输入是该层之前的所有卷积块(block)的特征图,而它自己的特征图则传递给之后的所有层。由于它的稠密连接模块,所以把这个方法称为稠密卷积网络(DenseNets)。如下图:x0是input,H1的输入是x0(input),H2的输入是x0和x1(x1是H1的输出)……

1. 减轻了vanishing-gradient(梯度消失)

这种连接方式使得特征和梯度的传递更加有效,网络也就更加容易训练。每一层都可以直接利用损失函数的梯度以及最开始的输入信息,相当于是一种隐形的深度监督(implicit deep supervision),这有助于训练更深的网络。前面提到过梯度消失问题在网络深度越深的时候越容易出现,原因就是输入信息和梯度信息在很多层之间传递导致的,而现在这种密集连接相当于每一层都直接连接输入和损失,因此就可以减轻梯度消失现象,这样构建更深的网络不是问题。

2. 加强了特征的传递,更有效地利用了特征

每层的输出特征图都是之后所有层的输入。

3. 一定程度上较少了参数数量

DenseNets的稠密连接模块(dense block)的一个优点是它比传统的卷积网络有更少的参数,因为它不需要再重新学习多余的特征图。传统的前馈结构可以被看成一种层与层之间状态传递的算法。每一层接收前一层的状态,然后将新的状态传递给下一层。它改变了状态,但也传递了需要保留的信息。ResNets将这种信息保留的更明显,因为它加入了自身变换(identity transformations)。最近很多关于ResNets的研究都表明ResNets的很多层是几乎没有起作用的,可以在训练时随机的丢掉。DenseNet结构中,增加到网络中的信息与保留的信息有着明显的不同。DenseNet的dense block中每个卷积层都很窄(例如每一层有12个滤波器),仅仅增加小数量的特征图到网络的“集体知识”(collective knowledge),并且保持这些特征图不变——最后的分类器基于网络中的所有特征图进行预测。

另外作者还观察到这种密集连接有正则化的效果,因此对于过拟合有一定的抑制作用,因为参数减少了,所以过拟合现象减轻。

DenseNets

假设一张图片 x0 在卷积网络中传播。网络共有 L 层,每一层都有一个非线性转换函数H_l (定义为三种操作的组合函数,分别是:BN、ReLU和卷积),其中 l 表示第几层。用 x_l 表示第 l 层的输出。

传统的前馈网络是将 l-1 层的输出x_{l-1}作为 l 层的输入,得到 l 层的输出 x_l,可用该方程来表示: x_l=H_l(x_{l-1})

  • ResNets增加了一个跨层连接,将自身与非线性转换的结果相加:x_l=H_l(x_{l-1})+x_{l-1} 所以对于ResNet而言,l层的输出是l-1层的输出加上对l-1层输出的非线性变换,这样可以直接将梯度从后层传向前层。然而,自身与经过 H_l 得到的输出是通过求和的形式来连接的,这可能使网络中信息的传播受到影响。

  • DenseNets为了更好的改善层与层之间信息的传递,提出一种不同的连接模式:将该层与之后的所有层进行连接。因此,l 层将之前所有层的特征图 [x_0, x_1, ..., x_{l-1}] 作为输入:x_l=H_l([x_0, x_1, ..., x_{l-1}]),输入是之前所有特征图的拼接。而前面resnet是做值的相加,通道数是不变的。

所以从这两个公式就能看出DenseNet和ResNet在本质上的区别。

结构

前面的图表示的是dense block,而下面的图表示的则是一个DenseNet的结构图,在这个结构图中包含了3个dense block。作者将DenseNet分成多个dense block,原因是希望各个dense block内的feature map的size统一,这样在做concatenation就不会有size的问题。

增长速率k(growth rate):Dense block中,如果每个层函数 H_l 都产生 k 个特征图,那么第 l 层就有 k_0 + (l-1)k 个特征图作为输入,其中 k0 表示输入层的通道数。DenseNet和现存网络结构的一个很重要的不同是,DenseNet的网络很窄,如 k=12 。超参数 k 称为网络的增长速率。一个很小的增长速率在测试的数据集上就可以获得不错的效果,因为每一层都可以和它所在的block中之前的所有特征图进行连接,使得网络具有了“集体知识”(collective knowledge)。可以将特征图看作是网络的全局状态,每一层相当于是对当前状态增加 k 个特征图。增长速率控制着每一层有多少信息对全局状态有效。全局状态一旦被写定,就可以在网络中的任何地方被调用,而不用像传统的网络结构那样层与层之间的不断重复。

Bottleneck层:尽管每一层只产生 k 个输出特征图,但是根据dense block的设计,后面几层可以得到前面所有层的输入,因此拼接后的输入通道数还是比较大的。研究表明,每个dense block的中3x3的卷积之前加入1x1的卷积(就是所谓的bottleneck layer)可以减少输入的特征图数量,减小计算量,同时能融合各个通道的特征。将具有bottleneck层,即 BN-ReLU-Conv(1x1)-BN-ReLU-Conv(3x3) 的结构称为DenseNet-B。在论文中,令1x1的卷积生成 4k 个特征图。在每个Dense Block中都包含很多个子结构,以DenseNet-169的Dense Block(3)为例,包含32个1x1和3x3的卷积对,也就是第32个子结构的输入是前面31层的输出结果,每层输出的channel是 k=32。如果不做bottleneck操作,第 32 层的 3x3 卷积的输入就是31x32+(该Dense Block的输入channel),近1000了。而加上1x1的卷积,1x1卷积的输出是 4k,也就是128,然后再作为3*3卷积的输入,大大减少了计算量。

过渡层(Translation Layer):每两个dense block之间的层称为过渡层,完成卷积和池化的操作,目的是减小特征图的数量。过渡层由BN层、1x1卷积层和2x2平均池化层组成。如果一个dense block有 m 个特征图,我们让之后的过渡层生成 \theta m 个输出特征图,其中 \theta 表示压缩(compression)系数。定义 \theta <1 的 DenseNet 为 DenseNet-C,实验中 \theta=0.5 。如果bottleneck和过渡层都有\theta<1 ,我们称该模型为DenseNet-BC。还是以DenseNet-169的Dense Block(3)为例,虽然第32层的 3x3 卷积输出channel只有32个,但是紧接着还会像前面几层一样有通道的拼接操作,即将第32层的输出和第32层的输入做拼接,前面说过第32层的输入是1000左右的channel,所以最后每个Dense Block的输出也是1000多的channel。因此经过过渡层压缩后,传给下一个dense block的时候channel数量就会减少一半,这就是过度层的作用。文中还用到dropout操作来随机减少分支,避免过拟合,毕竟 DenseNets 的连接确实多。

实现细节

在除了ImageNet外的所有数据集上,实验中使用的DenseNet都有三个dense block,每一个block都有相同的层数。在进入第一个dense block之前,输入图像先经过了16个(DenseNet-BC中是两倍的增长速率)卷积。对于3x3的卷积层,使用一个像素的零填充来保证特征图尺寸不变。在两个dense block之间的过渡层中,我们在2x2的平均池化层之后增加了1x1的卷积。在最后一个dense block之后,使用全局平均池化和softmax分类器。三个dense block的特征图的尺寸分别是32x32,16x16,8x8。

对于在ImageNet数据集上的实验,我们使用4个dense block的DenseNet-BC结构,图片的输入是224x224。最开始的卷积层有 2k(64)个卷积,卷积核是7x7,步长是2;其余所有层的特征图都设为 k 。在ImageNet数据集上的网络如下表所示:

实验结果

下表是在三个数据集(C10,C100,SVHN)上和其他算法的对比结果。ResNet就是kaiming He的论文,对比结果一目了然。DenseNet-BC的网络参数和相同深度的DenseNet 相比确实减少了很多。参数减少除了可以节省内存,还能减少过拟合。这里对于SVHN数据集,DenseNet-BC的结果并没有DenseNet(k=24)的效果好,作者认为原因主要是SVHN这个数据集相对简单,更深的模型容易过拟合。在表格的倒数第二个区域的三个不同深度 L 和 k 的DenseNet的对比可以看出随着 L 和 k 的增加,模型的效果是更好的。

下图是DenseNet-BC和ResNet在ImageNet数据集上的对比,左边那个图是参数复杂度和错误率的对比,可以在相同错误率下看参数复杂度,也可以在相同参数复杂度下看错误率,提升还是很明显的。右边是flops(可以理解为计算复杂度)和错误率的对比,同样有效果。

Figure4也很重要。左边的图表示不同类型DenseNet的参数和error对比。中间的图表示DenseNet-BC和ResNet在参数和error的对比,相同error下,DenseNet-BC的参数复杂度要小很多。右边的图也是表达DenseNet-BC-100只需要很少的参数就能达到和ResNet-1001相同的结果。

另外提一下DenseNet和stochastic depth的关系,在stochastic depth中,residual中的layers在训练过程中会被随机drop掉,其实这就会使得相邻层之间直接连接,这和DenseNet是很像的。

总结:

该文章提出的 DenseNet 核心思想在于建立了不同层之间的连接关系,充分利用了特征图,进一步减轻了梯度消失问题,加深网络不是问题,而且训练效果非常好。另外,利用 bottleneck layer,translation layer 以及较小的 growth rate 使得网络变窄,参数减少,有效抑制了过拟合,同时计算量也减少了。DenseNet 优点很多,而且在和ResNet的对比中优势还是非常明显的。