深度学习训练营之Densenet网络

深度学习训练营

  • 原文链接
  • 环境介绍
  • 前言
  • 设计理念
  • 网络结构
  • 实验结果和讨论
  • pytorch实现DenseNet
  • 附录

原文链接

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍦 参考文章:365天深度学习训练营-第J3周:Densenet网络学习
  • 🍖 原作者:K同学啊|接辅导、项目定制

环境介绍

  • 语言环境:Python3.9.13
  • 编译器:jupyter notebook
  • 深度学习环境:TensorFlow2

前言

在计算机视觉领域当中,卷积神经网络(CNN)已经成为最主流的方法.CNN当中十分重要的就在于ResNet的出现,ResNet可以训练出更深的CNN模型,实现较高的准确度,有助于训练过程当中梯度的反向传播,从而训练出更深的CNN网络,
DenseNet(Densely connected convolutional networks),其基本思路和ResNet一致,重要的在于其将前面所有层与后面层的密集连接.
其一大特色在于通过特征在channel上实现特征重用(feature reuse)

设计理念

相较于ResNet,DenseNet提出了更加激进的密集连接机制,简单的来说,就是当前层是会接受前面所有的层作为额外的输入,也正是因为如此表现的更加紧密
对于一个 L L L 层的网络,DenseNet共包含 L ( L + 1 ) 2 \frac{L(L+1)}{2} 2L(L+1)个连接,这相较于ResNet,这是一种密集连接。而且DenseNet是直接concat来自不同层的特征图,这可以实现特征重用,提升效率,这一特点也是DenseNet与ResNet最主要的区别。
标准神经网络:
传统的网络在 l l l层的输出为 x l = H l ( x l − 1 ) x_l=H_l (x_{l-1}) xl=Hl(xl1)
在这里插入图片描述
ResNet:
对于ResNet来说,增加了来自上一层的输入的 i d e n t i t y identity identity函数: x l = H l ( x l − 1 ) + x l − 1 x_l=H_l(x _{l−1})+x_{l−1} xl=Hl(xl1)+xl1
在这里插入图片描述

DenseNet:
在DenseNet当中会连接到所有的层作为输入: x l = H l ( [ x 0 , x 1 , ⋅ , x l − 1 ] ) x_l=H_l([x_0,x_1,\cdot,x_{l-1}]) xl=Hl([x0,x1,,xl1])
在这里插入图片描述
需要注意到的是 H l ( ⋅ ) H_l(⋅) Hl()表示非线性转化函数( n o n − l i n e a r t r a n s f o r m a t i o n non-linear \\ transformation nonlineartransformation)
,这当中是包括像 B N BN BN, R e L U ReLU ReLU等格式各样的卷积层的组合操
DenseNet的密集连接方式要求了其需要保证特征图的一致,为解决这样的问题,使用到 D e n s B l o c k + T r a n s i t i o n DensBlock+Transition DensBlock+Transition的结构,其中 D e n s e B l o c k DenseBlock DenseBlock包含多个层的模块,保证每一层的特征图一样,可以实现层与层之间的密集连接
请添加图片描述

网络结构

D e n s e N e t DenseNet DenseNet的网络结构主要利用 D e n s e B l o c k DenseBlock DenseBlock T r a n s i t i o n Transition Transition组成
请添加图片描述
D e n s e B l o c k DenseBlock DenseBlock当中,每一个层的特征图大小一致,可以在 c h a n n e l channel channel维度上链接, D e n s e B l o c k DenseBlock DenseBlock的非线性组合函数 H ( ⋅ ) H(⋅) H()采用 B N + R e L U + 3 ∗ 3 C o n v BN+ReLU+3*3Conv BN+ReLU+33Conv的结构,
注意所有的 D e n s e B l o c k DenseBlock DenseBlock中各个层卷积之后会输出 k k k个特征图,即得到的特征图的 c h a n n e l channel channel数为 k k k,由于本身 D e n s e B l o c k DenseBlock DenseBlock随着深度的不断增加,其输入会不断增多,这样 k k k在不需要设置过高的情况下就可以得到很好的训练效果
请添加图片描述
为了减少计算量, D e n s e B l o c k DenseBlock DenseBlock内部采用bottleneck层减少计算量,即 B N + R e L U + 1 ∗ 1 C o n v + B N + R e L U + 3 ∗ 3 C o n v BN+ReLU+1*1 Conv+BN+ReLU+3*3Conv BN+ReLU+11Conv+BN+ReLU+33Conv,称为 D e n s e N e t − B DenseNet-B DenseNetB结构 ,其中 1 ∗ 1 C o n v 1*1Conv 11Conv可以得到 4 k 4k 4k个特征图,做到了降低特征数量,缩短了计算所需时间
请添加图片描述
对于Transition层,使用两个相邻的DenseBlock,从而降低特征图大小,结构为 B N + R e L U + 1 x 1 C o n v + 2 x 2 A v g P o o l i n g BN+ReLU+1x1 Conv+2x2 AvgPooling BN+ReLU+1x1Conv+2x2AvgPooling,另外,Transition层起到了压缩模型的作用,假定Transition上接 D e n s e B l o c k DenseBlock DenseBlock得到的特征图 c h a n n e l channel channel数为 m m m,使用Transition层产生 θ m \theta m θm个特征(经过卷积层, θ ∈ ( 0 , 1 ] \theta \in(0,1] θ(0,1]是压缩系数,只要 θ < 1 \theta <1 θ<1就相当于对特征个数经过Transition层发生了变化),文章中 θ = 0.5 \theta=0.5 θ=0.5,对于bottleneck层的DenseBlock结构和压缩系数小于1的Transition结构称为DenseNet-BC
论文当中ImageNet数据集所采用的网络配置如下图所示:请添加图片描述

实验结果和讨论

给出了DenseNet在CIFAR-100和ImagetNet数据集上与ResNet的对比结果,如下图,可以看得出来DenseNet的网络性能成功在更小的参数下超越了 ResNet-1001
在这里插入图片描述
在ImageNet数据集上ResNet和DenseNet之间的比较
请添加图片描述
综合来看,DenseNet的优势如下;

  • 由于密集连接方式,DenseNet提升了梯度的反向传播,使得模型更加容易训练,由于每层可以直接到达最后的误差信号,实现了隐式的"deep supervision"
  • 参数更小且计算更高效,这有点违反直觉,由于DenseNet是通过concat特征来实现短路连接,实现了特征重用,并且采用较小的growth rate,每个层所独有的特征图是比较小的
  • 由于特征复用,最后的分类器使用了低级特征

pytorch实现DenseNet

B N + R e L U + 1 x 1 C o n v + B N + R e L U + 3 x 3 C o n v BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv BN+ReLU+1x1Conv+BN+ReLU+3x3Conv结构

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)

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

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

最后是实现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

选择不同的网络参数可以实现不同深度的DenseNet

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

附录

参考内容连接:
详解DenseNet(密集连接的卷积网络)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/22151.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据分享】1901-2021年1km分辨率逐月平均气温栅格数据(全国/分省/免费获取)

气温数据是我们最常用的气象指标之一&#xff0c;之前我们给大家分享过1950-2022年0.1 x 0.1精度的逐月平均气温栅格数据和逐年平均气温栅格数据&#xff08;均可查询之前的文章获悉详情&#xff09;&#xff01; 本次我们分享的是精度更高的气温栅格数据——1901-2021年1km分…

【C++】类和对象(3)

文章目录 一、初始化列表二、explicit关键字三、static成员四、友元4.1 友元函数4.2 友元类 五、内部类六、匿名对象七、编译器的优化 一、初始化列表 首先我们先回顾一下构造函数&#xff0c;对象的初始化由构造函数来完成&#xff0c;我们可以在构造函数的函数体内对对象的成…

asp.net就业满意度问调查系统

本系统主要有会员&#xff08;调查者&#xff09;和管理员&#xff0c;他们具体的功能如下&#xff1a; 会员功能&#xff1a;注册&#xff0c;登录&#xff0c;修改个人信息&#xff0c;调查&#xff0c;查看调查结果及影响&#xff0c;留言,首先是会员注册&#xff0c;注册后…

广域通信网 - HDLC 高级数据链路控制协议

文章目录 1 概述2 HDLC2.1 帧类型2.2 帧结构 3 扩展3.1 网工软考真题 1 概述 #mermaid-svg-JEuFH1qP4tY5jI5p {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-JEuFH1qP4tY5jI5p .error-icon{fill:#552222;}#mermaid-…

python如何连接mysql数据库

python链接mysql数据库要用到pymysql模块中的connect &#xff0c;connect函数是pymysql模块中 用于连接MySQL数据库的一个函数。 所以连接mysql之前需要先导入pymysql模块。 第一步&#xff0c;mysql模块下载 方法1&#xff08;使用pip命令安装&#xff09;&#xff1a; 因…

MySQL数据库基础4-内置函数

文章目录 日期函数字符串函数数学函数其他函数 日期函数 函数名称描述current date()当前日期current time()当前时间current timestamp()当前时间戳date(datetime)返回datetime参数的日期部分date add(date, interval d_value type)在date中添加日期或时间&#xff0c;interv…

调用百度API自动生成春联

目录 1、作者介绍2、百度智能春联介绍录2.1 功能介绍2.2 技术特色 3、智能春联API接口介绍3.1 请求参数3.2 返回参数 4. 操作流程5. 代码实现 1、作者介绍 范宇帅&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生 研究方向&#xff1a;多机器人协…

Windows安装Ubuntu双系统

Windows安装Ubuntu双系统 1.下载Ubuntu 16.04&#xff0c;地址https://releases.ubuntu.com/16.04/ 2.下载Rufus&#xff0c;地址https://rufus.ie/zh/ 3.准备U盘&#xff0c;烧录系统 4.磁盘分区 5.重启&#xff0c;按住shift键 本人电脑是联想小新 Windows11系统&#xff0…

Elasticsearch环境搭建(Windows)

一、介绍 布式、RESTful 风格的搜索和分析。 Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎。Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。Kibana 使您能够以交互方式探索、可视化和分享对数据的见解&#xff0c;并管…

Spring Cloud第二季--服务网关Gateway

文章目录 一、Gateway和Zuul的区别二、Gateway的核心概念三、小试牛刀3.1、代码测试3.2、关于Predicate3.3、关于Filter 一、Gateway和Zuul的区别 Spring Cloud Gateway是在Spring生态系统之上构建的API网关服务&#xff0c;基于Spring 5&#xff0c;Spring Boot 2和 Project …

【文献研究】轴辐式航线网络设计—Liner hub-and-spoke shipping network design

学习文献&#xff1a;轴辐式航线网络设计—Liner hub-and-spoke shipping network design 3. 模型建立 轴辐式航线网络设计 三级轴辐式网络&#xff1a;喂给港-二级枢纽港-一级枢纽港 主要考虑的限制条件&#xff1a;多种类型的集装箱船舶、转运时间、多种类型的集装箱 转运操…

Windows 11部署WSL(Windows Subsystem for Linux——适用于Windows的Linux子系统)

文章目录 前言一、Windows 11部署WSL&#xff08;Windows Subsystem for Linux&#xff09;1.打开控制面板→程序→启动或关闭 Windows 功能2.勾选 “适用于 Linux 的 Windows 子系统” 和 “虚拟机平台”3.立即重新启动电脑4.按win键或者点击左下角的windows图标打开微软的应用…

使用C++快速上手ProtoBuf (一)

文章目录 课程目标一、初始ProtoBuf1. 序列化概念2.ProtoBuf是什么3.ProtoBuf的使⽤特点 二、安装ProtoBuf三、教学思路四、快速上⼿步骤1&#xff1a;创建.proto文件步骤2&#xff1a;编译contacts.proto⽂件&#xff0c;⽣成C⽂件步骤3&#xff1a;序列化与反序列化的使⽤⼩结…

人员与叉车防撞预警方案

叉车是仓库重吨位运输设备&#xff0c;在工厂、港口、码头、物流企业等有着广泛的使用。然而&#xff0c;叉车事故频繁发生已经引起人们的广泛关注。多数叉车因为前方货物遮挡的视线盲区多&#xff0c;极容易发生事故&#xff0c;例如撞伤人或货架导致货物倒塌伤人&#xff0c;…

Promise面试题

Promise面试题&#xff0c;带你搞懂同步异步执行顺序 前置知识面试题面试题一面试题二面试题三面试题四 分析面试题一分析面试题二分析面试题三分析面试题四分析 前置知识 Promise中的then方法 then&#xff1a;指定用于得到成功value的成功回调和用于得到失败reason的失败回调…

C语言深度解析--数组

目录 一维数组的创建与初始化 一维数组的创建&#xff1a; 一维数组的初始化&#xff1a; 一维数组的使用&#xff1a; 一维数组在内存中的存储&#xff1a; 二维数组的创建与初始化 二维数组的创建&#xff1a; 二维数组的初始化&#xff1a; 二维数组的使用&#xf…

字节跳动开源其云原生数据仓库 ByConity

动手点关注 干货不迷路 ‍ ‍项目简介 ByConity 是字节跳动开源的云原生数据仓库&#xff0c;它采用计算-存储分离的架构&#xff0c;支持多个关键功能特性&#xff0c;如计算存储分离、弹性扩缩容、租户资源隔离和数据读写的强一致性等。通过利用主流的 OLAP 引擎优化&#xf…

Hive---拉链表设计与实现

1 数据同步问题 Hive在实际工作中主要用于构建离线数据仓库&#xff0c;定期的从各种数据源中同步采集数据到Hive中&#xff0c;经过分层转换提供数据应用。比如每天需要从MySQL中同步最新的订单信息、用户信息、店铺信息等到数据仓库中&#xff0c;进行订单分析、用户分析。 …

使用Gradle7.6.1 + SpringBoot3.0.2 + java17创建微服务项目(学习)

这是一个大胆的决定 这里是导航 技术栈开发工具一、创建gradle父子项目&#xff08;deity&#xff09;1.0 简单流程示意1.1、IDEA中主要图示1.1.1 项目结构图1.1.2 IDEA中 Gradle配置 1.2、deity父项目build.gradle文件1.3、deity父项目settings.gradle文件1.4、子项目build.g…

django ORM框架 第四章 聚合函数

上一章&#xff1a;django ORM框架 第三章 关联表的数据创建与查询_做测试的喵酱的博客-CSDN博客 一、聚合函数类型&#xff1a; from django.db.models import Q, Count, Avg, Max, Min 班级表&#xff1a; 学生信息表&#xff1a; 1.1 Count 模版&#xff1a; QuerySet.…