//对densenet的一些理解

论文链接:https://arxiv.org/pdf/1608.06993.pdf

代码链接:https://github.com/liuzhuang13/DenseNet

最近研究表明在越靠近输入的层与越靠近输出的层之间的连接越短,能使卷积神经网络更深,分类效果更准确。

残差网络有一个缺点:残差操作可能会阻碍网络中的信息流。

这篇博客当时记录笔记,==比较混乱别喷。

看完第三部分表示不知的121是怎么算出来的。

重点讲一下论文的第三部分(差不多翻译一下。):

densenet提出的原因以及所包含的操作。

假定x0是一张要通过卷积网络的图片。这个网络有L层,每一层实现一个非线性转换H_l(.),l标志层数(也就是第l层)。H_l(.)是一个包含一系列操作的函数,比如BN、ReLU、池化以及卷积。下面第l层的输出用x_l表示。

1.残差网络

传统的前馈网络将第l层的输出作为第(l+1)层的输入,也就有下面这个公式:x_l = H_l(x_(l-1)) 。残差网络使用了绕过非线性变换且与自身结合的跳跃连接,也就是:x_l = H_l(x_(l-1)) + x_(l-1)。可见,残差网络的优点就是在反向传播时,梯度可以直接通过自身函数从后面的层网前面的层(前向传播是从前面的层传到后面,反向传播的梯度信息就是从后面往前面传。)。但是自身函数与H_l的输出是通过加法操作结合的,加法可能会阻碍网络中信息的流动。

2.密集连接

相比于传统的卷积网络连接方式,这篇论文提出了一个不一样的连接模式,也就是使每一卷积层,都与其后的卷积层相连,如图

//对densenet的一些理解_第1张图片

造成的结果就是 第l层的输出x_l与之前的l-1层的输出都有关:x_l = H_l([x_0, x_1, x_2, ..., x_(l-1)]),其中[x_0, x_1, x_2, ..., x_(l-1)]是指0-(l-1)层的输出的拼接(这些输出的特征图的高宽一样,在通道维上进行拼接,从而得到第l层的输入),再经过H_l(.)函数,从而得到第l层的输出。

3.混合函数

H_l(.)是指这个混合函数,(这一部分的写作是源于Identity mappings in deep residual networks这篇论文激发的灵感。)且它包括连续(按顺序来。)的三个操作:BN(批归一化)+ReLU(激活函数)+3*3卷积。

4.池化层

上面也提到过,要进行拼接操作,这些特征图的尺寸(高与宽)必须一致。但对于网络来说,特征图大小必须改变,也就是下采样层(或者说池化层)必须有。为了能引入池化操作,本论文提出了一个包括卷积与池化的过渡层。在相邻的密集块之间放置一过渡层。本论文实验用到的过渡层包括:BN+1*1卷积+2*2平均池化。(也就是在过渡层实现下采样。)

5.增长率

混合函数H能产生k张特征图,那么第l层的输入特征图的数量为k_0 + k x (l-1),其中k_0是指输入图片的通道数。这里的k也就是增长率,且k可以取比较小的值,比如12,那么相比现存的网络架构,densenet会更窄。作者指出,在他们测试过的数据上,使用比较小的增长率,会能有效取得SOTA水平的结果。可以将特征图视为网络的全局状态。 /每层将自己的k个特征图添加到此状态。 增长率调节每一层为全局状态贡献多少新信息。 写入后的全局状态可以在网络中的任何位置进行访问,并且与传统的网络体系结构不同,无需从一层到另一层进行复制。/(此处为原文翻译。)

6.瓶颈层

即BN+ReLU+conv(1*1)+BN+ReLU+conv(3*3),其中conv1*1产生4k特征图。

7.压缩

个人觉得在论文里Densenet-BC的命名有点牵强,densenet-B是指bottleneck层,该层最后产生32层特征图,因此特征图数量就是会减少,而过渡层的作用除了下采样,自然有控制网络层数的作用,输出特征图的层数自然也要变小。模型一般densenet-B,与densenet-C都用到。

from torchvision.models.densenet import densenet121
net = densenet121()
print(net)

查看网络结构,会发现现denseblock里的denselayer输出是32,比如

(denseblock1): _DenseBlock(
      (denselayer1): _DenseLayer(
        (norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(64, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(128, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      )

(denselayer2): _DenseLayer(
        (norm1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(96, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(128, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      )

denseblock1中的denselayer1的conv2输出是32,下一层的输入时64+32,

实现细节

由于imagenet数据集图像尺寸是224*224,在最开始的卷积层输出是2*32层,如下所示

(conv0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
    (norm0): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (relu0): ReLU(inplace=True)
    (pool0): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)

你可能感兴趣的:(cnn模型,神经网络,卷积,深度学习)