Bottleneck、CSP、DP结构详细介绍

news2024/12/23 6:08:15

文章目录

  • 前言
  • 一、Bottleneck
    • DarknetBottleneck
  • 二、CSP
    • CSP思想
    • pp-picodet中的CSPLayer
  • DP卷积


前言

本篇文章详细介绍了三种神经网络中常见的结构,bottleneck、CSP、DP,并附上了代码加深理解。

一、Bottleneck

Bottleneck出现在ResNet50/101/152这种深层网络中,基本思想就是先用1x1减少通道数再进行卷积最后再通过1x1升维减少计算量,最后和输入相加形成残差基本结构。
在这里插入图片描述

DarknetBottleneck

残差网络具有深远影响,有很多类似的结构,比如darknetBottleneck,这是在CSP里面用的一个子模块,是yolo里面使用的。下面看下代码,其实就是将3x3卷积和1x1升维放到了一起,理论上计算量是要大一点。

class DarknetBottleneck(nn.Layer):
    """The basic bottleneck block used in Darknet.

    Each Block consists of two ConvModules and the input is added to the
    final output. Each ConvModule is composed of Conv, BN, and act.
    The first convLayer has filter size of 1x1 and the second one has the
    filter size of 3x3.

    Args:
        in_channels (int): The input channels of this Module.
        out_channels (int): The output channels of this Module.
        expansion (int): The kernel size of the convolution. Default: 0.5
        add_identity (bool): Whether to add identity to the out.
            Default: True
        use_depthwise (bool): Whether to use depthwise separable convolution.
            Default: False
    """

    def __init__(self,
                 in_channels,
                 out_channels,
                 kernel_size=3,
                 expansion=0.5,
                 add_identity=True,
                 use_depthwise=False,
                 act="leaky_relu"):
        super(DarknetBottleneck, self).__init__()
        hidden_channels = int(out_channels * expansion)
        conv_func = DPModule if use_depthwise else ConvBNLayer
        self.conv1 = ConvBNLayer(
            in_channel=in_channels,
            out_channel=hidden_channels,
            kernel_size=1,
            act=act)
        self.conv2 = conv_func(
            in_channel=hidden_channels,
            out_channel=out_channels,
            kernel_size=kernel_size,
            stride=1,
            act=act)
        self.add_identity = \
            add_identity and in_channels == out_channels

    def forward(self, x):
        identity = x
        out = self.conv1(x)
        out = self.conv2(out)

        if self.add_identity:
            return out + identity
        else:
            return out

二、CSP

CSP思想

CSP结构出自CSPNet
下面两张图估计也是老网红了。CSP的核心思想就是把输入按照通道一分为二,只对其中一部分进行卷积等操作,另外一部分和第二部分的输出concat,也有点残差的味道。后来的yolov4的cspdarknet53就采用了这种结构,影响很广泛。
在这里插入图片描述
在这里插入图片描述

pp-picodet中的CSPLayer

以picodet里面的一段代码学习一下这个层的实现。输入分层,这里使用了两个1x1卷积,然后part2部分进行了darknetbottleneck操作,最后concat,非常简单易懂。

class CSPLayer(nn.Layer):
    """Cross Stage Partial Layer.

    Args:
        in_channels (int): The input channels of the CSP layer.
        out_channels (int): The output channels of the CSP layer.
        expand_ratio (float): Ratio to adjust the number of channels of the
            hidden layer. Default: 0.5
        num_blocks (int): Number of blocks. Default: 1
        add_identity (bool): Whether to add identity in blocks.
            Default: True
        use_depthwise (bool): Whether to depthwise separable convolution in
            blocks. Default: False
    """

    def __init__(self,
                 in_channels,
                 out_channels,
                 kernel_size=3,
                 expand_ratio=0.5,
                 num_blocks=1,
                 add_identity=True,
                 use_depthwise=False,
                 act="leaky_relu"):
        super().__init__()
        mid_channels = int(out_channels * expand_ratio)
        self.main_conv = ConvBNLayer(in_channels, mid_channels, 1, act=act)
        self.short_conv = ConvBNLayer(in_channels, mid_channels, 1, act=act)
        self.final_conv = ConvBNLayer(
            2 * mid_channels, out_channels, 1, act=act)

        self.blocks = nn.Sequential(* [
            DarknetBottleneck(
                mid_channels,
                mid_channels,
                kernel_size,
                1.0,
                add_identity,
                use_depthwise,
                act=act) for _ in range(num_blocks)
        ])

    def forward(self, x):
        x_short = self.short_conv(x)

        x_main = self.main_conv(x)
        x_main = self.blocks(x_main)

        x_final = paddle.concat((x_main, x_short), axis=1)
        return self.final_conv(x_final)

DP卷积

DP卷积就是Depth-wise and point-wise,即深度可分离卷积。假如我们见到这种结构,就是妥妥的DP卷积。
在这里插入图片描述
所谓dw卷积就是将卷积group参数设为输出通道数量。一般的卷积我们默认group=1,假设输入特征是 81x81x256,有256个通道,所需输出通道数为128,则卷积核尺寸为3x3x256,总共128个卷积核。如果group=2,则卷积核尺寸为3x3x128,总共64个卷积核。。以此类推,如果group=128,卷积核尺寸为3x3x2,只需一个卷积核。因为一个group就可以输出group数量的featuremap,因此所需卷积核数量=输出通道数量/group。一般我们所需的输出通道数与输入通道相等,即256,因此卷积核尺寸为3x3x1,group=256,也就是每个通道做一次2D卷积即可。
所谓pw卷积很简单,就是1x1卷积,目的是融合通道信息。
你会发现dw卷积之后,通道与通道之间没有任何交互,因此需要一个pw卷积进行跨通道信息融合。使用DP卷积可以大幅减少计算量,是很多轻量级网络的必备结构。
下面贴一个实现代码:

class DPModule(nn.Layer):
    """
    Depth-wise and point-wise module.
     Args:
        in_channel (int): The input channels of this Module.
        out_channel (int): The output channels of this Module.
        kernel_size (int): The conv2d kernel size of this Module.
        stride (int): The conv2d's stride of this Module.
        act (str): The activation function of this Module,
                   Now support `leaky_relu` and `hard_swish`.
    """

    def __init__(self,
                 in_channel=96,
                 out_channel=96,
                 kernel_size=3,
                 stride=1,
                 act='leaky_relu',
                 use_act_in_out=True):
        super(DPModule, self).__init__()
        initializer = nn.initializer.KaimingUniform()
        self.use_act_in_out = use_act_in_out
        self.dwconv = nn.Conv2D(
            in_channels=in_channel,
            out_channels=out_channel,
            kernel_size=kernel_size,
            groups=out_channel,
            padding=(kernel_size - 1) // 2,
            stride=stride,
            weight_attr=ParamAttr(initializer=initializer),
            bias_attr=False)
        self.bn1 = nn.BatchNorm2D(out_channel)
        self.pwconv = nn.Conv2D(
            in_channels=out_channel,
            out_channels=out_channel,
            kernel_size=1,
            groups=1,
            padding=0,
            weight_attr=ParamAttr(initializer=initializer),
            bias_attr=False)
        self.bn2 = nn.BatchNorm2D(out_channel)
        if act == "hard_swish":
            act = 'hardswish'
        self.act = act

    def forward(self, x):
        x = self.bn1(self.dwconv(x))
        if self.act:
            x = getattr(F, self.act)(x)
        x = self.bn2(self.pwconv(x))
        if self.use_act_in_out and self.act:
            x = getattr(F, self.act)(x)
        return x

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

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

相关文章

矩阵特征值怎么求?矩阵特征值计算器来帮你

大家好,这里是效率办公指南! 📚今天我们要探讨一个数学和编程领域中经常遇到的问题——矩阵特征值的计算方式,以及如何计算一个2x2矩阵的特征值。无论你是数学爱好者,还是编程高手,这个主题都可能对你有所…

29 C 语言中的随机数实现:rand 与 srand

目录 1 为什么需要随机数? 1.1 背景介绍 1.2 应用场景 2 C 语言实现随机数 2.1 rand() 函数 2.1.1 函数原型 2.1.2 功能说明 2.1.3 案例演示 2.2 srand() 函数 2.2.1 函数原型 2.2.2 功能说明 2.2.3 案例演示 2.3 指定范围的随机数 2.3.1 获…

为什么 qt 成为 c++ 界面编程的第一选择?

一、前言 为什么现在QT越来越成为界面编程的第一选择,笔者从事qt界面编程已经有接近8年,在这之前我做C界面都是基于MFC,也做过5年左右。当时为什么会从MFC转到QT,主要原因是MFC开发界面想做得好看一些十分困难,引用第…

hexo github部署,通过域名访问你的博客

hexo github部署,通过域名访问你的博客 hexo 常用命令hexo github 部署 在部署之前,了解一下hexo的常用命令 hexo 常用命令 hexo new "My New Post" # 新建文章 hexo n "My New Post"hexo generate # 生成静态文件 hexo ghexo serv…

【CTF】Nginx日志注入

Nginx日志注入: 日志包含漏洞的成因还是服务器没有进行严格的过滤 ,导致用户可以进行任意文件读取,但是前提是服务器需要开启了记录日志的功能才可以利用这个漏洞。 对于Apache,日志存放路径:/var/log/apache/access.l…

【论文阅读】FedBABU:TOWARD ENHANCED REPRESENTATION FOR FEDERATED IMAGE CLASSIFICATION

算法流程: 训练过程中冻结客户端的头部参数,只训练主体参数。训练完之后再在客户端本地跑几个epoch微调一下(文章推荐5个)。 由于该算法与FedPer思路过于相似,故读完后跑了个实验。 FedPer:训练过程中只聚合主体参数。…

Redis --- redis事务和分布式事务锁

redis事务基本实现 Redis 可以通过 MULTI,EXEC,DISCARD 和 WATCH 等命令来实现事务(transaction)功能。 > MULTI OK > SET USER "Guide哥" QUEUED > GET USER QUEUED > EXEC 1) OK 2) "Guide哥"使用 MULTI命令后可以输入…

Linux应用开发实验班——JSON-RPC

目录 前言 1.是什么JSON-RPC 2.常用的JSON函数 1.创建JSON 2.根据名字获取JSON 3.获取JSON的值 4.删除JSON 3.如何进行远程调用 服务器 客户端 4.基于JSON-RPC进行硬件操作 课程链接 前言 学习的课程是百问网韦东山老师的课程,对更详细步骤感兴趣的同学…

LINUX网络编程:Tcp(2)

目录 1.Tcp流量控制 2.滑动窗口 2.1滑动窗口的更新 2.2滑动窗口的丢包问题 1.报文丢失的情况 2.ACK丢失的情况 3.拥塞控制 3.1慢启动 3.2拥塞窗口的增长 1.Tcp流量控制 为什会有流量控制? 1.在网络通信中,假如发送方的发送能力特别的强&#xff0…

支付宝沙箱环境 支付

一 什么是沙箱: 沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境 支付宝正式和沙箱环境的区别 : AI: 从沙箱到正式环境: 当应用程序开发完成后,需要将应用程序从沙箱环境迁移到正式环境。 这通常涉及…

opencv图像增强十四:opencv两种白平衡介绍及实现

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、白平衡介绍二、灰度世界法三、完美反射法 前言 在摄影与影像领域,白平衡是一个至关重要的概念。它直接影响着画面的色彩表现,关系到…

构建网络遇到的问题-AlexNet

1.对模型进行初始化采用的一般代码 def _initialize_weights(self):for m in self.modules(): # 遍历模型每一层if isinstance(m, nn.Conv2d): # 判定m层是否属于nn.Conv2d类型nn.init.kaiming_normal_(m.weight, modefan_out, nonlinearityrelu)if m.bias is not None:nn.in…

从自动化到智能化:AI如何推动业务流程自动化

引言:从自动化到智能化的必然趋势 在当今数字化时代,企业为了提升效率、降低成本,纷纷采用自动化技术来简化重复性任务。然而,传统自动化仅限于标准化操作,无法应对复杂的决策和多变的市场环境。随着人工智能&#xff…

基于springboot垃圾分类网站

基于springboot垃圾分类网站 摘 要 本论文主要论述了如何使用JAVA语言开发一个垃圾分类网站 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述垃圾分类网站的当…

Android开发拍身份证带人像框和国徽框效果

Android开发拍身份证带人像框和国徽框效果 拍身份证时往往要带上外框辅助用户拍照,这也是很常见的需求。 一、思路 自定义Camera和自定义拍照的界面,把外框画上去,做个遮罩 二、效果图: Android开发教程实战案例源码分享-拍身…

深入理解计算机系统-Bomb Lab

使用 头歌 平台 GDB 调试器 反汇编函数

动力锂电池电芯壳体市场前景:预计2030年全球市场规模将达到49.2亿美元

动力锂电池罐起着传输能量、承载电解液、保护安全等重要作用,是锂电池的重要组成部分。 据QYResearch调研团队最新报告“全球动力锂电池电芯壳体市场报告2024-2030”显示,预计2030年全球动力锂电池电芯壳体市场规模将达到49.2亿美元,未来几年…

分布式算法

分布式场景下的核心问题 分布式场景下困扰我们的3个核心问题(CAP):一致性、可用性、分区容错性。 1、一致性(Consistency):无论服务如何拆分,所有实例节点同一时间看到是相同的数据。 2、可用性…

开源链动 2+1 模式 S2B2C 商城小程序:社交电商团队为王的新引擎

摘要:本文深入探讨在社交电商领域中,团队的重要性以及如何借助开源链动 21 模式 S2B2C 商城小程序,打造具有强大竞争力的团队,实现个人价值与影响力的放大,创造被动收入,迈向财富自由之路,同时为…

从汽车高速线束角度浅谈中控屏黑屏、闪屏及信号阈值低故障-之AEM线束测试仪应用案例

故障成因和解决方案 随着车载信息娱乐技术的迅速发展,中控屏已经成为现代汽车的标配。然而,许多主机厂和消费者在车辆使用过程中常常遇到中控屏出现黑屏、闪屏以及信号阈值低等问题,给使用带来了诸多困扰。本文将从汽车高速线束的角度&#…