当前位置: 首页 > news >正文

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

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

轻量级卷积神经网络由于其低计算预算限制了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 Fclass attention2d(nn.Module):def __init__(self, in_planes, ratios, K, temperature, init_weight=True):super(attention2d, self).__init__()assert temperature%3==1self.avgpool = nn.AdaptiveAvgPool2d(1)if in_planes!=3:hidden_planes = int(in_planes*ratios)else:hidden_planes = Kself.fc1 = nn.Conv2d(in_planes, hidden_planes, 1, bias=False)self.fc2 = nn.Conv2d(hidden_planes, K, 1, bias=False)self.temperature = temperatureif 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 -=3print('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==0self.in_planes = in_planesself.out_planes = out_planesself.kernel_size = kernel_sizeself.stride = strideself.padding = paddingself.dilation = dilationself.groups = groupsself.bias = biasself.K = Kself.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 = Noneif 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.lryc.cn/news/361025.html

相关文章:

  • 23、linux系统文件和日志分析
  • 安装VS2017后,离线安装Debugging Tools for Windows(QT5.9.2使用MSVC2017 64bit编译器)
  • 路由策略实验2
  • Linux网络-守护进程版字典翻译服务器
  • Python 推导式详解:高效简洁的数据处理技巧
  • 车联网安全入门——ICSim模拟器使用
  • leetcode - 20.有效的括号(LinkedHashMap)
  • 多维数组的动态内存分配(malloc和new)
  • 71、评测OrangePi AIpro开发板和USB CAMERAOAK视频解码+推理+编码+推流测试
  • 为什么需要开局调用函数?
  • QT-demo:0轴分布图表
  • git远程仓库限额的解决方法——大文件瘦身
  • 碰撞检测技术在AI中的重要作用
  • UE5 Cesium2 最新使用地理配准子关卡构造全球场景
  • 【Java数据结构】详解LinkedList与链表(二)
  • 【精读文献】J. Environ. Manage.|青藏高原生态恢复项目下植被覆盖动态及其对生态系统服务的约束效应
  • QT之常用控件
  • 【嵌入式硬件】DRV8874电机驱动
  • 考研数学:有些无穷小不能用等价无穷小的公式?
  • 谷歌浏览器的平替,内置开挂神器,我已爱不释手!
  • UMLChina为什么叒要翻译《分析模式》?
  • npm install 安装很慢如何解决?
  • 哈夫曼树的构造,哈夫曼树的存在意义--求哈夫曼编码
  • 一个全面了解Xilinx FPGA IP核的窗口:《Xilinx系列FPGA芯片IP核详解》(可下载)
  • virtualbox识别windows上usb设备
  • LabVIEW步进电机的串口控制方法与实现
  • 云计算-高级云资源配置(Advanced Cloud Provisioning)
  • Nginx企业级负载均衡:技术详解系列(17)—— 长连接优化策略与下载服务器高效搭建
  • LabVIEW如何确保步进电机的长期稳定运行
  • vue2 bug 小白求助!!!(未解决,大概是浏览器缓存的问题或者是路由的问题)