YOLOv8目标检测创新改进与实战案例专栏
专栏目录: YOLOv8有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例
专栏链接: YOLOv8基础解析+创新改进+实战案例
介绍
摘要
我们提出了DySample,这是一种超轻量且高效的动态上采样器。尽管最近基于内核的动态上采样器(如CARAFE、FADE和SAPA)在性能上取得了显著提升,但它们引入了大量工作负载,主要是由于耗时的动态卷积以及用于生成动态内核的额外子网络。此外,FADE和SAPA需要高分辨率特征的指导,这在某种程度上限制了它们的应用场景。为了解决这些问题,我们绕过了动态卷积,从点采样的角度来构建上采样,这种方法更节省资源,并且可以轻松使用PyTorch中的标准内置函数实现。我们首先展示了一个简单的设计,然后一步步展示如何增强其上采样行为,最终实现我们新的上采样器DySample。与之前基于内核的动态上采样器相比,DySample不需要定制的CUDA包,并且参数、FLOPs、GPU内存和延迟都大大减少。除了轻量级的特点外,DySample在五个密集预测任务(包括语义分割、目标检测、实例分割、全景分割和单目深度估计)中表现优于其他上采样器。代码可在 https://github.com/tiny-smart/dysample 获取。
文章链接
论文地址:论文地址
代码地址:代码地址
基本原理
DySample是一种超轻量级且高效的动态上采样器,旨在通过学习采样来学习上采样。与传统的基于卷积核的动态上采样方法不同,DySample从点采样的角度设计,将一个点分割成多个点以实现更清晰的边缘。其核心技术原理是通过动态采样来实现上采样过程,而不需要额外的CUDA包。DySample通过寻找每个上采样点的正确语义聚类来进行采样过程,从而实现高效的上采样。与Deformable Attention等方法不同,DySample针对上采样进行了定制化设计,为每个上采样位置采样单个点,将一个点分割成s^2个上采样点。通过高度优化的PyTorch内置函数,DySample的反向传播速度较快,训练时间增加可忽略不计。在推理时间、训练内存、训练时间、GFLOPs和参数数量等方面,DySample相比其他动态上采样器具有更低的成本,且在多个密集预测任务中表现出色,包括语义分割、目标检测、实例分割、全景分割和单目深度估计。
DySample与CARAFE、FADE和SAPA等动态上采样方法的不同之处:
DySample是基于点采样的设计,将一个点分割成多个点以实现更清晰的边缘,而CARAFE、FADE和SAPA等方法是基于卷积核的动态上采样方法,通过生成动态卷积核或聚类来实现上采样。
DySample不需要高分辨率的引导特征作为输入,也不需要额外的CUDA包,而CARAFE、FADE和SAPA等方法通常需要高分辨率的引导特征以及额外的子网络或动态卷积操作。
DySample通过动态采样来实现上采样过程,寻找每个上采样点的正确语义聚类,而CARAFE、FADE和SAPA等方法通常使用动态卷积或聚类来重新组合输入特征。
DySample在实现上更加轻量级,不需要定制化的CUDA包,具有更低的计算资源消耗,而CARAFE、FADE和SAPA等方法通常需要更多的参数、FLOPs、GPU内存和推理时间。
核心代码
import torch
import torch.nn as nn
import torch.nn.functional as F
def normal_init(module, mean=0, std=1, bias=0):
"""
使用正态分布初始化网络模块的权重和偏置(如果存在)。
Args:
module (nn.Module): 要初始化的网络模块。
mean (float): 正态分布的均值。默认为0。
std (float): 正态分布的标准差。默认为1。
bias (float): 偏置的初始值。默认为0。
"""
if hasattr(module, 'weight') and module.weight is not None:
nn.init.normal_(module.weight, mean, std)
if hasattr(module, 'bias') and module.bias is not None:
nn.init.constant_(module.bias, bias)
def constant_init(module, val, bias=0):
"""
使用常数初始化网络模块的权重和偏置(如果存在)。
Args:
module (nn.Module): 要初始化的网络模块。
val (float): 权重和偏置的常数初始值。
bias (float): 偏置的初始值。默认为0。
"""
if hasattr(module, 'weight') and module.weight is not None:
nn.init.constant_(module.weight, val)
if hasattr(module, 'bias') and module.bias is not None:
nn.init.constant_(module.bias, bias)
class DySample(nn.Module):
def __init__(self, in_channels, scale=2, style='lp', groups=4, dyscope=False):
"""
动态采样模块的初始化函数。
Args:
in_channels (int): 输入通道数。
scale (int): 尺度因子。默认为2。
style (str): 采样风格,可以是'lp'(低-高)或'pl'(高-低)。默认为'lp'。
groups (int): 分组数。默认为4。
dyscope (bool): 是否启用动态范围。默认为False。
"""
super().__init__()
self.scale = scale
self.style = style
self.groups = groups
assert style in ['lp', 'pl']
if style == 'pl':
assert in_channels >= scale ** 2 and in_channels % scale ** 2 == 0
assert in_channels >= groups and in_channels % groups == 0
if style == 'pl':
in_channels = in_channels // scale ** 2
out_channels = 2 * groups
else:
out_channels = 2 * groups * scale ** 2
self.offset = nn.Conv2d(in_channels, out_channels, 1)
normal_init(self.offset, std=0.001)
if dyscope:
self.scope = nn.Conv2d(in_channels, out_channels, 1, bias=False)
constant_init(self.scope, val=0.)
self.register_buffer('init_pos', self._init_pos())
task与yaml配置
详见:https://blog.csdn.net/shangyanaf/article/details/139990001