优秀的html5网站 2016,网页小游戏在线玩4399,企业宣传模板图片,上海比较大的外贸公司有哪些论文地址#xff1a; DAT论文地址
官方地址#xff1a;官方代码的地址
代码地址#xff1a;文末有修改了官方代码BUG的代码块复制粘贴即可
一、本文介绍
本文给大家带来的是YOLOv8改进DAT(Vision Transformer with Deformable Attention)的教程#xff0c;其发布于2022… 论文地址 DAT论文地址
官方地址官方代码的地址
代码地址文末有修改了官方代码BUG的代码块复制粘贴即可
一、本文介绍
本文给大家带来的是YOLOv8改进DAT(Vision Transformer with Deformable Attention)的教程其发布于2022年CVPR2022上同时被评选为Best Paper由此可以证明其是一种十分有效的改进机制其主要的核心思想是引入可变形注意力机制和动态采样点(听着是不是和可变形动态卷积DCN挺相似)。同时在网络结构中引入一个DAT计算量由8.9GFLOPs涨到了9.4GFLOPs。本文的讲解主要包含三方面DAT的网络结构思想、DAttention的代码复现如何添加DAttention到你的结构中实现涨点下面先来分享我测试的对比图(因为资源有限我只用了100张图片的数据集进行了100个epoch的训练虽然这个实验不能产生确定性的结论但是可以作为一个参考)。
适用检测对象-各种检测目标都可以使用并不针对于某一特定的目标有效。 视频讲解-暂未更新 前文回顾-YOLOv8改进有效涨点专栏-持续复现各种最新机制 目录
一、本文介绍
二、DAT的网络结构思想
2.1 DAT的主要思想和改进
2.2 DAT的网络结构图
2.3 DAT和其他机制的对比
三、DAT即插即用的代码块
四、添加DAT到你的网络中
五、DAT可添加的位置
5.1推荐DAT可添加的位置
5.2图示DAT可添加的位置
六、本文总结 二、DAT的网络结构思想
2.1 DAT的主要思想和改进
DATVision Transformer with Deformable Attention是一种引入了可变形注意力机制的视觉TransformerDAT的核心思想主要包括以下几个方面 可变形注意力Deformable Attention传统的Transformer使用标准的自注意力机制这种机制会处理图像中的所有像素导致计算量很大。而DAT引入了可变形注意力机制它只关注图像中的一小部分关键区域。这种方法可以显著减少计算量同时保持良好的性能。 动态采样点在可变形注意力机制中DAT动态地选择采样点而不是固定地处理整个图像。这种动态选择机制使得模型可以更加集中地关注于那些对当前任务最重要的区域。 即插即用DAT的设计允许它适应不同的图像大小和内容使其在多种视觉任务中都能有效工作如图像分类、对象检测等。 总结DAT通过引入可变形注意力机制改进了视觉Transformer的效率和性能使其在处理复杂的视觉任务时更加高效和准确。 2.2 DAT的网络结构图 (a) 展示了可变形注意力的信息流。左侧部分一组参考点均匀地放置在特征图上这些点的偏移量是由查询通过偏移网络学习得到的。然后如右侧所示根据变形点从采样特征中投影出变形的键和值。相对位置偏差也通过变形点计算增强了输出转换特征的多头注意力。为了清晰展示图中仅显示了4个参考点但在实际实现中实际上有更多的点。
(b) 展示了偏移生成网络的详细结构每层输入和输出特征图的大小都有标注(这个Offset network在网络的代码中需要控制可添加可不添加)。
通过上面的方式产生多种参考点分布在图像上从而提高检测的效率最终的效果图如下- 2.3 DAT和其他机制的对比
DAT与其他视觉Transformer模型和CNN模型中的DCN可变形卷积网络的对比图如下突出了它们处理查询的不同方法(图片展示的很直观不给大家描述过程了) 三、DAT即插即用的代码块
下面的代码是DAT的网络结构代码官方的代码中存在许多bug而且参数都未定义这里我替大家都行了修改而且在使用时无需手动添加任何参数我都设置了通过模型进行了自动计算使用方法看章节四。
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import einops
from timm.models.layers import to_2tuple, trunc_normal_class LayerNormProxy(nn.Module):def __init__(self, dim):super().__init__()self.norm nn.LayerNorm(dim)def forward(self, x):x einops.rearrange(x, b c h w - b h w c)x self.norm(x)return einops.rearrange(x, b h w c - b c h w)class DAttentionBaseline(nn.Module):def __init__(self, q_size(224,224), kv_size(224,224), n_heads8, n_head_channels32, n_groups1,attn_drop0.0, proj_drop0.0, stride1,offset_range_factor-1, use_peTrue, dwc_peTrue,no_offFalse, fixed_peFalse, ksize9, log_cpbFalse):super().__init__()n_head_channels int(q_size / 8)q_size (q_size, q_size)self.dwc_pe dwc_peself.n_head_channels n_head_channelsself.scale self.n_head_channels ** -0.5self.n_heads n_headsself.q_h, self.q_w q_size# self.kv_h, self.kv_w kv_sizeself.kv_h, self.kv_w self.q_h // stride, self.q_w // strideself.nc n_head_channels * n_headsself.n_groups n_groupsself.n_group_channels self.nc // self.n_groupsself.n_group_heads self.n_heads // self.n_groupsself.use_pe use_peself.fixed_pe fixed_peself.no_off no_offself.offset_range_factor offset_range_factorself.ksize ksizeself.log_cpb log_cpbself.stride stridekk self.ksizepad_size kk // 2 if kk ! stride else 0self.conv_offset nn.Sequential(nn.Conv2d(self.n_group_channels, self.n_group_channels, kk, stride, pad_size, groupsself.n_group_channels),LayerNormProxy(self.n_group_channels),nn.GELU(),nn.Conv2d(self.n_group_channels, 2, 1, 1, 0, biasFalse))if self.no_off:for m in self.conv_offset.parameters():m.requires_grad_(False)self.proj_q nn.Conv2d(self.nc, self.nc,kernel_size1, stride1, padding0)self.proj_k nn.Conv2d(self.nc, self.nc,kernel_size1, stride1, padding0)self.proj_v nn.Conv2d(self.nc, self.nc,kernel_size1, stride1, padding0)self.proj_out nn.Conv2d(self.nc, self.nc,kernel_size1, stride1, padding0)self.proj_drop nn.Dropout(proj_drop, inplaceTrue)self.attn_drop nn.Dropout(attn_drop, inplaceTrue)if self.use_pe and not self.no_off:if self.dwc_pe:self.rpe_table nn.Conv2d(self.nc, self.nc, kernel_size3, stride1, padding1, groupsself.nc)elif self.fixed_pe:self.rpe_table nn.Parameter(torch.zeros(self.n_heads, self.q_h * self.q_w, self.kv_h * self.kv_w))trunc_normal_(self.rpe_table, std0.01)elif self.log_cpb:# Borrowed from Swin-V2self.rpe_table nn.Sequential(nn.Linear(2, 32, biasTrue),nn.ReLU(inplaceTrue),nn.Linear(32, self.n_group_heads, biasFalse))else:self.rpe_table nn.Parameter(torch.zeros(self.n_heads, self.q_h * 2 - 1, self.q_w * 2 - 1))trunc_normal_(self.rpe_table, std0.01)else:self.rpe_table Nonetorch.no_grad()def _get_ref_points(self, H_key, W_key, B, dtype, device):ref_y, ref_x torch.meshgrid(torch.linspace(0.5, H_key - 0.5, H_key, dtypedtype, devicedevice),torch.linspace(0.5, W_key - 0.5, W_key, dtypedtype, devicedevice),indexingij)ref torch.stack((ref_y, ref_x), -1)ref[..., 1].div_(W_key - 1.0).mul_(2.0).sub_(1.0)ref[..., 0].div_(H_key - 1.0).mul_(2.0).sub_(1.0)ref ref[None, ...].expand(B * self.n_groups, -1, -1, -1) # B * g H W 2return reftorch.no_grad()def _get_q_grid(self, H, W, B, dtype, device):ref_y, ref_x torch.meshgrid(torch.arange(0, H, dtypedtype, devicedevice),torch.arange(0, W, dtypedtype, devicedevice),indexingij)ref torch.stack((ref_y, ref_x), -1)ref[..., 1].div_(W - 1.0).mul_(2.0).sub_(1.0)ref[..., 0].div_(H - 1.0).mul_(2.0).sub_(1.0)ref ref[None, ...].expand(B * self.n_groups, -1, -1, -1) # B * g H W 2return refdef forward(self, x):x xB, C, H, W x.size()dtype, device x.dtype, x.deviceq self.proj_q(x)q_off einops.rearrange(q, b (g c) h w - (b g) c h w, gself.n_groups, cself.n_group_channels)offset self.conv_offset(q_off).contiguous() # B * g 2 Hg WgHk, Wk offset.size(2), offset.size(3)n_sample Hk * Wkif self.offset_range_factor 0 and not self.no_off:offset_range torch.tensor([1.0 / (Hk - 1.0), 1.0 / (Wk - 1.0)], devicedevice).reshape(1, 2, 1, 1)offset offset.tanh().mul(offset_range).mul(self.offset_range_factor)offset einops.rearrange(offset, b p h w - b h w p)reference self._get_ref_points(Hk, Wk, B, dtype, device)if self.no_off:offset offset.fill_(0.0)if self.offset_range_factor 0:pos offset referenceelse:pos (offset reference).clamp(-1., 1.)if self.no_off:x_sampled F.avg_pool2d(x, kernel_sizeself.stride, strideself.stride)assert x_sampled.size(2) Hk and x_sampled.size(3) Wk, fSize is {x_sampled.size()}else:x_sampled F.grid_sample(inputx.reshape(B * self.n_groups, self.n_group_channels, H, W),gridpos[..., (1, 0)], # y, x - x, ymodebilinear, align_cornersTrue) # B * g, Cg, Hg, Wgx_sampled x_sampled.reshape(B, C, 1, n_sample)# self.proj_k.weight torch.nn.Parameter(self.proj_k.weight.float())# self.proj_k.bias torch.nn.Parameter(self.proj_k.bias.float())# self.proj_v.weight torch.nn.Parameter(self.proj_v.weight.float())# self.proj_v.bias torch.nn.Parameter(self.proj_v.bias.float())# 检查权重的数据类型q q.reshape(B * self.n_heads, self.n_head_channels, H * W)k self.proj_k(x_sampled).reshape(B * self.n_heads, self.n_head_channels, n_sample)v self.proj_v(x_sampled).reshape(B * self.n_heads, self.n_head_channels, n_sample)attn torch.einsum(b c m, b c n - b m n, q, k) # B * h, HW, Nsattn attn.mul(self.scale)if self.use_pe and (not self.no_off):if self.dwc_pe:residual_lepe self.rpe_table(q.reshape(B, C, H, W)).reshape(B * self.n_heads, self.n_head_channels,H * W)elif self.fixed_pe:rpe_table self.rpe_tableattn_bias rpe_table[None, ...].expand(B, -1, -1, -1)attn attn attn_bias.reshape(B * self.n_heads, H * W, n_sample)elif self.log_cpb:q_grid self._get_q_grid(H, W, B, dtype, device)displacement (q_grid.reshape(B * self.n_groups, H * W, 2).unsqueeze(2) - pos.reshape(B * self.n_groups,n_sample,2).unsqueeze(1)).mul(4.0) # d_y, d_x [-8, 8]displacement torch.sign(displacement) * torch.log2(torch.abs(displacement) 1.0) / np.log2(8.0)attn_bias self.rpe_table(displacement) # B * g, H * W, n_sample, h_gattn attn einops.rearrange(attn_bias, b m n h - (b h) m n, hself.n_group_heads)else:rpe_table self.rpe_tablerpe_bias rpe_table[None, ...].expand(B, -1, -1, -1)q_grid self._get_q_grid(H, W, B, dtype, device)displacement (q_grid.reshape(B * self.n_groups, H * W, 2).unsqueeze(2) - pos.reshape(B * self.n_groups,n_sample,2).unsqueeze(1)).mul(0.5)attn_bias F.grid_sample(inputeinops.rearrange(rpe_bias, b (g c) h w - (b g) c h w, cself.n_group_heads,gself.n_groups),griddisplacement[..., (1, 0)],modebilinear, align_cornersTrue) # B * g, h_g, HW, Nsattn_bias attn_bias.reshape(B * self.n_heads, H * W, n_sample)attn attn attn_biasattn F.softmax(attn, dim2)attn self.attn_drop(attn)out torch.einsum(b m n, b c n - b c m, attn, v)if self.use_pe and self.dwc_pe:out out residual_lepeout out.reshape(B, C, H, W)y self.proj_drop(self.proj_out(out))h, w pos.reshape(B, self.n_groups, Hk, Wk, 2), reference.reshape(B, self.n_groups, Hk, Wk, 2)return y四、添加DAT到你的网络中
添加教程这里不再重复介绍、因为专栏内容有许多添加过程又需要截特别图片会导致文章大家读者也不通顺如果你已经会添加注意力机制了可以跳过本章节如果你还不会大家可以看我下面的文章里面详细的介绍了拿到一个任意机制(C2f、Conv、Bottleneck、Loss、DetectHead)如何添加到你的网络结构中去。 添加教程-YOLOv8改进 | 如何在网络结构中添加注意力机制、C2f、卷积、Neck、检测头 五、DAT可添加的位置
5.1推荐DAT可添加的位置
DAT可以是一种即插即用的注意力机制其可以添加的位置有很多添加的位置不同效果也不同所以我下面推荐几个添加的位置大家可以进行参考当然不一定要按照我推荐的地方添加。 残差连接中在残差网络的残差连接中加入注意力机制(这个位置我推荐的原因是因为DCN放在残差里面效果挺好的大家可以尝试) 特征金字塔SPPF在特征金字塔网络之前可以帮助模型更好地融合不同尺度的特征。 Neck部分YOLOv8的Neck部分负责特征融合这里添加注意力机制可以帮助模型更有效地融合不同层次的特征。 输出层前在最终的输出层前加入注意力机制可以使模型在做出最终预测之前更加集中注意力于最关键的特征。 大家可能看我描述不太懂大家可以看下面的网络结构图中我进行了标注。
5.2图示DAT可添加的位置 六、本文总结
到此本文的正式分享内容就结束了在这里给大家推荐我的YOLOv8改进有效涨点专栏本专栏目前为新开的平均质量分98分后期我会根据各种最新的前沿顶会进行论文复现也会对一些老的改进机制进行补充目前本专栏免费阅读(暂时大家尽早关注不迷路~)如果大家觉得本文帮助到你了订阅本专栏关注后续更多的更新~
本专栏其它内容(持续更新)
YOLOv8改进 | 如何在网络结构中添加注意力机制、C2f、卷积、Neck、检测头
YOLOv8改进 | ODConv附修改后的C2f、Bottleneck模块代码
YOLOv8改进有效涨点系列-手把手教你添加动态蛇形卷积(Dynamic Snake Convolution)
YOLOv8性能评估指标-mAP、Precision、Recall、FPS、IoU
YOLOv8改进有效涨点系列-适合多种检测场景的BiFormer注意力机制(Bi-level Routing Attention) YOLOv8改进有效涨点系列-多位置替换可变形卷积(DCNv1、DCNv2、DCNv3)
详解YOLOv8网络结构/环境搭建/数据集获取/训练/推理/验证/导出/部署