DenseNet(密集连接的卷积网络)

这篇具有很好参考价值的文章主要介绍了DenseNet(密集连接的卷积网络)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

DenseNet是指Densely connected convolutional networks(密集卷积网络)。它的优点主要包括有效缓解梯度消失、特征传递更加有效、计算量更小、参数量更小、性能比ResNet更好。它的缺点主要是较大的内存占用。

1. DenseNet网络

DenseNet网络与Resnet、GoogleNet类似,都是为了解决深层网络梯度消失问题的网络。

  • Resnet从深度方向出发,通过建立前面层与后面层之间的“短路连接”或“捷径”,从而能训练出更深的CNN网络。
  • GoogleNet从宽度方向出发,通过Inception(利用不同大小的卷积核实现不同尺度的感知,最后进行融合来得到图像更好的表征)。
  • DenseNet从特征入手,通过对前面所有层与后面层的密集连接,来极致利用训练过程中的所有特征,进而达到更好的效果和减少参数。

2.设计理念

为了详细对比Resnet与DenseNet的区别,分别介绍Resnet网络和DenseNet网络。

2.1 Resnet

densenet,机器视觉,深度学习,网络,深度学习,计算机视觉

ResNet网络的短路连接机制(其中+代表的是元素级相加操作)

在Resnet网络中,通过一个残差连接将输入部分内容与卷积后的内容结合在一起。如果卷积层因为层数过深而不起作用,这不会影响最终的结果。哪一层卷积层起作用就调用哪一层卷积层,从而避免了层数过深的问题。这也是残差结构所带来的优势所在。

2.2 DenseNet

densenet,机器视觉,深度学习,网络,深度学习,计算机视觉

DenseNet网络的密集连接机制(其中c代表的是channel级连接操作)

在DenseNet中,一个更激进的密集连接机制被设计用来充分利用特征。简单来说就是每一层的特征都被保存下来,在后面的每次卷积操作中用到。因此,每一层的网络结构都用到了前面的所有信息(包括卷积操作前和卷积操作后的信息)。

注意:在Resnet网络结构中,网路的残差连接是+操作。即:两个数据规模是相同的,得到的数据跟前面的数据规模也是相同的。而DenseNet网络中,是合并操作。即:在channel维度上连接在一起(这里各个层的特征图大小是相同的)。

2.3 密集连接的实现

首先实现DenseBlock中的内部结构,这里是BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv结构,最后也加入dropout层以用于训练过程。

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)
        #通过torch.cat操作将前面的数据合并在一起 
        #类似如:第一次操作:[x, features] 
        #      第二次操作:[x, features_1] 其中,此时的x为[x, features] 
        return torch.cat([x, new_features], 1)

3. DenseNet的实现

DenseNet的网络结构如图所示。可以发现,该网络主要有Dense Block和Transition Layer两个部分组成。
DenseNet共在三个图像分类数据集(CIFAR,SVHN和ImageNet)上进行测试。对于前两个数据集,其输入图片大小为 32 × 32 ,所使用的DenseNet在进入第一个DenseBlock之前,首先进行进行一次3x3卷积(stride=1),卷积核数为16(对于DenseNet-BC为 2 k )。DenseNet共包含三个DenseBlock,各个模块的特征图大小分别为 32 × 32, 16 × 16 和 8 × 8 ,每个DenseBlock里面的层数相同。最后的DenseBlock之后是一个global AvgPooling层,然后送入一个softmax分类器。注意,在DenseNet中,所有的3x3卷积均采用padding=1的方式以保证特征图大小维持不变。对于基本的DenseNet,使用如下三种网络配置:{ L = 40 , k = 12 },{ L = 100 , k = 12 },{ L = 40 , k = 24 } 。而对于DenseNet-BC结构,使用如下三种网络配置:{ L = 100 , k = 12 } , { L = 250 , k = 24 } ,{ L = 190 , k = 40 } 。这里的 L 指的是网络总层数(网络深度),一般情况下,我们只把带有训练参数的层算入其中,而像Pooling这样的无参数层不纳入统计中,此外BN层尽管包含参数但是也不单独统计,而是可以计入它所附属的卷积层。对于普通的L = 40 , k = 12 网络,除去第一个卷积层、2个Transition中卷积层以及最后的Linear层,共剩余36层,均分到三个DenseBlock可知每个DenseBlock包含12层。其它的网络配置同样可以算出各个DenseBlock所含层数。

densenet,机器视觉,深度学习,网络,深度学习,计算机视觉

ImageNet数据集上所采用的DenseNet结构

3.1 Dense Block的实现

由于后面层的输入会非常大,DenseBlock内部可以采用bottleneck层来减少计算量,主要是原有的结构中增加1x1 Conv,如图所示,即BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv,称为DenseNet-B结构。其中1x1 Conv得到 4 k个特征图它起到的作用是降低特征数量,从而提升计算效率。
densenet,机器视觉,深度学习,网络,深度学习,计算机视觉

DenseBlock模块,内部是密集连接方式(输入特征数线性增长):

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)

3.2 Transition Layer的实现

对于Transition层,它主要是连接两个相邻的DenseBlock,并且降低特征图大小。Transition层包括一个1x1的卷积和2x2的AvgPooling,结构为BN+ReLU+1x1 Conv+2x2 AvgPooling。另外,Transition层可以起到压缩模型的作用。假定Transition的上接DenseBlock得到的特征图channels数为m ,Transition层可以产生 θ m个特征(通过卷积层),其中 θ ∈ ( 0 , 1 ] 是压缩系数(compression rate)。当 θ = 1时,特征个数经过Transition层没有变化,即无压缩,而当压缩系数小于1时,这种结构称为DenseNet-C,文中使用 θ = 0.5。对于使用bottleneck层的DenseBlock结构和压缩系数小于1的Transition组合结构称为DenseNet-BC。
Transition层,它主要是一个卷积层和一个池化层:

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))

3.3 DenseNet网络

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

3.4 DenseNet-121网络

这里实现了DenseNet-121网络,且可以通过设置是否预训练来加载Pytorch模型中的DenseNet-121模型。

def densenet121(pretrained=False, **kwargs):
    """DenseNet121"""
    model = DenseNet(num_init_features=64, growth_rate=32, block_config=(6, 12, 24, 16),
                     **kwargs)

    if pretrained:
        # '.'s are no longer allowed in module names, but pervious _DenseLayer
        # has keys 'norm.1', 'relu.1', 'conv.1', 'norm.2', 'relu.2', 'conv.2'.
        # They are also in the checkpoints in model_urls. This pattern is used
        # to find such keys.
        pattern = re.compile(
            r'^(.*denselayer\d+\.(?:norm|relu|conv))\.((?:[12])\.(?:weight|bias|running_mean|running_var))$')
        state_dict = model_zoo.load_url(model_urls['densenet121'])
        for key in list(state_dict.keys()):
            res = pattern.match(key)
            if res:
                new_key = res.group(1) + res.group(2)
                state_dict[new_key] = state_dict[key]
                del state_dict[key]
        model.load_state_dict(state_dict)
    return model

4. 测试

最后,我们使用一个简单的代码来对模型进行测试。
注意:输入必须是224,224的图片,如果不是的话模型参数需要进行调整。

model = densenet121()
x = torch.rand(size=(1,3,224,224))
print(model(x).shape)

文章来源地址https://www.toymoban.com/news/detail-671965.html

到了这里,关于DenseNet(密集连接的卷积网络)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CNN 卷积神经网络之 DenseNet 网络的分类统一项目(包含自定义数据集的获取)

    本章实现的项目是DenseNet 网络对花数据集的五分类,下载链接: 基于迁移学习的 DenseNet 图像分类项目 DenseNet 网络是在 ResNet 网络上的改进,大概的网络结构如下: 图像识别任务主要利用神经网络对图像进行特征提取,最后通过全连接层将特征和分类个数进行映射。传统的网

    2024年02月04日
    浏览(44)
  • 【AI】《动手学-深度学习-PyTorch版》笔记(十九):卷积神经网络模型(GoogLeNet、ResNet、DenseNet)

    发布时间:2014年 GoogLeNet的贡献是如何选择合适大小的卷积核,并将不同大小的卷积核组合使用。 之前介绍的网络结构都是串行的,GoogLeNet使用并行的网络块,称为“Inception块” “Inception块”前后进化了四次,论文链接: [1]https://arxiv.org/pdf/1409.4842.pdf [2]https://arxiv.org/pdf/150

    2024年02月12日
    浏览(61)
  • 经典神经网络论文超详细解读(六)——DenseNet学习笔记(翻译+精读+代码复现)

    上一篇我们介绍了ResNet:经典神经网络论文超详细解读(五)——ResNet(残差网络)学习笔记(翻译+精读+代码复现) ResNet通过短路连接,可以训练出更深的CNN模型,从而实现更高的准确度。今天我们要介绍的是 DenseNet(《Densely connected convolutional networks》) 模型,它的基本

    2024年02月03日
    浏览(56)
  • 经典神经网络(7)DenseNet及其在Fashion-MNIST数据集上的应用

    DenseNet 不是通过更深或者更宽的结构,而是通过特征重用来提升网络的学习能力。 ResNet 的思想是:创建从“靠近输入的层” 到 “靠近输出的层” 的直连。而 DenseNet 做得更为彻底:将所有层以前馈的形式相连,这种网络因此称作 DenseNet 。 DenseNet 具有以下的优点: 缓解梯度

    2024年02月12日
    浏览(35)
  • Densenet模型详解

    DenseNet的主要思想是密集连接,它在卷积神经网络(CNN)中引入了密集块(Dense Block),在这些块中,每个层都与前面所有层直接连接。这种设计可以让信息更快速地传播,有助于解决梯度消失的问题,同时也能够增加网络的参数共享,减少参数量,提高模型的效率和性能。

    2024年02月11日
    浏览(31)
  • DenseNet详解

    入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删。 ✨完整代码在我的github上,有需要的朋友可以康康✨ https://github.com/tt-s-t/Deep-Learning.git 目录 一、DenseNet网络的背景 二、DenseNet网络结构 1、Dense Block——特征重

    2024年02月05日
    浏览(29)
  • 使用 TensorFlow 创建 DenseNet 121

            本篇示意DenseNet如何在tensorflow上实现,DenseNet与ResNet有类似的地方,都有层与层的“短路”方式,但两者对层的短路后处理有所不同,本文遵照原始论文的技术路线,完整复原了DenseNet的全部网络。

    2024年02月07日
    浏览(29)
  • J4 - ResNet与DenseNet结合

    🍨 本文为🔗365天深度学习训练营 中的学习记录博客 🍖 原作者:K同学啊 | 接辅导、项目定制 系统: Linux 语言: Python3.8.10 深度学习框架: Pytorch2.0.0+cu118 显卡:GTX2080TI 原始的DenseNet结构图如下: 原始的ResNet结构图如下: 经过对比可以发现,ResNet的恒等块是经过了3个Conv层,而

    2024年01月20日
    浏览(34)
  • DenseNet代码复现+超详细注释(PyTorch)

    关于DenseNet的原理和具体细节,可参见上篇解读:经典神经网络论文超详细解读(六)——DenseNet学习笔记(翻译+精读+代码复现) 接下来我们就来复现一下代码。 整个DenseNet模型主要包含三个核心细节结构,分别是 DenseLayer (整个模型最基础的原子单元,完成一次最基础的

    2023年04月23日
    浏览(46)
  • CNN(四):ResNet与DenseNet结合--DPN

     🍨 本文为 🔗365天深度学习训练营 中的学习记录博客 🍖 原作者: K同学啊|接辅导、项目定制      前面实现了ResNet和DenseNet的算法,了解了它们有各自的特点: ResNet:通过建立前面层与后面层之间的“短路连接”(shortcu),其特征则直接进行sum操作,因此channel数不变;

    2024年02月13日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包