【YOLOv10改进 -卷积Conv】 AKConv(可改变核卷积):任意数量的参数和任意采样形状的即插即用的卷积

简介: AKConv是一种可改变核卷积,旨在解决传统卷积的局限,包括固定大小的卷积窗口和卷积核尺寸。AKConv提供灵活的卷积核参数和采样形状,适应不同尺度特征。其创新点包括:1)支持任意大小和形状的卷积核;2)使用新算法确定初始采样位置;3)应用动态偏移调整采样位置;4)优化模型参数和计算效率。AKConv已应用于YOLOv8,提高网络性能。相关代码可在<https://github.com/CV-ZhangXin/AKConv>找到。

YOLOv10目标检测创新改进与实战案例专栏

专栏链接: YOLOv10 创新改进有效涨点

AKConv介绍

AKConv(可改变核卷积),主要用来解决传统卷积中固有的缺陷。

  1. 卷积窗口的固定大小:

    传统卷积中,每个神经元只关注输入数据中一个固定大小的局部区域,而不能有效地捕捉到其他窗口的信息。这在处理全局上下文信息时可能会限制网络的性能。

  2. 卷积核尺寸的固定性:

    传统卷积网络中的卷积核大小通常是固定的(如 3x3, 5x5)。这种固定尺寸的核可能不适合捕捉所有尺度的特征。例如,较小的核可能适合捕捉细粒度的特征,而较大的核可能更适合捕捉更宽泛的特征。固定的卷积核尺寸和结构限制了网络在处理多尺度特征时的灵活性和有效性。

摘要

基于卷积操作的神经网络在深度学习领域取得了显著成果,但标准卷积操作中存在两个固有缺陷。一方面,卷积操作仅限于局部窗口,无法从其他位置捕获信息,且其采样形状是固定的。另一方面,卷积核的大小固定为 k×k,这是一个固定的正方形形状,随着大小的增长,参数的数量呈平方增长。显然,在不同数据集和不同位置,目标的形状和大小是多样的。具有固定采样形状和正方形的卷积核不适应目标的变化。针对上述问题,本工作探索了可变核卷积(AKConv),它使卷积核具有任意数量的参数和任意采样形状,为网络开销与性能之间的权衡提供了更丰富的选择。在AKConv中,我们通过一种新的坐标生成算法定义了任意大小卷积核的初始位置。为适应目标的变化,我们引入偏移量来调整每个位置样本的形状。此外,我们通过使用相同大小和不同初始采样形状的AKConv来探索神经网络的效果。AKConv通过不规则卷积操作完成高效的特征提取过程,并为卷积采样形状带来更多探索选项。在代表性数据集COCO2017、VOC 7+12和VisDrone-DET2021上的目标检测实验充分展示了AKConv的优势。AKConv可以作为即插即用的卷积操作替换卷积操作以提高网络性能。相关任务的代码可在 https://github.com/CV-ZhangXin/AKConv 找到。

AKConv的创新特点:

  1. 卷积核的灵活性:AKConv支持卷积核参数的任意化设定,能够根据具体的应用需求自由调整其大小与形状,以更精准地适配不同尺度的目标特征。

  2. 初始采样位置生成算法:AKConv引入了一种创新的算法,用于为各种尺寸的卷积核确定初始采样位置,增强了网络处理不同大小目标的适应性。

  3. 动态采样位置偏移:为了应对目标形状的多样性,AKConv采用动态偏移技术调整采样位置,以实现更精确的特征捕捉。

  4. 模型参数与计算效率的优化:AKConv的参数数量可线性调节,有助于在受限的硬件资源下实现计算效率的优化,特别适合于资源受限的轻量级模型部署。

yoloV10引入AKConv

新建ultralytics/nn/Conv/AKConv.py

import torch.nn as nn
import torch
from einops import rearrange
import math


class AKConv(nn.Module):
    def __init__(self, inc, outc, num_param, stride=1, bias=None):
        super(AKConv, self).__init__()
        self.num_param = num_param
        self.stride = stride
        self.conv = nn.Sequential(nn.Conv2d(inc, outc, kernel_size=(num_param, 1), stride=(num_param, 1), bias=bias),
                                  nn.BatchNorm2d(outc),
                                  nn.SiLU())  # the conv adds the BN and SiLU to compare original Conv in YOLOv5.
        self.p_conv = nn.Conv2d(inc, 2 * num_param, kernel_size=3, padding=1, stride=stride)
        nn.init.constant_(self.p_conv.weight, 0)
        self.p_conv.register_full_backward_hook(self._set_lr)

    @staticmethod
    def _set_lr(module, grad_input, grad_output):
        grad_input = (grad_input[i] * 0.1 for i in range(len(grad_input)))
        grad_output = (grad_output[i] * 0.1 for i in range(len(grad_output)))

    def forward(self, x):
        # N is num_param.
        offset = self.p_conv(x)
        dtype = offset.data.type()
        N = offset.size(1) // 2
        # (b, 2N, h, w)
        p = self._get_p(offset, dtype)

        # (b, h, w, 2N)
        p = p.contiguous().permute(0, 2, 3, 1)
        q_lt = p.detach().floor()
        q_rb = q_lt + 1

        q_lt = torch.cat([torch.clamp(q_lt[..., :N], 0, x.size(2) - 1), torch.clamp(q_lt[..., N:], 0, x.size(3) - 1)],
                         dim=-1).long()
        q_rb = torch.cat([torch.clamp(q_rb[..., :N], 0, x.size(2) - 1), torch.clamp(q_rb[..., N:], 0, x.size(3) - 1)],
                         dim=-1).long()
        q_lb = torch.cat([q_lt[..., :N], q_rb[..., N:]], dim=-1)
        q_rt = torch.cat([q_rb[..., :N], q_lt[..., N:]], dim=-1)

        # clip p
        p = torch.cat([torch.clamp(p[..., :N], 0, x.size(2) - 1), torch.clamp(p[..., N:], 0, x.size(3) - 1)], dim=-1)

        # bilinear kernel (b, h, w, N)
        g_lt = (1 + (q_lt[..., :N].type_as(p) - p[..., :N])) * (1 + (q_lt[..., N:].type_as(p) - p[..., N:]))
        g_rb = (1 - (q_rb[..., :N].type_as(p) - p[..., :N])) * (1 - (q_rb[..., N:].type_as(p) - p[..., N:]))
        g_lb = (1 + (q_lb[..., :N].type_as(p) - p[..., :N])) * (1 - (q_lb[..., N:].type_as(p) - p[..., N:]))
        g_rt = (1 - (q_rt[..., :N].type_as(p) - p[..., :N])) * (1 + (q_rt[..., N:].type_as(p) - p[..., N:]))

        # resampling the features based on the modified coordinates.
        x_q_lt = self._get_x_q(x, q_lt, N)
        x_q_rb = self._get_x_q(x, q_rb, N)
        x_q_lb = self._get_x_q(x, q_lb, N)
        x_q_rt = self._get_x_q(x, q_rt, N)

        # bilinear
        x_offset = g_lt.unsqueeze(dim=1) * x_q_lt + \
                   g_rb.unsqueeze(dim=1) * x_q_rb + \
                   g_lb.unsqueeze(dim=1) * x_q_lb + \
                   g_rt.unsqueeze(dim=1) * x_q_rt

        x_offset = self._reshape_x_offset(x_offset, self.num_param)
        out = self.conv(x_offset)

        return out

修改tasks.py

详见:https://blog.csdn.net/shangyanaf/article/details/139991759

相关文章
|
人工智能 监控 网络协议
【网络技术】心跳机制(入门讲解)
【网络技术】心跳机制(入门讲解)
|
机器学习/深度学习 编解码 计算机视觉
YOLOv11改进策略【Head】| ASFF 自适应空间特征融合模块,改进检测头Detect_ASFF
YOLOv11改进策略【Head】| ASFF 自适应空间特征融合模块,改进检测头Detect_ASFF
2554 13
YOLOv11改进策略【Head】| ASFF 自适应空间特征融合模块,改进检测头Detect_ASFF
|
计算机视觉
YOLOv11改进策略【损失函数篇】| Shape-IoU:考虑边界框形状和尺度的更精确度量
YOLOv11改进策略【损失函数篇】| Shape-IoU:考虑边界框形状和尺度的更精确度量
1647 4
|
9月前
|
人工智能 自然语言处理 前端开发
深度解析Playwright MCP:功能、优势与挑战,AI如何提升测试效率与覆盖率
Playwright MCP通过AI与浏览器交互,实现自然语言驱动的自动化测试。它降低门槛、提升效率,助力测试工程师聚焦高价值工作,是探索性测试与快速验证的新利器。
|
9月前
|
人工智能 数据可视化 数据库
如何与AI有效沟通:描述问题及提示词技巧
本文整理自Anthropic的AI素养课程,系统梳理“描述能力”(Description)三大维度:结果、过程与行为描述,结合提示工程六大技巧,揭示如何通过清晰沟通将AI从工具变为思维伙伴,提升人机协作效能。
921 4
|
机器学习/深度学习 编解码 测试技术
RT-DETR改进策略【注意力机制篇】| WACV-2024 D-LKA 可变形的大核注意 针对大尺度、不规则的目标图像
RT-DETR改进策略【注意力机制篇】| WACV-2024 D-LKA 可变形的大核注意 针对大尺度、不规则的目标图像
429 2
RT-DETR改进策略【注意力机制篇】| WACV-2024 D-LKA 可变形的大核注意 针对大尺度、不规则的目标图像
|
机器学习/深度学习 算法 计算机视觉
YOLOv5 | 卷积模块 | 即插即用的可变核卷积AKConv【附代码+小白可上手】
本文介绍了YOLOv5模型的一个改进,即使用AKConv替代标准卷积以提高目标检测效果。AKConv允许卷积核有任意数量的参数和采样形状,增强了对不同目标形状和大小的适应性。教程详细讲解了AKConv的原理,提供了代码实现步骤,包括如何将AKConv添加到YOLOv5中,并给出了相关代码片段。此外,还分享了完整的YOLOv5 AKConv实现代码和GFLOPs计算,鼓励读者动手实践。通过这一改进,网络在保持性能的同时增加了灵活性。
|
机器学习/深度学习 存储 计算机视觉
基于YOLOv8深度学习的路面坑洞检测与分割系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割(2)
基于YOLOv8深度学习的路面坑洞检测与分割系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割
|
人工智能 达摩院 语音技术
用1张图像生成数字人,快来制作你的AI视频吧~
最近魔搭上线了一项新能力——仅需输入单张人像照片,利用文字或语音驱动即可秒级生成数字人AI视频!这让小编的短视频UP梦又重新启航燃起了希望!它完全解救了社恐星人,图生视频能力替你说话、唱歌、讲段子、吟诗....无需再对着摄像头NG,一整个绝绝子叠buff!
用1张图像生成数字人,快来制作你的AI视频吧~
|
NoSQL 算法 Java
万字 + 20张图 Zookeeper分布式锁实现原理
前面我们通过Redis分布式锁实现Redisson 15问文章剖析了Redisson的源码,理清了Redisson是如何实现的分布式锁和一些其它的特性。这篇文章就来接着剖析Zookeeper分布式锁的实现框架Curator的源码,看看Curator是如何实现Zookeeper分布式锁的,以及它提供的哪些其它的特性。
万字 + 20张图 Zookeeper分布式锁实现原理