YOLOv5改进 | 独家创新篇 | 利用DCNv3结合DLKA形成全新的注意力机制(全网独家创新)

本文主要是介绍YOLOv5改进 | 独家创新篇 | 利用DCNv3结合DLKA形成全新的注意力机制(全网独家创新),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  一、本文介绍

本文给大家带来的机制是由我独家创新结合Deformable Large Kernel Attention (D-LKA) 注意力机制和DCNv3可变形卷积的全新注意力机制模块(算是二次创新)D-LKA的基本原理是结合了大卷积核和可变形卷积的注意力机制,通过采用大卷积核来模拟类似自我关注的感受野,同时避免了传统自我关注机制的高计算成本,同时我们利用DCNv3来优化其中的可变形卷积,本文内容为我独家整理。

 欢迎大家订阅我的专栏一起学习YOLO! 

专栏目录:YOLOv5改进有效涨点目录 | 包含卷积、主干、检测头、注意力机制、Neck上百种创新机制

专栏回顾:YOLOv5改进专栏——持续复现各种顶会内容——内含100+创新

目录

  一、本文介绍

二、Deformable-LKA机制原理

2.1 Deformable-LKA的基本原理

2.2 大卷积核

2.3 可变形卷积DCNv3

2.4 2D和3D适应性

三、核心代码

四、添加方式教程

4.1 修改一

4.2 修改二 

4.3 修改三 

4.4 修改四 

五、Deformable-LKA的yaml文件和运行记录

5.1 Deformable-LKA的yaml文件

5.2 Deformable-LKA的训练过程截图 

五、本文总结


二、Deformable-LKA机制原理

论文地址:官方论文地址

代码地址:官方代码地址

​​


2.1 Deformable-LKA的基本原理

Deformable Large Kernel Attention (D-LKA) 的基本原理是结合了大卷积核和可变形卷积的注意力机制,通过采用大卷积核来模拟类似自我关注的感受野,同时避免了传统自我关注机制的高计算成本。此外,D-LKA通过可变形卷积来灵活调整采样网格,使得模型能够更好地适应不同的数据模式。可以将其分为以下几点:

1. 大卷积核: D-LKA 使用大卷积核来捕捉图像的广泛上下文信息,模仿自我关注机制的感受野。

2. 可变形卷积: 结合可变形卷积技术,允许模型的采样网格根据图像特征灵活变形,适应不同的数据模式。

3. 2D和3D适应性: D-LKA的2D和3D版本,使其在处理不同深度的数据时表现出色。

下面我来分别讲解这三种主要的改进机制->


2.2 大卷积核

大卷积核(Large Kernel)是一种用于捕捉图像中的广泛上下文信息的机制。它模仿自注意力(self-attention)机制的感受野,但是使用更少的参数和计算量。通过使用深度可分离的卷积(depth-wise convolution)深度可分离的带扩张的卷积(depth-wise dilated convolution),可以有效地构造大卷积核。这种方法允许网络在较大的感受野内学习特征,同时通过减少参数数量来降低计算复杂度。在Deformable LKA中,大卷积核与可变形卷积结合使用,进一步增加了模型对复杂图像模式的适应性。

上图为变形大核注意力(Deformable Large Kernel Attention, D-LKA)模块的架构。从图中可以看出,该模块由多个卷积层组成,包括:

1. 标准的2D卷积(Conv2D)。
2. 带有偏移量的变形卷积(Deformable Convolution, Deform-DW Conv2D),允许网络根据输入特征自适应地调整其感受野。
3. 偏移场(Offsets Field)的计算,它是由一个标准卷积层生成,用于指导变形卷积层如何调整其采样位置。
4. 激活函数GELU,增加非线性。


2.3 可变形卷积DCNv3

首先我们先来介绍一个大的概念DCN全称为Deformable Convolutional Networks,翻译过来就是可变形卷积的意思,其是一种用于目标检测和图像分割的卷积神经网络模块,通过引入可变形卷积操作来提升模型对目标形变的建模能力。

什么是可变形卷积?我们看下图来看一下就了解了。

上图中展示了标准卷积和可变形卷积中的采样位置。在标准卷积(a)中,采样位置按照规则的网格形式排列(绿色点)。这意味着卷积核在进行卷积操作时,会在输入特征图的规则网格位置上进行采样。

而在可变形卷积(b)中,采样位置是通过引入偏移量进行变形的(深蓝色点),并用增强的偏移量(浅蓝色箭头)进行表示。这意味着在可变形卷积中,不再局限于规则的网格位置,而是可以根据需要在输入特征图上自由地进行采样。

通过引入可变形卷积,可以推广各种变换,例如尺度变换、(异向)长宽比和旋转等变换,这在(c)和(d)中进行了特殊情况的展示。这说明可变形卷积能够更灵活地适应不同类型的变换,从而增强了模型对目标形变的建模能力。

总之,标准卷积(规则采样)在进行卷积操作时按照规则网格位置进行采样,而可变形卷积通过引入偏移量来实现非规则采样,从而在形状变换(尺度、长宽比、旋转等)方面具有更强的泛化能力。

下面是一个三维的角度来分析大家应该会看的更直观。

其中左侧的是输入特征,右侧的是输出特征,我们的卷积核大小是一个3x3的,我们将输入特征中3x3区域映射为输出特征中的1x1,问题就在于这个3x3的区域怎么选择,传统的卷积就是规则的形状,可变形卷积就是在其中加入一个偏移量,然后对于个每个点分别计算,然后改变3x3区域中每个点的选取,提取一些可能具有更丰富特征的点,从而提高检测效果。

下面我们来看一下在实际检测效果中,可变形卷积的效果,下面的图片分别为大物体、中物体、小物体检测,其中红色的部分就是我们提取出来的特征。

图中的每个图像三元组展示了三个级别的3×3可变形滤波器的采样位置(每个图像中有729个红色点),以及分别位于背景(左侧)、小物体(中间)和大物体(右侧)上的三个激活单元(绿色点)。

这个图示的目的是说明在不同的物体尺度上,可变形卷积中的采样位置如何变化。在左侧的背景图像中,可变形滤波器的采样位置主要集中在图像的背景部分。在中间的小物体图像中,采样位置的焦点开始向小物体的位置移动,并在小物体周围形成更密集的采样点。在右侧的大物体图像中,采样位置进一步扩展并覆盖整个大物体,以更好地捕捉其细节和形变。

通过这些图示,我们可以观察到可变形卷积的采样位置可以根据不同的目标尺度自适应地调整,从而在不同尺度的物体上更准确地捕捉特征。这增强了模型对于不同尺度目标的感知能力,并使其更适用于不同尺度物体的检测任务,这也是为什么开头的地方我说了本文适合于各种目标的检测对象。

上图可能可能更加直观一些。


2.4 2D和3D适应性

2D和3D适应性指的是Deformable Large Kernel Attention(D-LKA)技术应用于不同维度数据的能力2D D-LKA专为处理二维图像数据设计,适用于常见的医学成像方法,如X射线或MRI中的单层切片。而3D D-LKA则扩展了这种技术,使其能够处理三维数据集,充分利用体积图像数据中的空间上下文信息。3D版本特别擅长于交叉深度数据理解,即能够在多个层面上分析和识别图像特征,这对于体积重建和更复杂的医学成像任务非常有用。

上图展示了3D和2D Deformable Large Kernel Attention(D-LKA)模型的网络架构。左侧是3D D-LKA模型,右侧是2D D-LKA模型。

1. 3D D-LKA模型(左侧):包含多个3D D-LKA块,这些块在下采样和上采样之间交替,用于深度特征学习和分辨率恢复。

2. 2D D-LKA模型(右侧):利用MaxViT块作为编码器组件,并在不同的分辨率级别上使用2D D-LKA块,通过扩展(Patch Expanding)和D-LKA注意力机制进行特征学习。


三、核心代码

核心代码的使用方式看章节四!

import warnings
import torch
from torch import nn
import torch.nn.functional as F
from torch.nn.init import xavier_uniform_, constant___all__ = ['C3_DCNv3_DLKA', 'deformable_LKA_Attention']def _get_reference_points(spatial_shapes, device, kernel_h, kernel_w, dilation_h, dilation_w, pad_h=0, pad_w=0,stride_h=1, stride_w=1):_, H_, W_, _ = spatial_shapesH_out = (H_ - (dilation_h * (kernel_h - 1) + 1)) // stride_h + 1W_out = (W_ - (dilation_w * (kernel_w - 1) + 1)) // stride_w + 1ref_y, ref_x = torch.meshgrid(torch.linspace(# pad_h + 0.5,# H_ - pad_h - 0.5,(dilation_h * (kernel_h - 1)) // 2 + 0.5,(dilation_h * (kernel_h - 1)) // 2 + 0.5 + (H_out - 1) * stride_h,H_out,dtype=torch.float32,device=device),torch.linspace(# pad_w + 0.5,# W_ - pad_w - 0.5,(dilation_w * (kernel_w - 1)) // 2 + 0.5,(dilation_w * (kernel_w - 1)) // 2 + 0.5 + (W_out - 1) * stride_w,W_out,dtype=torch.float32,device=device))ref_y = ref_y.reshape(-1)[None] / H_ref_x = ref_x.reshape(-1)[None] / W_ref = torch.stack((ref_x, ref_y), -1).reshape(1, H_out, W_out, 1, 2)return refdef _generate_dilation_grids(spatial_shapes, kernel_h, kernel_w, dilation_h, dilation_w, group, device):_, H_, W_, _ = spatial_shapespoints_list = []x, y = torch.meshgrid(torch.linspace(-((dilation_w * (kernel_w - 1)) // 2),-((dilation_w * (kernel_w - 1)) // 2) +(kernel_w - 1) * dilation_w, kernel_w,dtype=torch.float32,device=device),torch.linspace(-((dilation_h * (kernel_h - 1)) // 2),-((dilation_h * (kernel_h - 1)) // 2) +(kernel_h - 1) * dilation_h, kernel_h,dtype=torch.float32,device=device))points_list.extend([x / W_, y / H_])grid = torch.stack(points_list, -1).reshape(-1, 1, 2). \repeat(1, group, 1).permute(1, 0, 2)grid = grid.reshape(1, 1, 1, group * kernel_h * kernel_w, 2)return griddef dcnv3_core_pytorch(input, offset, mask, kernel_h,kernel_w, stride_h, stride_w, pad_h,pad_w, dilation_h, dilation_w, group,group_channels, offset_scale):# for debug and test only,# need to use cuda version insteadinput = F.pad(input,[0, 0, pad_h, pad_h, pad_w, pad_w])N_, H_in, W_in, _ = input.shape_, H_out, W_out, _ = offset.shaperef = _get_reference_points(input.shape, input.device, kernel_h, kernel_w, dilation_h, dilation_w, pad_h, pad_w, stride_h, stride_w)grid = _generate_dilation_grids(input.shape, kernel_h, kernel_w, dilation_h, dilation_w, group, input.device)spatial_norm = torch.tensor([W_in, H_in]).reshape(1, 1, 1, 2). \repeat(1, 1, 1, group * kernel_h * kernel_w).to(input.device)sampling_locations = (ref + grid * offset_scale).repeat(N_, 1, 1, 1, 1).flatten(3, 4) + \offset * offset_scale / spatial_normP_ = kernel_h * kernel_wsampling_grids = 2 * sampling_locations - 1# N_, H_in, W_in, group*group_channels -> N_, H_in*W_in, group*group_channels -> N_, group*group_channels, H_in*W_in -> N_*group, group_channels, H_in, W_ininput_ = input.view(N_, H_in * W_in, group * group_channels).transpose(1, 2). \reshape(N_ * group, group_channels, H_in, W_in)# N_, H_out, W_out, group*P_*2 -> N_, H_out*W_out, group, P_, 2 -> N_, group, H_out*W_out, P_, 2 -> N_*group, H_out*W_out, P_, 2sampling_grid_ = sampling_grids.view(N_, H_out * W_out, group, P_, 2).transpose(1, 2). \flatten(0, 1)# N_*group, group_channels, H_out*W_out, P_sampling_input_ = F.grid_sample(input_, sampling_grid_, mode='bilinear', padding_mode='zeros', align_corners=False)# (N_, H_out, W_out, group*P_) -> N_, H_out*W_out, group, P_ -> (N_, group, H_out*W_out, P_) -> (N_*group, 1, H_out*W_out, P_)mask = mask.view(N_, H_out * W_out, group, P_).transpose(1, 2). \reshape(N_ * group, 1, H_out * W_out, P_)output = (sampling_input_ * mask).sum(-1).view(N_,group * group_channels, H_out * W_out)return output.transpose(1, 2).reshape(N_, H_out, W_out, -1).contiguous()class to_channels_first(nn.Module):def __init__(self):super().__init__()def forward(self, x):return x.permute(0, 3, 1, 2)class to_channels_last(nn.Module):def __init__(self):super().__init__()def forward(self, x):return x.permute(0, 2, 3, 1)def build_norm_layer(dim,norm_layer,in_format='channels_last',out_format='channels_last',eps=1e-6):layers = []if norm_layer == 'BN':if in_format == 'channels_last':layers.append(to_channels_first())layers.append(nn.BatchNorm2d(dim))if out_format == 'channels_last':layers.append(to_channels_last())elif norm_layer == 'LN':if in_format == 'channels_first':layers.append(to_channels_last())layers.append(nn.LayerNorm(dim, eps=eps))if out_format == 'channels_first':layers.append(to_channels_first())else:raise NotImplementedError(f'build_norm_layer does not support {norm_layer}')return nn.Sequential(*layers)def build_act_layer(act_layer):if act_layer == 'ReLU':return nn.ReLU(inplace=True)elif act_layer == 'SiLU':return nn.SiLU(inplace=True)elif act_layer == 'GELU':return nn.GELU()raise NotImplementedError(f'build_act_layer does not support {act_layer}')def _is_power_of_2(n):if (not isinstance(n, int)) or (n < 0):raise ValueError("invalid input for _is_power_of_2: {} (type: {})".format(n, type(n)))return (n & (n - 1) == 0) and n != 0class CenterFeatureScaleModule(nn.Module):def forward(self,query,center_feature_scale_proj_weight,center_feature_scale_proj_bias):center_feature_scale = F.linear(query,weight=center_feature_scale_proj_weight,bias=center_feature_scale_proj_bias).sigmoid()return center_feature_scaleclass DCNv3_pytorch(nn.Module):def __init__(self,channels=64,kernel_size=3,dw_kernel_size=None,stride=1,pad=1,dilation=1,group=4,offset_scale=1.0,act_layer='GELU',norm_layer='LN',center_feature_scale=False):"""DCNv3 Module:param channels:param kernel_size:param stride:param pad:param dilation:param group:param offset_scale:param act_layer:param norm_layer"""super().__init__()if channels % group != 0:raise ValueError(f'channels must be divisible by group, but got {channels} and {group}')_d_per_group = channels // groupdw_kernel_size = dw_kernel_size if dw_kernel_size is not None else kernel_size# you'd better set _d_per_group to a power of 2 which is more efficient in our CUDA implementationif not _is_power_of_2(_d_per_group):warnings.warn("You'd better set channels in DCNv3 to make the dimension of each attention head a power of 2 ""which is more efficient in our CUDA implementation.")self.offset_scale = offset_scaleself.channels = channelsself.kernel_size = kernel_sizeself.dw_kernel_size = dw_kernel_sizeself.stride = strideself.dilation = dilationself.pad = padself.group = groupself.group_channels = channels // groupself.offset_scale = offset_scaleself.center_feature_scale = center_feature_scaleself.dw_conv = nn.Sequential(nn.Conv2d(channels,channels,kernel_size=dw_kernel_size,stride=1,padding=(dw_kernel_size - 1) // 2,groups=channels),build_norm_layer(channels,norm_layer,'channels_first','channels_last'),build_act_layer(act_layer))self.offset = nn.Linear(channels,group * kernel_size * kernel_size * 2)self.mask = nn.Linear(channels,group * kernel_size * kernel_size)self.input_proj = nn.Linear(channels, channels)self.output_proj = nn.Linear(channels, channels)self._reset_parameters()if center_feature_scale:self.center_feature_scale_proj_weight = nn.Parameter(torch.zeros((group, channels), dtype=torch.float))self.center_feature_scale_proj_bias = nn.Parameter(torch.tensor(0.0, dtype=torch.float).view((1,)).repeat(group, ))self.center_feature_scale_module = CenterFeatureScaleModule()def _reset_parameters(self):constant_(self.offset.weight.data, 0.)constant_(self.offset.bias.data, 0.)constant_(self.mask.weight.data, 0.)constant_(self.mask.bias.data, 0.)xavier_uniform_(self.input_proj.weight.data)constant_(self.input_proj.bias.data, 0.)xavier_uniform_(self.output_proj.weight.data)constant_(self.output_proj.bias.data, 0.)def forward(self, input):""":param query                       (N, H, W, C):return output                     (N, H, W, C)"""input = input.permute(0, 2, 3, 1)N, H, W, _ = input.shapex = self.input_proj(input)x_proj = xx1 = input.permute(0, 3, 1, 2)x1 = self.dw_conv(x1)offset = self.offset(x1)mask = self.mask(x1).reshape(N, H, W, self.group, -1)mask = F.softmax(mask, -1).reshape(N, H, W, -1)x = dcnv3_core_pytorch(x, offset, mask,self.kernel_size, self.kernel_size,self.stride, self.stride,self.pad, self.pad,self.dilation, self.dilation,self.group, self.group_channels,self.offset_scale)if self.center_feature_scale:center_feature_scale = self.center_feature_scale_module(x1, self.center_feature_scale_proj_weight, self.center_feature_scale_proj_bias)# N, H, W, groups -> N, H, W, groups, 1 -> N, H, W, groups, _d_per_group -> N, H, W, channelscenter_feature_scale = center_feature_scale[..., None].repeat(1, 1, 1, 1, self.channels // self.group).flatten(-2)x = x * (1 - center_feature_scale) + x_proj * center_feature_scalex = self.output_proj(x).permute(0, 3, 1, 2)return xclass DeformConv(nn.Module):def __init__(self, in_channels, groups, kernel_size=(3, 3), padding=1, stride=1, dilation=1, bias=True):super(DeformConv, self).__init__()self.deform_conv = DCNv3_pytorch(in_channels)def forward(self, x):out = self.deform_conv(x)return outclass deformable_LKA(nn.Module):def __init__(self, dim):super().__init__()self.conv0 = DeformConv(dim, kernel_size=(5, 5), padding=2, groups=dim)self.conv_spatial = DeformConv(dim, kernel_size=(7, 7), stride=1, padding=9, groups=dim, dilation=3)self.conv1 = nn.Conv2d(dim, dim, 1)def forward(self, x):u = x.clone()attn = self.conv0(x)attn = self.conv_spatial(attn)attn = self.conv1(attn)return u * attnclass deformable_LKA_Attention(nn.Module):def __init__(self, d_model):super().__init__()self.proj_1 = nn.Conv2d(d_model, d_model, 1)self.activation = nn.GELU()self.spatial_gating_unit = deformable_LKA(d_model)self.proj_2 = nn.Conv2d(d_model, d_model, 1)def forward(self, x):shorcut = x.clone()x = self.proj_1(x)x = self.activation(x)x = self.spatial_gating_unit(x)x = self.proj_2(x)x = x + shorcutreturn xdef autopad(k, p=None, d=1):  # kernel, padding, dilation"""Pad to 'same' shape outputs."""if d > 1:k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-sizeif p is None:p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-padreturn pclass Conv(nn.Module):"""Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""default_act = nn.SiLU()  # default activationdef __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):"""Initialize Conv layer with given arguments including activation."""super().__init__()self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)self.bn = nn.BatchNorm2d(c2)self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()def forward(self, x):"""Apply convolution, batch normalization and activation to input tensor."""return self.act(self.bn(self.conv(x)))def forward_fuse(self, x):"""Perform transposed convolution of 2D data."""return self.act(self.conv(x))class Bottleneck(nn.Module):# Standard bottleneckdef __init__(self, c1, c2, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, shortcut, groups, expansionsuper().__init__()c_ = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, c_, 1, 1)self.cv2 = Conv(c_, c2, 3, 1, g=g)self.Dattention = deformable_LKA_Attention(c2)self.add = shortcut and c1 == c2def forward(self, x):return x + self.Dattention(self.cv2(self.cv1(x))) if self.add else self.Dattention(self.cv2(self.cv1(x)))class C3_DCNv3_DLKA(nn.Module):# CSP Bottleneck with 3 convolutionsdef __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansionsuper().__init__()c_ = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, c_, 1, 1)self.cv2 = Conv(c1, c_, 1, 1)self.cv3 = Conv(2 * c_, c2, 1)  # optional act=FReLU(c2)self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))def forward(self, x):return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))if __name__ == "__main__":# Generating Sample imageimage_size = (1, 64, 224, 224)image = torch.rand(*image_size)# Modelmodel = C3_DCNv3_DLKA(64, 64)out = model(image)print(out.size())


四、添加方式教程

4.1 修改一

第一还是建立文件,我们找到如下yolov5-master/models文件夹下建立一个目录名字呢就是'modules'文件夹(用群内的文件的话已经有了无需新建)!然后在其内部建立一个新的py文件将核心代码复制粘贴进去即可。


4.2 修改二 

第二步我们在该目录下创建一个新的py文件名字为'__init__.py'(用群内的文件的话已经有了无需新建),然后在其内部导入我们的检测头如下图所示。


4.3 修改三 

第三步我门中到如下文件'yolov5-master/models/yolo.py'进行导入和注册我们的模块(用群内的文件的话已经有了无需重新导入直接开始第四步即可)!

从今天开始以后的教程就都统一成这个样子了,因为我默认大家用了我群内的文件来进行修改!!


4.4 修改四 

按照我的添加在parse_model里添加即可。

到此就修改完成了,大家可以复制下面的yaml文件运行。


五、Deformable-LKA的yaml文件和运行记录

5.1 Deformable-LKA的yaml文件

主干和Neck全部用上该卷积轻量化到机制的yaml文件。

# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # 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, Conv, [512, 1, 1]],[-1, 1, nn.Upsample, [None, 2, "nearest"]],[[-1, 6], 1, Concat, [1]], # cat backbone P4[-1, 3, C3_DCNv3_DLKA, [512, False]], # 13[-1, 1, Conv, [256, 1, 1]],[-1, 1, nn.Upsample, [None, 2, "nearest"]],[[-1, 4], 1, Concat, [1]], # cat backbone P3[-1, 3, C3_DCNv3_DLKA, [256, False]], # 17 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]], # cat head P4[-1, 3, C3_DCNv3_DLKA, [512, False]], # 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]], # cat head P5[-1, 3, C3_DCNv3_DLKA, [1024, False]], # 23 (P5/32-large)[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)]


5.2 Deformable-LKA的训练过程截图 


五、本文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

 专栏回顾:YOLOv5改进专栏——持续复现各种顶会内容——内含100+创新

这篇关于YOLOv5改进 | 独家创新篇 | 利用DCNv3结合DLKA形成全新的注意力机制(全网独家创新)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/800909

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

基于 YOLOv5 的积水检测系统:打造高效智能的智慧城市应用

在城市发展中,积水问题日益严重,特别是在大雨过后,积水往往会影响交通甚至威胁人们的安全。通过现代计算机视觉技术,我们能够智能化地检测和识别积水区域,减少潜在危险。本文将介绍如何使用 YOLOv5 和 PyQt5 搭建一个积水检测系统,结合深度学习和直观的图形界面,为用户提供高效的解决方案。 源码地址: PyQt5+YoloV5 实现积水检测系统 预览: 项目背景

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

【Tools】大模型中的自注意力机制

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 自注意力机制(Self-Attention)是一种在Transformer等大模型中经常使用的注意力机制。该机制通过对输入序列中的每个元素计算与其他元素之间的相似性,

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分

【Tools】大模型中的注意力机制

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 在大模型中,注意力机制是一种重要的技术,它被广泛应用于自然语言处理领域,特别是在机器翻译和语言模型中。 注意力机制的基本思想是通过计算输入序列中各个位置的权重,以确

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

UVM:callback机制的意义和用法

1. 作用         Callback机制在UVM验证平台,最大用处就是为了提高验证平台的可重用性。在不创建复杂的OOP层次结构前提下,针对组件中的某些行为,在其之前后之后,内置一些函数,增加或者修改UVM组件的操作,增加新的功能,从而实现一个环境多个用例。此外还可以通过Callback机制构建异常的测试用例。 2. 使用步骤         (1)在UVM组件中内嵌callback函

一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究

转自: 一种改进的red5集群方案的应用: http://wenku.baidu.com/link?url=jYQ1wNwHVBqJ-5XCYq0PRligp6Y5q6BYXyISUsF56My8DP8dc9CZ4pZvpPz1abxJn8fojMrL0IyfmMHStpvkotqC1RWlRMGnzVL1X4IPOa_  基于Red5服务器集群负载均衡调度算法研究 http://ww