Loading [MathJax]/extensions/TeX/boldsymbol.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >深度学习经典网络解析:4.DenseNet

深度学习经典网络解析:4.DenseNet

作者头像
AiCharm
发布于 2023-05-15 07:35:44
发布于 2023-05-15 07:35:44
2.8K00
代码可运行
举报
文章被收录于专栏:AiCharmAiCharm
运行总次数:0
代码可运行

1.背景介绍

  DenseNet是CVPR2017年的Best Paper,它脱离了加深网络层数(ResNet)和加宽网络结构(Inception)来提升网络性能的定式思维,从特征的角度考虑,通过特征重用和旁路(Bypass)设置,既大幅度减少了网络的参数量,又在一定程度上缓解了gradient vanishing问题的产生.结合信息流和特征复用的假设,DenseNet当之无愧成为2017年计算机视觉顶会的年度最佳论文。

  众所周知,CNN已经成为了深度学习方向最主要的网络结构之一。从一开始的只有五层结构的LeNet, 到后来拥有19层结构的VGG,再到首次跨越100层网络的HighwayNetworks与ResNet, 网络层数的加深成为CNN发展的主要方向之一。

  但是随着CNN网络层数的不断增加开始出现梯度消失和模型退化(50层的网络不如20层的网络),批量归一化(BatchNormalization)的广泛使用在一定程度上缓解了梯度消失的问题,而ResNet和Highway Networks通过构造恒等映射设置旁路,进一步减少了梯度消失和模型退化的产生。Fractal Nets通过将不同深度的网络并行化,在获得了深度的同时保证了梯度的传播,随机深度网络通过对网络中一些层进行失活,既证明了ResNet深度的冗余性,又缓解了上述问题的产生。虽然这些不同的网络框架通过不同的实现加深的网络层数,但是他们都包含了相同的核心思想将feature map进行跨网络层的连接

用通俗的话说——CNN网络层数越大,输出到输入的路径就会变得更长,就会出现一个问题:梯度经过这么长的路径反向传播回输入的时候很可能就会消失。

那有没有一种方法可以让网络又深梯度又不会消失?

DenseNet提出了一种很简单的方法:将前面所有层与后面的层建立密集连接来对特征进行重用来解决这个问题

2.DenseNet与ResNet

2.1ResNet

  ResNet(Deep Residual Network深度残差网络):通过建立前面层与后面层之间的“短路连接”,这有助于训练过程中梯度的反向传播,从而能训练出更深的CNN网络。

2.2DenseNet

  DenseNet采用密集连接机制,即互相连接所有的层,每个层都会与前面所有层在channel维度上连接(concat)在一起,实现特征重用,作为下一层的输入。这样,不但减缓了梯度消失的现象,也使其可以在参数与计算量更少的情况下实现比ResNet更优的性能。

3.DenseNet的数学表示

传统的网络在L层的输出为:

ResNet,增加了来自上一层输入:

DenseNet中,会连接前面所有层作为输入:

代表是非线性转化函数,它是一个组合操作,其可能包括一系列的BN(Batch Normalization), ReLU, Pooling及Conv操作。特征传递方式是直接将前面所有层的特征concat后传 到下一层,而不是前面层都要有一个箭头指向后面的所有层.

4.DenseNet网络架构

  DenseNet的密集连接方式需要特征图大小保持一致 。所 以 DenseNet 网络中使用DenseBlock+Transition的结构。  DenseBlock是包含很多层的模块,每个层的特征图大小相同,层与层之间采用密集连接方式

  Transition模块是连接两个相邻的DenseBlock,并且通过Pooling使特征图大小降低。

4.1DenseBlock

  • 在DenseBlock中,各个层的特征图大小一致,可以在channel维度上连接。DenseBlock中的非线性组合函数采用的是BN+ReLU+3x3Conv的结构。
  • 这里有一个参数

, 称为增长率, 指的是每一层的额外通道数, , 假如输入层特征图的channel为

, 那么

的channel数就为

。因为每一层都接受前面所有层的特征图,即特征传递方式是直接将前面所有层的特征concat后传到下一层,一般情况下使用较小的K(一般为12),要注意这个K的实际含义就是这层新提取出的特征。

  • Dense Block采用了激活函数在前、卷积层在后的顺序,即BN-ReLU-Conv的顺序,这种方式也被称为pre-activation。通常的模型relu等激活函数处于卷积conv、批归一化batchnorm之后,即Conv-BN-ReLU,也被称为post-activation。作者证明,如果采用post-activation设计,性能会变差。

BottleNeck层

  由于后面层的输入会非常大,DenseBlock内部可以采用Bottleneck层(瓶颈层)来减少计算量,主要是原有的结构中增加1x1 Conv,即BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv称为DenseNet-B结构。其中1x1 Conv得到4k个特征图它起到的作用是降低特征数量,从而提升计算效率。  每一个Bottleneck输入输出的特征通道数是相同的。这里1×1卷积的作用是固定输出通道数达到降维的作用,1×1卷积输出的通道数通常是GrowthRate的4倍。当几十个Bottleneck相连接时,concat后的通道数会增加到上千,如果不增加1×1的卷积来降维,后续3×3卷积所需的参数量会急剧增加。

  假设输入通道数为64,增长率K=32,经过15个Bottleneck,通道数输出为:64+15x32=544

  如果不使用1×1卷积,第16个Bottleneck层参数量是:3x3x544x32=156672

  如果使用1×1卷积,第16个Bottleneck层参数量是:

1x1x544x128+3x3x128x32=106496

  可以看到参数量大大降低

在这里插入图片描述

4.2Transition层

  Transition层它主要是连接两个相邻的DenseBlock,并且降低特征图大小。

Transition层包括一个1x1的卷积和2x2的AvgPooling,结构为BN+ReLU+1x1 Conv+2x2 AvgPooling

  Transition层可以起到压缩模型的作用。假定Transition的上接DenseBlock得到的特征图 channels数为

,Transition层可以产生

个特征(通过卷积层),其中

是压缩系 数 (compression rate)。当

时,特征个数经过Transition层没有变化,即无压缩,而当压缩系数小于1时,这种结构称为DenseNet-C,一般使用

。对于使用bottleneck层的 DenseBlock结构和压缩系数小于1的Transition组合结构称为DenseNet-BC。DenseBlock结构和压缩系数小于1的Transition组合结构称为DenseNet-BC。

  可以通过一张参数计算的图来回顾一下(其中

是Dense Block,

是Transition模块), 我们可以看到每经过一个Dense Block深度增加量=增长率✖密集块数量, 其中+号代表concat。

5.DenseNet评价

5.1DenseNet优点

5.1.1更强的梯度流动

  由于密集连接方式,DenseNet提升了梯度的反向传播,使得网络更容易训练。由于每层可以直达最后的误差信号,实现了隐式的“deep supervision”。误差信号可以很容易地传播到较早的层,所以较早的层可以从最终分类层获得直接监管(监督)。  减轻了vanishing-gradient(梯度消失) 梯度消失问题在网络深度越深的时候越容易出现,原因就是输入信息和梯度信息在很多层之间传递导致的,而现在这种dense -connection相当于每一层都直接连接input和loss,因此就可以减轻梯度消失现象,这样更深网络不是问题。

5.1.2减少了参数数量

  如下图所示,在ResNet中, 参数量与

成正比,而在DenseNet中参数量与

成正比, 因为

远小于

, 所以DenseNet的参数量小很多。

5.1.3保证低维度特征

  在标准的卷积网络中,最终输出只会利用提取最高层次的特征。  而在DenseNet中,它使用了不同层次的特征,倾向于给出更平滑的决策边界。这也解释了为什么训练数据不足时DenseNet表现依旧良好。

5.2DenseNet不足

  DenseNet的不足在于由于需要进行多次Concatnate操作,数据需要被复制多次显存容易增加得很快,需要一定的显存优化技术。另外,DenseNet是一种更为特殊的网络,ResNet则相对一般化一些,因此ResNet的应用范围更广泛。

6.使用Pytorch实现DenseNet

6.1实现DenseBlock中的内部结构

  这里是BN+ReLU+1x1 Conv+BN+ReLU+3x3Conv结构,最后加入dropout层以用于训练过程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class _DenseLayer(nn.Sequential):
    """Basic unit of DenseBlock (using bottleneck layer) """
    def __init__(self, num_input_features, growth_rate, bn_size, drop_rate):
        super(_DenseLayer, self).__init__()
        self.add_module("norm1", nn.BatchNorm2d(num_input_features))
        self.add_module("relu1", nn.ReLU(inplace=True))
        self.add_module("conv1", nn.Conv2d(num_input_features, bn_size*growth_rate,
                                           kernel_size=1, stride=1, bias=False))
        self.add_module("norm2", nn.BatchNorm2d(bn_size*growth_rate))
        self.add_module("relu2", nn.ReLU(inplace=True))
        self.add_module("conv2", nn.Conv2d(bn_size*growth_rate, growth_rate,
                                           kernel_size=3, stride=1, padding=1, bias=False))
        self.drop_rate = drop_rate

    def forward(self, x):
        new_features = super(_DenseLayer, self).forward(x)
        if self.drop_rate > 0:
            new_features = F.dropout(new_features, p=self.drop_rate, training=self.training)
        return torch.cat([x, new_features], 1)

6.2实现DenseBlock模块

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class _DenseBlock(nn.Sequential):
    """DenseBlock"""
    def __init__(self, num_layers, num_input_features, bn_size, growth_rate, drop_rate):
        super(_DenseBlock, self).__init__()
        for i in range(num_layers):
            layer = _DenseLayer(num_input_features+i*growth_rate, growth_rate, bn_size,
                                drop_rate)
            self.add_module("denselayer%d" % (i+1,), layer)

6.3 实现Transition层:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class _Transition(nn.Sequential):
    """Transition layer between two adjacent DenseBlock"""
    def __init__(self, num_input_feature, num_output_features):
        super(_Transition, self).__init__()
        self.add_module("norm", nn.BatchNorm2d(num_input_feature))
        self.add_module("relu", nn.ReLU(inplace=True))
        self.add_module("conv", nn.Conv2d(num_input_feature, num_output_features,
                                          kernel_size=1, stride=1, bias=False))
        self.add_module("pool", nn.AvgPool2d(2, stride=2))

6.4 实现DenseNet网络:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class DenseNet(nn.Module):
    "DenseNet-BC model"
    def __init__(self, growth_rate=32, block_config=(6, 12, 24, 16), num_init_features=64,
                 bn_size=4, compression_rate=0.5, drop_rate=0, num_classes=1000):
        """        :param growth_rate: (int) number of filters used in DenseLayer, `k` in the paper        :param block_config: (list of 4 ints) number of layers in each DenseBlock        :param num_init_features: (int) number of filters in the first Conv2d        :param bn_size: (int) the factor using in the bottleneck layer        :param compression_rate: (float) the compression rate used in Transition Layer        :param drop_rate: (float) the drop rate after each DenseLayer        :param num_classes: (int) number of classes for classification        """
        super(DenseNet, self).__init__()
        # first Conv2d
        self.features = nn.Sequential(OrderedDict([
            ("conv0", nn.Conv2d(3, num_init_features, kernel_size=7, stride=2, padding=3, bias=False)),
            ("norm0", nn.BatchNorm2d(num_init_features)),
            ("relu0", nn.ReLU(inplace=True)),
            ("pool0", nn.MaxPool2d(3, stride=2, padding=1))
        ]))

        # DenseBlock
        num_features = num_init_features
        for i, num_layers in enumerate(block_config):
            block = _DenseBlock(num_layers, num_features, bn_size, growth_rate, drop_rate)
            self.features.add_module("denseblock%d" % (i + 1), block)
            num_features += num_layers*growth_rate
            if i != len(block_config) - 1:
                transition = _Transition(num_features, int(num_features*compression_rate))
                self.features.add_module("transition%d" % (i + 1), transition)
                num_features = int(num_features * compression_rate)

        # final bn+ReLU
        self.features.add_module("norm5", nn.BatchNorm2d(num_features))
        self.features.add_module("relu5", nn.ReLU(inplace=True))

        # classification layer
        self.classifier = nn.Linear(num_features, num_classes)

        # params initialization
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.bias, 0)
                nn.init.constant_(m.weight, 1)
            elif isinstance(m, nn.Linear):
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        features = self.features(x)
        out = F.avg_pool2d(features, 7, stride=1).view(features.size(0), -1)
        out = self.classifier(out)
        return out

深度学习经典网络解析:2.AlexNet

深度学习经典网络解析:1.LeNet-5

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-02-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AiCharm 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
面经|3.一文搞通DenseNet原理与代码
在以往的网络都是从要么深(比如ResNet,解决了网络深时候的梯度消失问题)要么宽(比如GoogleNet的Inception)的网络,而作者则是从feature入手,通过对feature的极致利用达到更好的效果和更少的参数。
灿视学长
2021/05/28
9620
DenseNet:比ResNet更优的CNN模型
本篇文章首先介绍DenseNet的原理以及网路架构,然后讲解DenseNet在Pytorch上的实现。
机器学习算法工程师
2018/07/27
1.7K0
DenseNet:比ResNet更优的CNN模型
来聊聊DenseNet及其变体PeleeNet、VoVNet
前面,基础积累系列的文章讲了ResNet网络及其变体,具体可以参考文章:来聊聊ResNet及其变体,ResNet通过前层与后层的“短路连接”(Shortcuts),加强了前后层之间的信息流通,在一定程度上缓解了梯度消失现象,从而可以将神经网络搭建得很深。更进一步,这次的主角DenseNet最大化了这种前后层信息交流,通过建立前面所有层与后面层的密集连接,实现了特征在通道维度上的复用,使其可以在参数与计算量更少的情况下实现比ResNet更优的性能。
AI算法修炼营
2020/05/26
1.7K0
来聊聊DenseNet及其变体PeleeNet、VoVNet
densenet详解_dense参数
  DenseNet 见于论文《Densely Connected Convolutional Networks》,是 CVPR2017 的 oral。一般而言,为提升网络效果,研究者多从增加网络深/宽度方向着力。但 DenseNet 另辟蹊径,聚焦于特征图的极致利用。延续借助跳层连接解决梯度消失 (如 ResNet) 的思路,论文提出的 Dense Block 将所有层直接相连 (密集连接),保证特征信息最大程度的传输利用,大幅提升网络性能。
全栈程序员站长
2022/11/11
2.4K0
densenet详解_dense参数
pytorch senet_lstm pytorch
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/10
9070
pytorch senet_lstm pytorch
pytorch实现卷积神经网络_pytorch项目
论文链接:https://arxiv.org/pdf/1608.06993.pdf 顾名思义,DenseNet采用了高密度的跳连结构,对于每一层,使用先前所有层的输出作为输入,该层的输出将作为之后所有层的输入的一部分。因此对于一个dense模块,假设有 L L L层,那么存在 L ( L + 1 ) 2 \frac{L(L+1)}{2} 2L(L+1)​直接的连接。
全栈程序员站长
2022/11/10
5320
pytorch实现卷积神经网络_pytorch项目
Pytorch搭建DenseNet[通俗易懂]
首先回顾一下DenseNet的结构,DenseNet的每一层都都与前面层相连,实现了特征重用。
全栈程序员站长
2022/11/10
5310
Pytorch搭建DenseNet[通俗易懂]
基于Pytorch构建DenseNet网络对cifar-10进行分类
DenseNet是指Densely connected convolutional networks(密集卷积网络)。它的优点主要包括有效缓解梯度消失、特征传递更加有效、计算量更小、参数量更小、性能比ResNet更好。它的缺点主要是较大的内存占用。
python与大数据分析
2023/09/03
4890
基于Pytorch构建DenseNet网络对cifar-10进行分类
【现代深度学习技术】现代卷积神经网络07:稠密连接网络(DenseNet)
深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上,结合当代大数据和大算力的发展而发展出来的。深度学习最重要的技术特征是具有自动提取特征的能力。神经网络算法、算力和数据是开展深度学习的三要素。深度学习在计算机视觉、自然语言处理、多模态数据分析、科学探索等领域都取得了很多成果。本专栏介绍基于PyTorch的深度学习算法实现。 【GitCode】专栏资源保存在我的GitCode仓库:https://gitcode.com/Morse_Chen/PyTorch_deep_learning。
Francek Chen
2025/04/04
510
【现代深度学习技术】现代卷积神经网络07:稠密连接网络(DenseNet)
densenet121网络结构_resnet网络结构详解
An advantage of ResNets is that the gradient can flow directly through the identity function from later layers to the earlier layers. However, the identity function and the output of H are combined by summation, which may impede the information flow in the network.
全栈程序员站长
2022/11/11
1.7K0
densenet121网络结构_resnet网络结构详解
DenseNet模型[通俗易懂]
《Densely Connected Convolutional Networks》阅读笔记
全栈程序员站长
2022/11/10
5510
DenseNet模型[通俗易懂]
图像处理经典网络
GoogLeNet 引入了并行连结的网络结构,其基础卷积块称为 Inception 块,其结构如下:
hotarugali
2022/03/11
3.2K0
图像处理经典网络
【AI】超分辨率经典论文复现(2)——2017年
这次是这周新复现的一些超分辨率相关的机器学习的东西, 所选文章是知乎帖子 [从SRCNN到EDSR,总结深度学习端到端超分辨率方法发展历程]https://zhuanlan.zhihu.com/p/31664818 整理而来(文末点击原文可以跳转), 顺序接着上篇【AI】超分辨率经典论文复现(1)——2016年. 本文4.7k字, 篇幅不长. 由于复现了这么多网络, 现在对这个领域也熟悉了起来, 接下来我还会继续复现别的网络但是不会再这样按照一篇文章的顺序来进行了, 而是对感兴趣的进行复现然后凑够一定数量就发一篇.
ZifengHuang
2021/04/13
9300
从零开始学Pytorch(九)之批量归一化和残差网络
处理后的任意一个特征在数据集中所有样本上的均值为0、标准差为1。 标准化处理输入数据使各个特征的分布相近
墨明棋妙27
2022/09/23
9360
CNN基础 & CV基本应用
直接上代码,kaiming初始化真的猛。与LeNet相比,这里的主要变化是使用更小的学习速率训练,这是因为网络更深更广、图像分辨率更高,训练卷积神经网络就更昂贵。
Sarlren
2022/10/28
4180
CNN基础 & CV基本应用
[深度概念]·Keras实现DenseNet
先来一张图,便于理解网络结构,推荐的dense_block一般是3。两个dense_block之间的就是过渡层。每个dense_block内部都使用密集连接。
小宋是呢
2019/06/27
1.6K0
[深度概念]·Keras实现DenseNet
densenet详解_resnet详解
从2012年AlexNet大展身手以来,卷积神经网络经历了(LeNet、)AlexNet、ZFNet、VGGNet、GoogLeNet(借鉴Network in Network)、ResNet、DenseNet的大致发展路线。其实,自从ResNet提出之后,ResNet的变种网络层出不穷,各有特点,性能都略有提高。
全栈程序员站长
2022/11/10
1.6K0
densenet详解_resnet详解
DenseNet详解
作为CVPR2017年的Best Paper, DenseNet脱离了加深网络层数(ResNet)和加宽网络结构(Inception)来提升网络性能的定式思维,从特征的角度考虑,通过特征重用和旁路(Bypass)设置,既大幅度减少了网络的参数量,又在一定程度上缓解了gradient vanishing问题的产生.结合信息流和特征复用的假设,DenseNet当之无愧成为2017年计算机视觉顶会的年度最佳论文.
SIGAI学习与实践平台
2018/09/29
3770
DenseNet详解
一文总览CNN网络架构演进:从LeNet到DenseNet
卷积神经网络可谓是现在深度学习领域中大红大紫的网络框架,尤其在计算机视觉领域更是一枝独秀。CNN从90年代的LeNet开始,21世纪初沉寂了10年,直到12年AlexNet开始又再焕发第二春,从ZF Net到VGG,GoogLeNet再到ResNet和最近的DenseNet,网络越来越深,架构越来越复杂,解决反向传播时梯度消失的方法也越来越巧妙。新年有假期,就好好总结一波CNN的各种经典架构吧,领略一下CNN的发展历程中各路大神之间的智慧碰撞之美。
小草AI
2019/05/29
8770
densenet解析_给我一个承诺详细解读
这篇文章是Densely Connected Convolutional Networks的解读,在精简部分内容的同时补充了相关的概念。如有错误,敬请指正。 论文地址:https://arxiv.org/abs/1608.06993 代码地址:https://github.com/liuzhuang13/DenseNet
全栈程序员站长
2022/11/11
6830
densenet解析_给我一个承诺详细解读
相关推荐
面经|3.一文搞通DenseNet原理与代码
更多 >
LV.3
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验