365天深度学习训练营-第J4周:ResNet与DenseNet结合探索

news2024/7/30 13:15:18

   目录

一、前言

二、论文解读

三、DPN代码复现

 四、总结


一、前言

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊|接辅导、项目定制
● 难度:夯实基础⭐⭐
● 语言:Python3、Pytorch3
● 时间:2月26日-3月3日
🍺要求:
1、对Resnet和Densenet进行总结和探索结合的可能性
2、查阅论文找到结合的点

二、论文解读

论文:DPN(Dual Path Networks)

DPN是在resneXt,denseNet之后,对resnet系列的进一步创新,作者巧妙的将resnet与denseNet相结合,提出了dual path architectures,构造了DPN网络结构。

ResNet和DenseNet是近几年两种比较热门的网络结构,ResNet把输入直接加到(element-wise adding)卷积的输出上,DenseNet则把每一层的输出都拼接(concatenate)到了其后每一层的输入上。在这篇论文中作者用High Order RNN结构(HORNN)把DenseNet和ResNet联系到了一起,证明了DenseNet能从靠前的层级中提取到新的特征,而ResNet本质上是对之前层级中已提取特征的复用。通过把这两种结构的优点结合到一起,就有了最新结构Dual Path Networks(DPN)。

论文第二章、第三章详细介绍了DPN的理论基础,包含有较多的公式,简单而言就是借鉴了:

  • resnet特征重用(因为前面特征被sum到了后面层上面)
  • denseNet容易发现新特征(将前面特征均进行了concat组合)

Dual Path Architecture(DPA)以ResNet为主要框架,保证了特征的低冗余度,并在其基础上添加了一个非常小的DenseNet分支,用于生成新的特征。DPA的结构可以使用

 

 

三、DPN代码复现

pytorch实现

import torch
import torch.nn as nn
import torch.nn.functional as F
from collections import OrderedDict

__all__ = ['DPN', 'dpn92', 'dpn98', 'dpn131', 'dpn107', 'dpns']


def dpn92(num_classes=1000):
    return DPN(num_init_features=64, k_R=96, G=32, k_sec=(3,4,20,3), inc_sec=(16,32,24,128), num_classes=num_classes)


def dpn98(num_classes=1000):
    return DPN(num_init_features=96, k_R=160, G=40, k_sec=(3,6,20,3), inc_sec=(16,32,32,128), num_classes=num_classes)


def dpn131(num_classes=1000):
    return DPN(num_init_features=128, k_R=160, G=40, k_sec=(4,8,28,3), inc_sec=(16,32,32,128), num_classes=num_classes)


def dpn107(num_classes=1000):
    return DPN(num_init_features=128, k_R=200, G=50, k_sec=(4,8,20,3), inc_sec=(20,64,64,128), num_classes=num_classes)


dpns = {
    'dpn92': dpn92,
    'dpn98': dpn98,
    'dpn107': dpn107,
    'dpn131': dpn131,
}


class DualPathBlock(nn.Module):
    def __init__(self, in_chs, num_1x1_a, num_3x3_b, num_1x1_c, inc, G, _type='normal'):
        super(DualPathBlock, self).__init__()
        self.num_1x1_c = num_1x1_c

        if _type is 'proj':
            key_stride = 1
            self.has_proj = True
        if _type is 'down':
            key_stride = 2
            self.has_proj = True
        if _type is 'normal':
            key_stride = 1
            self.has_proj = False

        if self.has_proj:
            self.c1x1_w = self.BN_ReLU_Conv(in_chs=in_chs, out_chs=num_1x1_c+2*inc, kernel_size=1, stride=key_stride)

        self.layers = nn.Sequential(OrderedDict([
            ('c1x1_a', self.BN_ReLU_Conv(in_chs=in_chs, out_chs=num_1x1_a, kernel_size=1, stride=1)),
            ('c3x3_b', self.BN_ReLU_Conv(in_chs=num_1x1_a, out_chs=num_3x3_b, kernel_size=3, stride=key_stride, padding=1, groups=G)),
            ('c1x1_c', self.BN_ReLU_Conv(in_chs=num_3x3_b, out_chs=num_1x1_c+inc, kernel_size=1, stride=1)),
        ]))

    def BN_ReLU_Conv(self, in_chs, out_chs, kernel_size, stride, padding=0, groups=1):
        return nn.Sequential(OrderedDict([
            ('norm', nn.BatchNorm2d(in_chs)),
            ('relu', nn.ReLU(inplace=True)),
            ('conv', nn.Conv2d(in_chs, out_chs, kernel_size, stride, padding, groups=groups, bias=False)),
        ]))

    def forward(self, x):
        data_in = torch.cat(x, dim=1) if isinstance(x, list) else x
        if self.has_proj:
            data_o = self.c1x1_w(data_in)
            data_o1 = data_o[:,:self.num_1x1_c,:,:]
            data_o2 = data_o[:,self.num_1x1_c:,:,:]
        else:
            data_o1 = x[0]
            data_o2 = x[1]

        out = self.layers(data_in)

        summ = data_o1 + out[:,:self.num_1x1_c,:,:]
        dense = torch.cat([data_o2, out[:,self.num_1x1_c:,:,:]], dim=1)
        return [summ, dense]


class DPN(nn.Module):

    def __init__(self, num_init_features=64, k_R=96, G=32,
                 k_sec=(3, 4, 20, 3), inc_sec=(16,32,24,128), num_classes=1000):

        super(DPN, self).__init__()
        blocks = OrderedDict()

        # conv1
        blocks['conv1'] = nn.Sequential(
            nn.Conv2d(3, num_init_features, kernel_size=7, stride=2, padding=3, bias=False),
            nn.BatchNorm2d(num_init_features),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
        )

        # conv2
        bw = 256
        inc = inc_sec[0]
        R = int((k_R*bw)/256)
        blocks['conv2_1'] = DualPathBlock(num_init_features, R, R, bw, inc, G, 'proj')
        in_chs = bw + 3 * inc
        for i in range(2, k_sec[0]+1):
            blocks['conv2_{}'.format(i)] = DualPathBlock(in_chs, R, R, bw, inc, G, 'normal')
            in_chs += inc

        # conv3
        bw = 512
        inc = inc_sec[1]
        R = int((k_R*bw)/256)
        blocks['conv3_1'] = DualPathBlock(in_chs, R, R, bw, inc, G, 'down')
        in_chs = bw + 3 * inc
        for i in range(2, k_sec[1]+1):
            blocks['conv3_{}'.format(i)] = DualPathBlock(in_chs, R, R, bw, inc, G, 'normal')
            in_chs += inc

        # conv4
        bw = 1024
        inc = inc_sec[2]
        R = int((k_R*bw)/256)
        blocks['conv4_1'] = DualPathBlock(in_chs, R, R, bw, inc, G, 'down')
        in_chs = bw + 3 * inc
        for i in range(2, k_sec[2]+1):
            blocks['conv4_{}'.format(i)] = DualPathBlock(in_chs, R, R, bw, inc, G, 'normal')
            in_chs += inc

        # conv5
        bw = 2048
        inc = inc_sec[3]
        R = int((k_R*bw)/256)
        blocks['conv5_1'] = DualPathBlock(in_chs, R, R, bw, inc, G, 'down')
        in_chs = bw + 3 * inc
        for i in range(2, k_sec[3]+1):
            blocks['conv5_{}'.format(i)] = DualPathBlock(in_chs, R, R, bw, inc, G, 'normal')
            in_chs += inc

        self.features = nn.Sequential(blocks)
        self.classifier = nn.Linear(in_chs, num_classes)


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

 四、总结

DPN通过一系列非常精彩的推导分析出了ResNet和DenseNet各自的优缺点,通过将卷积网络抽象化为高层的RNN,得出了ResNet低冗余性的优点但是存在特征重用的缺点,也得出了DenseNet可以生成新特征的优点但是冗余度过高的问题,因此提出了结合ResNet和DenseNet的DPN。

DPN的结构并没有太复杂,通过Inception式的结构合并两种或者网络本质上是一种模型集成的方式,而DPN只是采用了ResNet和DenseNet的平均投票的方式仿佛过于简单了。基于模型集成的思想,我们也许可以从下面的几个角度进行进一步的优化:

  1. 采用更多种类的网络分支,例如加上SENet,NAS等等;
  2. 采用更好的集成方式,例如加上一个attention为不同的网络结构分支学习不同的权值,因为极有可能不用的网络结构在不同的深度起着不同的作用。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

难道ERP"死了",中台"凉了",低/无代码要称王了?

一句:“不上ERP等死,上了ERP找死”,可把ERP的尴尬处境说透了。 有人把ERP奉为信仰:“那些说ERP不好用的根本是没用明白。” 有人则认为ERP只是卖概念,冷嘲:“实施ERP的企业,估计一半都倒闭了。…

JavaSE-集合框架013-队列Queue及双端队列Deque

原文链接 Queue 我们可以把LinkedList当作队列来用,也可以当作链表来用。LinkedList只是一个实现方式,但是可以具备很多特点 虽然他是一个链表,但是当你从后加从前取,就是队列(Queue)。当你从后加从后取&a…

第七章 实现effect的stop功能

实现effect的stop功能 通过stop函数传入effect返回的runner 再次修改响应式对象的值的时候 不会修改成功 其实主要思路就是在调用stop函数的时候将 收集的effect依赖移除掉 老样子先给上测试用例: it(stop,()>{// 通过stop函数传入effect返回的runner 再次修…

JPG格式图片怎么弄?可以试试这些途径

在日常生活中,我们经常需要将图片转换为JPG格式,以便在各种设备上使用,因为 JPG 是一种常用的图像格式,具有广泛的兼容性和易用性。这里将介绍几种简单的方法,以帮助您将图片转换为JPG格式。方法一、使用格式转换软件转…

快速入门 Stream 流 【学习笔记】Java基础

若文章内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系博主删除。写这篇博客旨在制作笔记,方便个人在线阅览,巩固知识,无其他用途。 学习视频:【黑马 Java 基础教程…

怎么避免计算机SCI论文的重复率过高? - 易智编译EaseEditing

论文成稿前 在撰写阶段就避免重复:在撰写阶段就避免文章中的重复内容,可以减少后期修改的工作量。 在写作前,可以制定良好的计划和大纲,规划好文章的结构和内容,从而减少重复内容。 加强对相关文献的阅读 为了避免自己…

大话数据结构-迪杰斯特拉算法(Dijkstra)和弗洛伊德算法(Floyd)

6 最短路径 最短路径,对于图来说,是两顶点之间经过的边数最少的路径;对于网来说,是指两顶点之间经过的边上权值之和最小的路径。路径上第一个顶点为源点,最后一个顶点是终点。 6.1 迪杰斯特拉(Dijkstra&am…

【C语言】深度理解指针(上)

前言🌊谈到指针,想必大家都不陌生。它不仅是C语言的重难点,还是不少C初学者的噩梦。本期我们将深度探讨一些较为复杂的指针以及指针的妙用,带领大家感受指针的魅力😝。首先,我们先来复习复习指针的概念&…

dbutils给bean类对象赋值源码分析

本文重点 以ResultSetHandler的实现类BeanListHandler为例&#xff0c;探索dbutils的QueryRunner的实现细节&#xff0c;重点是如何给java bean类对象赋值。 public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws…

119.Android 简单的软键盘和菜单无缝切换效果,聊天界面软键盘无缝切换

//此效果主要通过动态设置windowSoftInputMode三种状态的切换实现&#xff1a;SOFT_INPUT_ADJUST_NOTHING、SOFT_INPUT_ADJUST_PAN、SOFT_INPUT_ADJUST_RESIZE。 1.第一步 导入需要用到的依赖库&#xff1a; //RecyclerView implementation com.android.support:recyclerview-…

做为骨干网络的分类模型的预训代码安装配置简单记录

一、安装配置环境 1、准备工作 代码地址 GitHub - bubbliiiing/classification-pytorch: 这是各个主干网络分类模型的源码&#xff0c;可以用于训练自己的分类模型。 # 创建环境 conda create -n ptorch1_2_0 python3.6 # 然后启动 conda install pytorch1.2.0 torchvision…

Anaconda环境配置Python绘图库Matplotlib的方法

本文介绍在Anaconda环境中&#xff0c;安装Python语言matplotlib模块的方法。 在之前的文章中&#xff0c;我们多次介绍了Python语言matplotlib库的使用&#xff1b;而这篇文章&#xff0c;就介绍一下在Anaconda环境下&#xff0c;配置matplotlib库的方法。 首先&#xff0c;打…

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual ...

目录 报错 解决 注意&#xff1a; - > 是追加的意思。 解决&#xff1a;分号结尾执行报错&#xff0c;然后重新输入正确的sql语句就可以了。 报错 在docker中部署mysql&#xff0c;创建进入mysql进行数据库查询的时候报错&#xff1a; ERROR 1064 (42000): You have a…

有趣的小知识(三)提升网站速度的秘诀:掌握缓存基础,让你的网站秒开

像MySql等传统的关系型数据库已经不能适用于所有的业务场景&#xff0c;比如电商系统的秒杀场景&#xff0c;APP首页的访问流量高峰场景&#xff0c;很容易造成关系型数据库的瘫痪&#xff0c;随着缓存技术的出现很好的解决了这个问题。 一、缓存的概念&#xff08;什么是缓存…

PyTorch保姆级安装教程

1 安装CUDA1.1 查找Nvidia适用的CUDA版本桌面右键&#xff0c;【打开 NVIDIA控制面板】查看【系统信息】查看NVIDIA的支持的CUDA的版本&#xff0c;下图可知支持的版本是 10.11.2 下载CUDACUDA下载官方网址https://developer.nvidia.com/cuda-toolkit-archive找到适合的版本下载…

第六章 effect.scheduler功能实现

effect.scheduler功能实现 主要先了解scheduler需要实现什么样的需求&#xff0c;有一下四点&#xff1a; 1 通过 effect 的第二个参数给定一个 scheduler 的 fn 2 effect 第一次执行的时候 还会执行 fn 3 当 响应式对象 set update 不执行fn 而是执行 scheduler 4 如果说…

面试问题【线程】

线程什么是进程什么是线程进程和线程的关系什么是并发和并行如何使用线程Thread 和 Runnable 两种开发线程的区别线程的生命周期什么是上下文切换什么是线程死锁如何避免死锁说说 sleep() 方法和 wait() 方法区别和共同点为什么我们调用 start() 方法时会执行 run() 方法&#…

Transformer学习

原论文&#xff1a;Attention Is All You Need。论文地址&#xff1a;https://arxiv.org/abs/1706.03762. Transformer是针对自然语言处理的&#xff0c;Google在2017年发表在Computation and Language&#xff0c;RNN模型记忆长度有限且无法并行化但是Tranformer解决了上述问…

解析几何北大第五版复习提纲

第一章 两向量向量积 向量积定义&#xff1a;a x b |a||b|sin几何意义&#xff1a;平行四边形面积性质&#xff1a; 两向量共线的充分必要条件是 a x b 0 数乘&#xff1a; 分配律&#xff1a; 求法&#xff1a;行列式 三向量混合积 混合积定义&#xff1a;对于一个六面体,…

快鲸SCRM发布口腔企业私域运营解决方案

口腔企业普遍面临着以下几方面运营痛点问题 1、获客成本居高不下&#xff0c;恶性竞争严重 2、管理系统落后&#xff0c;人员流失严重 3、客户顾虑多、决策时间长 4、老客户易流失&#xff0c;粘性差 以上这些痛点&#xff0c;不得不倒逼口腔企业向精细化运营客户迈进。 …