YOLOv8改进 | 主干网络| 可变形卷积网络C2f_DCN【CVPR2017】


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


专栏目录:《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进


卷积神经网络(CNN)由于其构建模块中固定的几何结构,天生就局限于对几何变换的建模。为此,引入了两个新的模块来增强CNN的变换建模能力,即可变形卷积和可变形RoI池化。两者都是基于在模块的空间采样位置增加附加偏移量的思想,并从目标任务中学习这些偏移量,而不需要额外的监督。这些新模块可以很容易地替换现有CNNs中的普通对应模块,并且可以通过标准的反向传播轻松地进行端到端的训练,从而产生可变形卷积网络。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址YOLOv8改进——更新各种有效涨点方法——点击即可跳转

目录

1.原理

2. 将C2f_DCN添加到YOLOv8中

2.1 Deformable Convolutional Networks代码实现

2.2 更改init.py文件

2.3 添加yaml文件

2.4 在task.py中进行注册

2.5 执行程序

3. 完整代码分享

4. GFLOPs

5. 进阶

6. 总结


1.原理

论文地址:Deformable Convolutional Networks——点击即可跳转

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

可变形卷积网络 (DCN) 旨在通过引入可变形卷积和可变形 RoI(感兴趣区域)池化模块来增强卷积神经网络 (CNN) 的建模能力。这些模块旨在解决 CNN 在处理几何变换方面的局限性。以下是 DCN 主要原理的概述:

可变形卷积网络的关键原理:

几何变换

  • 标准 CNN 难以处理缩放、旋转和变形等几何变换,因为它们的卷积操作基于固定网格结构。

  • DCN 通过允许卷积网格根据输入图像特征进行调整和变形来解决这个问题。

可变形卷积

  • 标准卷积:使用固定网格对输入特征图进行采样。例如,3x3 内核对输入特征图中的九个固定点进行采样。

  • 可变形卷积:在标准网格采样位置引入可学习的偏移量。这些偏移量是从前面的特征图中学习到的,使网格能够变形并适应图像中对象的形状和比例。 -实现:将偏移量应用于网格点,并使用双线性插值在这些新位置进行采样以处理分数偏移。

可变形 RoI 池化

标准 RoI 池化

将给定的 RoI 划分为固定的空间箱,并在每个箱内应用最大池化以将该区域转换为固定大小的特征图。 -可变形 RoI 池化:将可学习的偏移量添加到箱化位置,使池化操作能够适应 RoI 内对象的形状。 -实现:偏移量是通过额外的卷积层学习到的,并在池化操作期间应用以动态调整箱位。

训练和集成

可变形卷积和 RoI 池化都可以在任何 CNN 架构中取代其标准对应物。

  • 偏移学习过程引入的附加参数使用反向传播进行端到端训练。

  • 可变形卷积网络可轻松集成到最先进的 CNN 架构(如 ResNet 和 Inception-ResNet)中,用于对象检测和语义分割等任务。

优点:

  • 灵活性: 通过允许采样网格和 RoI 区域变形,DCN 可以更准确地模拟复杂的几何变换和对象形状的变化。

  • 性能: 实证结果表明,DCN 显著提高了对象检测和分割等复杂视觉任务的性能,尤其是对于具有不同尺度和变形的对象。

视觉插图:

  • 可变形卷积: 采样点不是固定的 3x3 网格,而是根据学习到的偏移进行位移,从而产生更灵活和自适应的感受野。

  • 可变形 RoI 池化:动态调整 RoI 箱以更好地适应对象的形状,从而增强池化操作的有效性。

应用:

  • 对象检测:更好地处理不同大小和形状的对象。

  • 语义分割:提高复杂场景中像素标记的准确性。

综上所述,DCN 通过引入可变形卷积和 RoI 池化增强了 CNN 的几何变换建模能力。这些模块为网络提供了根据输入特征调整其结构的能力,从而提高了各种计算机视觉任务的性能。

2. 将C2f_DCN添加到YOLOv8中

2.1 Deformable Convolutional Networks代码实现

关键步骤一: 将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/block.py中,并在该文件的__all__中添加“C2f_DCN”

*注:代码过长,只放置部分代码,需要可以查看第三部分的完整代码

class DCNv2(nn.Module):def __init__(self, in_channels, out_channels, kernel_size, stride=1,padding=1, dilation=1, groups=1, deformable_groups=1):super(DCNv2, self).__init__()self.in_channels = in_channelsself.out_channels = out_channelsself.kernel_size = (kernel_size, kernel_size)self.stride = (stride, stride)self.padding = (padding, padding)self.dilation = (dilation, dilation)self.groups = groupsself.deformable_groups = deformable_groupsself.weight = nn.Parameter(torch.empty(out_channels, in_channels, *self.kernel_size))self.bias = nn.Parameter(torch.empty(out_channels))out_channels_offset_mask = (self.deformable_groups * 3 *self.kernel_size[0] * self.kernel_size[1])self.conv_offset_mask = nn.Conv2d(self.in_channels,out_channels_offset_mask,kernel_size=self.kernel_size,stride=self.stride,padding=self.padding,bias=True,)self.bn = nn.BatchNorm2d(out_channels)self.act = Conv.default_actself.reset_parameters()def forward(self, x):offset_mask = self.conv_offset_mask(x)o1, o2, mask = torch.chunk(offset_mask, 3, dim=1)offset = torch.cat((o1, o2), dim=1)mask = torch.sigmoid(mask)x = torch.ops.torchvision.deform_conv2d(x,self.weight,offset,mask,self.bias,self.stride[0], self.stride[1],self.padding[0], self.padding[1],self.dilation[0], self.dilation[1],self.groups,self.deformable_groups,True)x = self.bn(x)x = self.act(x)return xdef reset_parameters(self):n = self.in_channelsfor k in self.kernel_size:n *= kstd = 1. / math.sqrt(n)self.weight.data.uniform_(-std, std)self.bias.data.zero_()self.conv_offset_mask.weight.data.zero_()self.conv_offset_mask.bias.data.zero_()class Bottleneck_DCN(nn.Module):# Standard bottleneck with DCNdef __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):  # ch_in, ch_out, shortcut, groups, kernels, expandsuper().__init__()c_ = int(c2 * e)  # hidden channelsif k[0] == 3:self.cv1 = DCNv2(c1, c_, k[0], 1)else:self.cv1 = Conv(c1, c_, k[0], 1)if k[1] == 3:self.cv2 = DCNv2(c_, c2, k[1], 1, groups=g)else:self.cv2 = Conv(c_, c2, k[1], 1, g=g)self.add = shortcut and c1 == c2def forward(self, x):return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))

可变形卷积网络 (DCN) 以一种将适应性引入标准卷积神经网络操作的方式处理数据。

可变形卷积网络中的主要处理流程

输入数据

  • 网络的输入通常是一张图像或一批图像。

初始卷积层

  • 输入图像通过初始标准卷积层处理以提取基本特征。这些层的功能与传统 CNN 中的层类似,应用固定网格卷积操作。

可变形卷积层

  • 在初始特征提取之后,应用可变形卷积层。

  • 偏移生成:对于特征图上的每个位置,使用单独的卷积操作来预测采样网格的偏移量。这会产生一个动态学习的偏移场。

  • 可变形采样:使用预测的偏移量,调整卷积的采样网格。卷积运算不是从固定位置采样,而是从偏移定义的位置采样,这些偏移通常是分数,需要双线性插值。

  • 卷积运算:然后使用新的变形网格位置应用卷积运算,生成具有增强的对输入几何结构的适应性的输出特征图。

可变形 RoI 池化(用于对象检测/分割任务)

  • RoI 提取:根据区域提议网络 (RPN) 等方法生成的提议,从特征图中提取感兴趣区域 (RoI)。

  • RoI 的偏移生成:与可变形卷积类似,预测 RoI 箱的偏移。

  • 可变形箱化:根据学习到的偏移量调整 RoI 池化中的箱,使池化区域能够适应 RoI 内对象的形状和位置。

  • 池化操作:在这些调整后的箱内执行最大池化或平均池化,以为每个 RoI 生成固定大小的特征图。

后续卷积层

  • 可变形卷积和/或 RoI 池化层的输出将输入到后续卷积层和全连接层中,具体取决于特定架构(例如 ResNet、Faster R-CNN)。

  • 这些层继续处理特征图以执行分类、边界框回归和分割等任务。

输出层

  • 网络的最后几层产生所需的输出,例如用于对象检测的类别分数和边界框坐标,或用于语义分割的逐像素分类。

训练

  • 使用反向传播对包括可变形模块在内的网络进行端到端训练。

  • 使用适合特定任务的损失函数(例如,分类的交叉熵损失、边界框回归的平滑 L1 损失)来指导训练过程。

  • 除了标准卷积参数外,还学习了可变形卷积和 RoI 池化层的偏移量和权重。

优点

  • 适应性:网络可以适应不同的物体形状和尺度,从而提高涉及不同几何变换的任务的性能。

  • 提高性能:实证结果表明,DCN 在物体检测和语义分割等任务中的表现优于传统 CNN。

结论

DCN 通过引入可变形卷积和 RoI 池化增强了传统 CNN,使其更有能力处理复杂的几何变化。这种适应性对于提高各种计算机视觉任务的性能至关重要。

2.2 更改init.py文件

关键步骤二:修改modules文件夹下的__init__.py文件,先导入函数

然后在下面的__all__中声明函数

2.3 添加yaml文件

关键步骤三:在/ultralytics/ultralytics/cfg/models/v8下面新建文件yolov8_DCN.yaml文件,粘贴下面的内容

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'# [depth, width, max_channels]n: [ 0.33, 0.25, 1024 ]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs# YOLOv8.0n backbone
backbone:# [from, repeats, module, args]- [ -1, 1, Conv, [ 64, 3, 2 ] ]  # 0-P1/2- [ -1, 1, Conv, [ 128, 3, 2 ] ]  # 1-P2/4- [ -1, 3, C2f_DCN, [ 128, True ] ]   - [ -1, 1, Conv, [ 256, 3, 2 ] ]  # 3-P3/8- [ -1, 6, C2f_DCN, [ 256, True ] ]- [ -1, 1, Conv, [ 512, 3, 2 ] ]  # 5-P4/16- [ -1, 6, C2f_DCN, [ 512, True ] ]- [ -1, 1, Conv, [ 1024, 3, 2 ] ]  # 7-P5/32- [ -1, 3, C2f_DCN, [ 1024, True ] ]- [ -1, 1, SPPF, [ 1024, 5 ] ]  # 9# YOLOv8.0n head
head:- [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ]- [ [ -1, 6 ], 1, Concat, [ 1 ] ]  # cat backbone P4- [ -1, 3, C2f_DCN, [ 512 ] ]  # 12- [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ]- [ [ -1, 4 ], 1, Concat, [ 1 ] ]  # cat backbone P3- [ -1, 3, C2f_DCN, [ 256 ] ]  # 15 (P3/8-small)- [ -1, 1, Conv, [ 256, 3, 2 ] ]- [ [ -1, 12 ], 1, Concat, [ 1 ] ]  # cat head P4- [ -1, 3, C2f_DCN, [ 512 ] ]  # 18 (P4/16-medium)- [ -1, 1, Conv, [ 512, 3, 2 ] ]- [ [ -1, 9 ], 1, Concat, [ 1 ] ]  # cat head P5- [ -1, 3, C2f_DCN, [ 1024 ] ]  # 21 (P5/32-large)- [ [ 15, 18, 21 ], 1, Detect, [ nc ] ]  # Detect(P3, P4, P5)

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


# YOLOv8n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple# YOLOv8s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple# YOLOv8l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple# YOLOv8m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple# YOLOv8x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple

2.4 在task.py中进行注册

关键步骤四:在parse_model函数中进行注册,添加C2f_DCN,

2.5 执行程序

关键步骤五:在ultralytics文件中新建train.py,将model的参数路径设置为yolov8_DCN.yaml的路径即可

from ultralytics import YOLO# Load a model
# model = YOLO('yolov8n.yaml')  # build a new model from YAML
# model = YOLO('yolov8n.pt')  # load a pretrained model (recommended for training)model = YOLO(r'/projects/ultralytics/ultralytics/cfg/models/v8/yolov8_DCN.yaml')  # build from YAML and transfer weights# Train the model
model.train(device = [3], batch=16)

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

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

3. 完整代码分享

https://pan.baidu.com/s/1kN1rW_tmKbefMKIkUXcqLw?pwd=ybu6

提取码: ybu6 

4. GFLOPs

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

未改进的YOLOv8nGFLOPs

img

改进后的GFLOPs

5. 进阶

可以结合损失函数和注意力机制进行改进

6. 总结

可变形卷积网络 (DCN) 通过引入可变形卷积和可变形 RoI(感兴趣区域)池化模块增强了传统的卷积神经网络 (CNN)。这些模块允许采样网格和 RoI 区域通过学习偏移量动态适应输入图像中对象的形状和比例。这种适应性使网络能够更有效地处理几何变换和变化,从而显著提高对象检测和语义分割等复杂视觉任务的性能。  

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

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

相关文章

SiLM585x系列SiLM5851NHCG-DG一款具有分离的管脚输出 单通道隔离驱动器 拥有强劲的驱动能力

SiLM585x系列SiLM5851NHCG-DG是一款单通道隔离驱动器,具有分离的管脚输出,提供3.0A源电流和6.0A灌电流。主动保护功能包括退饱和过流检测、UVLO、隔离故障报警和 2.5A 米勒钳位。输入侧电源的工作电压为3V至5.5V,输出侧电源的工作电压范围为1…

小柴冲刺嵌入式系统设计师系列总目录

工作两年 逐渐意识到基础知识的重要性✌️ 意识到掌握了这个证书好像就已经掌握了80%工作中用到的知识了。剩下的就在工作的实战中学习 来和小柴一起冲刺软考吧!加油😜 【小柴冲刺软考中级嵌入式系统设计师系列】总目录 前言 专栏目标:冲刺…

涵盖多项功能的文件外发系统,了解一下

伴随着业务范围的不断扩大,信息化的迅速发展,企业与客户、供应商等合作伙伴之间的文件交换也愈加频繁,尤其涉及到核心数据,像核心技术、设计图纸等敏感数据,对其的保护也是越发重视。文件外发系统,应运而生…

Linux基础 - RAID 与 LVM 磁盘阵列技术

目录 零. 简介 一. RAID 二. LVM 三. 总结 零. 简介 在 Linux 中,RAID(Redundant Array of Independent Disks,独立磁盘冗余阵列)和 LVM(Logical Volume Manager,逻辑卷管理器)是两种常用的…

机械继电器、固态继电器和模拟开关对比分析

1 结构 2 长期可靠性 与机械继电器相比,光继电器明显提高了可靠性,因为没有活动器件。 光继电器通过 LED 进行光学控制。通常情况下,此 LED 会随着时间的推移比开关本身更快地降级,具体取决于温度、正向电流、开关速度等。随着 LE…

群辉NAS使用Kodi影视墙

目录 一、KODI安装 二、修改UI语言 1、修改显示字体 2、修改语言为中文 四、添加媒体库 五、观看电影 五、高级设置 1、视图类型 2、修改点击播动作 五、补充 1、文件组织结构及命名 2、电影信息的刮削 (1)添加影片 (2)演员管理 (3)影片管理 (4)说明 K…

基于opencv的图像拼接

利用Python的OpenCV库实现了简单的图像拼接,示例 1. 图像拼接的基本原理 图像拼接主要包括以下几个步骤: 特征检测与匹配:首先,需要在待拼接的图像之间找到匹配的关键点或特征。OpenCV提供了如SIFT、SURF、ORB等特征提取器以及…

嵌入式EMC之TVS管

整理一些网上摘抄的笔记: TVS管认识: TVS的Vc要比,DCDC的最大承受电压要小

web前端大作业--美团外卖1

文章目录 概述代码截图代码链接 概述 web美团 登录和注册功能、页面展示。 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href&quo…

Vue组件生命周期深度剖析:从创建到销毁的八大钩子实战指南

系列文章目录 Vue核心指令解析&#xff1a;探索MVVM与数据操作之美 文章目录 系列文章目录前言一、Vue生命周期是什么&#xff1f;二、钩子函数讲解1. beforeCreate( 创建前 )2. created ( 创建后 &#xff09;3. beforeMount&#xff08;挂载前&#xff09;4. mounted&#xf…

Redis-数据类型-Geospatial(地理空间索引)

文章目录 1、查看redis是否启动2、通过客户端连接redis3、切换到db5数据库4、将地理位置信息&#xff08;经度和纬度&#xff09;添加到 Redis 的键&#xff08;key&#xff09;中4.1、添加大江商厦4.2、添加西部硅谷 5、升序返回有序集key&#xff0c;让分数一起和值返回的结果…

简约的服务器监控工具Ward

什么是 Ward &#xff1f; Ward 是一个简单简约的服务器监控工具。 Ward 支持自适应设计系统。此外&#xff0c;它还支持深色主题。它仅显示主要信息&#xff0c;如果您想查看漂亮的仪表板而不是查看一堆数字和图表&#xff0c;则可以使用它。 Ward 在所有流行的操作系统上都能…

Redis缓存机制详解(数据淘汰策略、缓存击穿、缓存穿透、缓存雪崩)

Redis缓存机制详解 Redis 作为一个高效的内存数据库&#xff0c;常用于缓存系统。 其缓存机制有助于提高数据访问速度、减轻后端数据库压力。 由于 Redis 是基于内存的数据库&#xff0c;内存资源有限&#xff0c;因此需要有合理的数据淘汰策略以管理内存使用。 1. 内存数据淘…

解决chrome浏览器总是将对站点的http访问改为https的问题

问题&#xff1a;vue项目本地运行出来的地址是http开头的&#xff0c;但在chrome浏览器中无法访问&#xff0c;在Edge浏览器就可以&#xff0c;发现是chrome总是自动将http协议升级为https。 已试过的有效的方法&#xff1a; 一、无痕模式下访问 无痕模式下访问不会将http自…

java基于ssm+jsp 超市进销存管理系统

1前台首页功能模块 宜佰丰超市进销存管理系统&#xff0c;在系统首页可以查看首页、商品信息、新闻资讯、留言反馈、我的、跳转到后台、购物车等内容&#xff0c;如图1所示。 图1前台首页功能界面图 用户注册&#xff0c;在用户注册页面可以填写用户名、密码、姓名、联系电话、…

代码随想录——跳跃游戏(Leecode55)

题目链接 贪心 class Solution {public boolean canJump(int[] nums) {int cover 0;if(nums.length 1){return true;}// 只有一个元素可以达到for(int i 0; i < cover; i){// 在cover内选择跳跃步数cover Math.max(i nums[i],cover);if(cover > nums.length - 1)…

出现 defineProps is a compiler macro and no longer needs to be imported. 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 执行前端代码的时候,出现如下问题: [@vue/compiler-sfc] defineProps is a compiler macro and no longer needs to be imported.[@vue/compiler-sfc] defineEmits is a compiler macro and no longer needs to be impo…

【排序 队列】1585. 检查字符串是否可以通过排序子字符串得到另一个字符串

本文涉及知识点 排序 队列 LeetCode1585. 检查字符串是否可以通过排序子字符串得到另一个字符串 给你两个字符串 s 和 t &#xff0c;请你通过若干次以下操作将字符串 s 转化成字符串 t &#xff1a; 选择 s 中一个 非空 子字符串并将它包含的字符就地 升序 排序。 比方说&a…

LLM大语言模型-AI大模型全面介绍

简介&#xff1a; 大语言模型&#xff08;LLM&#xff09;是深度学习的产物&#xff0c;包含数十亿至数万亿参数&#xff0c;通过大规模数据训练&#xff0c;能处理多种自然语言任务。LLM基于Transformer架构&#xff0c;利用多头注意力机制处理长距离依赖&#xff0c;经过预训…

政策护航新能源:政策红利激发行业活力,助推绿色经济腾飞

随着全球气候变化问题日益严重&#xff0c;新能源行业的发展成为推动绿色经济腾飞的重要引擎。近年来&#xff0c;各国政府纷纷出台政策支持新能源产业&#xff0c;旨在激发行业活力&#xff0c;促进经济可持续发展。本文将从政策红利的角度&#xff0c;探讨新能源行业发展的现…