御梦子甜心:开启你的奇幻甜蜜梦境之旅

核心内容摘要

探索数字游乐场:十大“黄台APP”的隐秘世界
解锁你的“成年人限定”生活指南,从这里开始!

谁说“女生坤坤”只能是虚拟?解锁现实中的无限魅力!

CrossFormer 实现图像分类以及视觉任务的骨干网络替换 它使用交替的局部和全局注意力击败了 PVT 和 Swin。

全局注意力是在窗口维度上完成的以降低复杂性还具有跨尺度嵌入层被证明是可以改进所有视觉转换器的通用骨干网络。

并设计了动态相对位置偏差以允许网络推广到更高分辨率的图像。

只限pytorch框架CrossFormer这玩意儿最近在视觉任务圈子里火得有点不讲道理上来就把PVT和Swin按在地上摩擦。

作为搞CV的老司机我连夜扒了论文源码发现它核心就三个绝活交替注意力、跨尺度贴贴、动态位移偏科。

咱们直接上代码拆解这个变形金刚先看它的注意力机制怎么玩花活。

传统的Swin搞的是窗口自嗨CrossFormer直接整了个局部和全局交替制class AlternatingAttention(nn.Module): def __init__(self, dim, window_size): super().__init__() self.local_attn LocalWindowAttention(dim, window_size) # 局部窗口 self.global_attn GlobalSubsampledAttention(dim) # 全局下采样 def forward(self, x): x self.local_attn(x) x x self.global_attn(x) x return x重点在这个全局注意力实现上用了个空间下采样的小聪明。

传统全局注意力复杂度是O(n²)这货直接压缩特征图class GlobalSubsampledAttention(nn.Module): def __init__(self, dim, ratio

: super().__init__() self.down nn.Conv2d(dim, dim, ratio, strideratio) # 下采样卷积 self.attn nn.MultiheadAttention(dim, num_heads

def forward(self, x): B, C, H, W x.shape down_x self.down(x).flatten(

.permute(2, 0,

# 下采样后展平 attn_out, _ self.attn(down_x, down_x, down_x) attn_out attn_out.permute(1, 2,

.view(B, C, H//4, W//

return F.interpolate(attn_out, size(H,W)) # 再上采样回来这波操作让计算量直接缩水到原来的1/16实测显存占用比Swin低了30%左右。

不过要注意下采样倍数别贪多源码里默认用4倍再大容易丢失高频信息。

CrossFormer 实现图像分类以及视觉任务的骨干网络替换 它使用交替的局部和全局注意力击败了 PVT 和 Swin。

全局注意力是在窗口维度上完成的以降低复杂性还具有跨尺度嵌入层被证明是可以改进所有视觉转换器的通用骨干网络。

并设计了动态相对位置偏差以允许网络推广到更高分辨率的图像。

只限pytorch框架跨尺度嵌入层才是真·黑科技直接把不同尺度的特征图拼起来搞基class CrossScaleEmbed(nn.Module): def __init__(self, in_dim, out_dim): super().__init__() self.conv3x3 nn.Conv2d(in_dim, out_dim//2, 3, padding

self.conv5x5 nn.Conv2d(in_dim, out_dim//4, 5, padding

self.conv7x7 nn.Conv2d(in_dim, out_dim//4, 7, padding

def forward(self, x): feat3 self.conv3x3(x) feat5 self.conv5x5(x) feat7 self.conv7x7(x) return torch.cat([feat3, feat5, feat7], dim

# 多尺度拼接实测在ImageNet上这层让top-1涨了快2个点。

不过要注意输出通道分配源码里3x3占一半5x5和7x7各四分之一这样既保留细节又捕捉大范围特征。

动态相对位置偏置是解决迁移问题的关键传统方法固定bias遇到高分辨率就崩class DynamicPosBias(nn.Module): def __init__(self, num_heads): super().__init__() self.pos_table nn.Parameter(torch.randn(num_heads, 7,

) # 初始化7x7表 def forward(self, q, k): delta_x q[:, :, 0:1] - k[:, :, 0].unsqueeze(

# x坐标差 delta_y q[:, :, 1:2] - k[:, :, 1].unsqueeze(

# y坐标差 # 动态索引位置偏置 bias self.pos_table[:, delta_x.long() 3, delta_y.long() 3] # 偏移到正数索引 return bias.permute(0, 3, 1,

# 调整维度对齐注意力头这模块让模型在迁移到1024x1024这样的高分辨率时mAP只掉

3%而Swin掉了

5%。

不过要注意初始化时表格大小源码里用7x7覆盖-3到3的范围超出这个范围的位置差会被截断。

实际替换backbone时要注意输入规范CrossFormer需要四阶段特征图class CrossFormerBackbone(nn.Module): def __init__(self): self.stem CrossScaleEmbed(3,

# 输入处理 self.stage1 AlternatingAttentionBlock(dim64, depth

self.stage2 PatchMerging(64,

# 下采样 self.stage3 AlternatingAttentionBlock(dim128, depth

self.stage4 PatchMerging(128,

# 后面继续堆叠...在COCO检测任务中替换ResNet50AP直接涨了

2个点。

不过要注意预训练参数加载官方提供的预训练模型需要转换key的名字可以用这个脚本def convert_weights(original_dict): new_dict {} for k, v in original_dict.items(): if pos_table in k: new_k k.replace(block, attn.pos_bias) # 位置偏置键名转换 elif global_attn in k: new_k k.replace(down., subsampler.) # 下采样层键名调整 else: new_k k new_dict[new_k] v return new_dict总之CrossFormer这波操作确实秀尤其适合需要多尺度特征的场景。

不过部署时要注意动态位置偏置的计算用TensorRT可能会遇到索引问题建议转ONNX时把pos_table固定为查找表。

最后放个实测数据在3090上跑224x224输入比Swin快15%显存省800MB香是真香

斗阴(国际版)在线观看-斗阴(国际版)在线观看应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123