YOLOv5 | 卷积模块 | 提高网络的灵活性和表征能力的动态卷积【附代码+小白可上手】

news2024/9/24 19:15:24

💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡

轻量级卷积神经网络由于其低计算预算限制了CNNs的深度(卷积层数)和宽度(通道数),导致了性能下降和表示能力受限的问题。而动态卷积恰好能解决这一问题,这是一种增加模型复杂性而不增加网络深度或宽度的新设计。本文给大家带来的教程是将YOLOv5的Conv用Dynamic_conv替换来提取特征。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。此外还增加了进阶模块,来提高学有能力的同学进一步增长知识。帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址: YOLOv5改进+入门——持续更新各种有效涨点方法 点击即可跳转

目录

1.原理

2. 代码实现

2.1 将代码添加到YOLOv5中

2.2 新增yaml文件

2.3 注册模块

2.4 执行程序

3. 完整代码分享

4. GFLOPs

5. 进阶

6. 总结


1. 原理

论文地址Dynamic Convolution: Attention over Convolution Kernels——点击即可跳转

官方代码官方代码仓库——点击即可跳转

动态卷积的是基于注意力机制的,它允许网络动态地选择和组合多个卷积核,以适应输入数据的不同部分或特征。

  1. 多个卷积核的选择

    在传统的卷积操作中,每个卷积层通常使用固定的卷积核。而在动态卷积中,会事先定义一组多个卷积核,这些卷积核可能具有不同的大小和形状。
  2. 注意力机制

    动态卷积通过引入注意力机制来决定在每个位置使用哪些卷积核。这个注意力可以根据输入数据的不同部分或特征动态地调整,以使网络能够更好地捕捉输入数据的相关信息。
  3. 卷积核的组合

    根据注意力机制的输出,动态卷积会动态地选择并组合多个卷积核。这种组合可以通过加权求和的方式进行,其中每个卷积核的权重由注意力机制确定。
  4. 非线性激活

    组合后的卷积核将应用于输入数据,并通过非线性激活函数(如ReLU)产生输出特征图。
  5. 网络训练

    在训练过程中,网络将根据损失函数反向传播并更新注意力机制的参数,以使网络能够学习到适合任务的最佳注意力分配方式。

总的来说,动态卷积通过引入注意力机制和动态地选择和组合多个卷积核,使网络能够更灵活地适应输入数据的不同部分或特征,从而提高网络的表征能力和性能。

2. 代码实现

2.1 将代码添加到YOLOv5中

关键步骤一: 将下面代码粘贴到/projects/yolov5-6.1/models/common.py文件中

import torch
import torch.nn as nn
import torch.nn.functional as F

class attention2d(nn.Module):
    def __init__(self, in_planes, ratios, K, temperature, init_weight=True):
        super(attention2d, self).__init__()
        assert temperature%3==1
        self.avgpool = nn.AdaptiveAvgPool2d(1)
        if in_planes!=3:
            hidden_planes = int(in_planes*ratios)
        else:
            hidden_planes = K
        self.fc1 = nn.Conv2d(in_planes, hidden_planes, 1, bias=False)
        self.fc2 = nn.Conv2d(hidden_planes, K, 1, bias=False)
        self.temperature = temperature
        if init_weight:
            self._initialize_weights()


    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)

    def updata_temperature(self):
        if self.temperature!=1:
            self.temperature -=3
            print('Change temperature to:', str(self.temperature))


    def forward(self, x):
        x = self.avgpool(x)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x).view(x.size(0), -1)
        return F.softmax(x/self.temperature, 1)


class Dynamic_conv2d(nn.Module):
    def __init__(self, in_planes, out_planes, kernel_size, ratio=0.25, stride=1, padding=0, dilation=1, groups=1, bias=True, K=4,temperature=34, init_weight=True):
        super(Dynamic_conv2d, self).__init__()
        assert in_planes%groups==0
        self.in_planes = in_planes
        self.out_planes = out_planes
        self.kernel_size = kernel_size
        self.stride = stride
        self.padding = padding
        self.dilation = dilation
        self.groups = groups
        self.bias = bias
        self.K = K
        self.attention = attention2d(in_planes, ratio, K, temperature)

        self.weight = nn.Parameter(torch.Tensor(K, out_planes, in_planes//groups, kernel_size, kernel_size), requires_grad=True)
        if bias:
            self.bias = nn.Parameter(torch.Tensor(K, out_planes))
        else:
            self.bias = None
        if init_weight:
            self._initialize_weights()

        #TODO 初始化
    def _initialize_weights(self):
        for i in range(self.K):
            nn.init.kaiming_uniform_(self.weight[i])


    def update_temperature(self):
        self.attention.updata_temperature()

    def forward(self, x): # 将batch视作维度变量,进行组卷积,因为组卷积的权重是不同的,动态卷积的权重也是不同的
        softmax_attention = self.attention(x)
        batch_size, in_planes, height, width = x.size()
        x = x.view(1, -1, height, width)# 变化成一个维度进行组卷积
        weight = self.weight.view(self.K, -1)

        # 动态卷积的权重的生成, 生成的是batch_size个卷积参数(每个参数不同)
        aggregate_weight = torch.mm(softmax_attention, weight).view(-1, self.in_planes, self.kernel_size, self.kernel_size)
        if self.bias is not None:
            aggregate_bias = torch.mm(softmax_attention, self.bias).view(-1)
            output = F.conv2d(x, weight=aggregate_weight, bias=aggregate_bias, stride=self.stride, padding=self.padding,
                              dilation=self.dilation, groups=self.groups*batch_size)
        else:
            output = F.conv2d(x, weight=aggregate_weight, bias=None, stride=self.stride, padding=self.padding,
                              dilation=self.dilation, groups=self.groups * batch_size)

        output = output.view(batch_size, self.out_planes, output.size(-2), output.size(-1))
        return output

动态卷积的流程如下:

  1. 准备多个卷积核

    首先,定义一组多个卷积核,这些卷积核可能具有不同的大小和形状。这些卷积核将作为动态卷积的基本构建单元。
  2. 计算注意力分布

    对于输入数据的每个位置,通过一个注意力网络或者其他注意力机制,计算出相应位置的注意力分布。这个注意力分布表示了不同卷积核在当前位置的重要程度。
  3. 动态卷积操作

    根据注意力分布,动态地选择和组合多个卷积核。通常是通过对每个卷积核的权重进行加权求和来实现,其中每个卷积核的权重由对应位置的注意力分布确定。
  4. 应用非线性激活

    将组合后的卷积核应用于输入数据,并通过非线性激活函数(如ReLU)产生输出特征图。
  5. 网络训练

    训练过程中,通过反向传播算法优化注意力网络或其他注意力机制的参数,以使网络能够学习到适合任务的最佳注意力分配方式。同时,也会更新卷积核的参数,使得网络能够学习到更好的特征表示。
  6. 重复步骤3至5

    在每个位置上重复执行动态卷积操作,直到整个输入数据被处理完毕,生成最终的输出特征图。

总结动态卷积通过引入注意力机制来动态选择和组合多个卷积核,从而使网络能够更灵活地适应输入数据的不同部分或特征,从而提高网络的表征能力和性能。

2.2 新增yaml文件

关键步骤二:在/projects/yolov5-6.1/models下新建文件 yolov5_dynamic.yaml并将下面代码复制进去

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license

# Parameters
nc: 80  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Dynamic_conv2d, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 13

   [-1, 1, Dynamic_conv2d, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 23 (P5/32-large)

   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

温馨提示:本文只是对yolov5l基础上添加swin模块,如果要对yolov8n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。


# YOLOv5n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
 
# YOLOv5s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
 
# YOLOv5l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
 
# YOLOv5m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple
 
# YOLOv5x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple
2.3 注册模块

关键步骤三:在yolo.py中注册, 大概在260行左右添加 ‘Dynamic_conv2d’

2.4 执行程序

在train.py中,将cfg的参数路径设置为yolov5_AKConv.yaml的路径

建议大家写绝对路径,确保一定能找到

 🚀运行程序,如果出现下面的内容则说明添加成功🚀

3. 完整代码分享

https://pan.baidu.com/s/1iePDb_lNUhRKhWOevDRp3g?pwd=xs2y

提取码: xs2y 

4. GFLOPs

关于GFLOPs的计算方式可以查看:百面算法工程师 | 卷积基础知识——Convolution

未改进的YOLOv5l的GFLOPs

 改进后的YOLOv5l的GFLOPs

5. 进阶

如果想计算量变化更小,如何修改呢,看过我的修改你是否学会了呢?不如动手试试吧

如果你想尝试但又不知从何下手,可以在评论区问问大家,我看到后也会及时回复

6. 总结

动态卷积是一种通过引入注意力机制,动态选择和组合多个卷积核的方法,以提高卷积神经网络的表征能力和性能。通过在每个位置上根据输入数据的不同部分或特征动态调整卷积核的选择和权重,动态卷积能够更灵活地捕获输入数据的相关信息,并产生更具表征能力的特征表示。在训练过程中,网络通过反向传播算法优化注意力机制的参数,并更新卷积核的参数,从而学习到适合任务的最佳注意力分配方式和特征表示,进而提高了网络的性能,优化图像分类或目标检测的准确率。

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

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

相关文章

广义线性chirplet变换【附MATLAB代码】

文章来源:微信公众号:EW Frontier 摘要 时频分析方法是一种刻画信号时变特征的有效工具,在相当长的一段时间内受到了广泛的关注。随着TF算法的发展,许多先进的方法被提出,可以提供更精确的TF结果。但是,不…

第一届 长城杯 总决赛wp

第一届 长城杯 总决赛 - Ahisec 第一阶段 Zip_guessinteger 第一层bkcrack攻击部分明文,注意偏移 ​ ┌──(root㉿Ten)-[~/tools/Misc/bkcrack] └─# ./bkcrack -C zip_guessinteger.zip -c breakthroughentry.txtflag.txt.zip -p 1.txt -o 30 bkcrack 1.6.1 …

Lora理解

Parameter-Efficient Fine-Tuning (PEFT) :节约开销的做法,fine-tune少量参数,而不是整个模型; Low-Rank Adaptation (LoRA) :是PEFT的一种;冻结原参数矩阵,只更新2个小参数矩阵。

面了字节大模型算法岗,太难了。。。

节前,我们组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 汇总合集…

音视频开发9 FFmpeg 解复用框架--如何将一个影音文件(mp4文件/wav文件) 最终播放起来

一,播放器框架 二 常用音视频术语 容器/文件(Conainer/File): 即特定格式的多媒体文件, 比如mp4、flv、mkv等。 媒体流(Stream): 表示时间轴上的一段连续数据&#xff0…

基于maxkey接入jeecgboot并实现账户同步

1. 注册应用 1.1 在统一认证中心注册第三方应用 1.1.1 填写应用名和登录地址 1.1.2 填写认证地址授权方式和作用域 1.1.3 选择权限范围并提交 1.2 配置访问权限 1.2.1 指定用户组 1.1.2 选择注册的应用 1.1.3 在单点登录认证页面查看添加的应用 1.3 同步一个第三方应用的账号…

sqlserver的查询(三)

目录 10. group by(分组) 11. having(对分组后的信息过滤) 可能从这里开始,执行顺序越来越显得重要了!!! 10. group by(分组) 这个查询相比前面会有一些困难; 格式:group by 字段的集合; 功…

.NET调用阿里云人脸识别1:1简易流程保姆级教学

需要注意的是,以下内容仅限基础调用 人脸比对1:1 功能说明 该功能是两张照片对比,比对两张照片是不是同一个人,至于应用到什么场景,可以参考阿里云的官方文档,我这边以大学生项目来说的话,比如员工打卡&a…

实现销售与客流双增长!看看社区零售“排队王”如何成为顶流?

5月18日至5月26日,北京华联BHGMall燃情推出了一年一度的2024 Need(你的)BHGDay,接棒“五一”热潮,献礼“520”,通过韩式俯拍机、人生四宫格拍摄大赛、真合拍星派对、超级品牌日等丰富多彩的线上线下活动&am…

react实现动态增减表单项

在做项目的时候,甲方给的信息有限,网页的备案信息写成固定的,如下图所示 之后验收的时候,甲方要求把这个备案信息写成动态的,可以自增减,就去react组件库看看有没有具体的实现,果真有&#xff…

STM32_HAL__TIM_输出比较

概述 STM32的输出比较功能通常是指在微控制器的PWM(脉冲宽度调制)生成能力中的一个方面。STM32微控制器拥有一个或多个定时器/计数器,这些定时器/计数器可以用来生成PWM信号。PWM信号是一种重要的控制信号,广泛应用于电机控制、亮…

1分钟快速掌握JSON格式

文章目录 先说理论代码举例对象型数组型总结 先说理论 下面是JSON的几种简单数据类型: 数据类型描述数字型JavaScript中的双进度浮点类型,通常根据具体情况定义,这里是没有特殊的整形的。字符串型带双引号的Unicode,带反斜杠转义布尔型true…

探索python循环逻辑的魅力:从无限到有限

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言:循环逻辑的初步认识 二、无限循环:持续运转的引擎 三、有…

等保服务是一次性服务吗?为什么?怎么理解?

我国等保政策已经严格落地执行,但还有不少企业对于等保服务不是很了解。例如有人问,等保服务是一次性服务吗?为什么?怎么理解?今天我们就来简单回答一下,仅供参考哈! 等保服务是一次性服务吗&…

前端Vue自定义顶部搜索框:实现热门搜索与历史搜索功能

前端Vue自定义顶部搜索框:实现热门搜索与历史搜索功能 摘要: 随着前端开发复杂性的增加,组件化开发成为了提高效率和降低维护成本的有效手段。本文介绍了一个基于Vue的前端自定义顶部搜索框组件,该组件不仅具备基本的搜索功能&am…

PLC无线通讯模块在触摸屏与台达PLC之间的应用教程

本方案可以作为信捷触摸屏与台达PLC之间在台达专用协议下将有线通讯改为无线通讯的应用实例。此方案中信捷TG765触摸屏作为主站,台达DVP-32EH PLC作为从站,采用西安达泰电子日系PLC无线通讯终端——DTD435MA-V384,作为实现无线通讯的硬件设备…

十分钟精通MinIO:minio的原理、部署、操作

一、认识MinIO Minio是一个简单易用的云存储服务,就像是一个放在网络上的大文件柜。想象一下,你有一间放满了各种文件的房间,有时候你需要把这些文件分享给朋友或者在不同地方访问它们。Minio就是帮你做到这一点的工具,它让你可以…

力扣:236.二叉树的最近公共祖先(C++)

文章目录 1. 题目描述2. 题目解析2.1 思路一2.1 思路二 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 题目来源: 力扣…二叉树的最近公共祖先 1. 题目描述 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表…

JUC框架(Semaphore、CountDownLatch、CyclicBarrier)

文章目录 Semaphore(信号量)Semaphore介绍Semaphore基本概念Semaphore使用场景Semaphore示例 CountDownLatch (计数器/闭锁)CountDownLatch 介绍CountDownLatch 基本概念CountDownLatch 使用场景CountDownLatch 基本方法CountDownLatch 示例 CyclicBarri…

新能源锂电池行业创业的财富方案,锂电池回收高阶课

课程下载:https://download.csdn.net/download/m0_66047725/89292234 更多资源下载:关注我。 实战攻略 12年锂电池回收行业经验与坑全收录 课程内容: 001-课程介绍.mp4 002-锂电池的全种类认识.mp4 003-废品锂电池到级片粉末价值估算,mp…