Mamba-yolo|结合Mamba注意力机制的视觉检测

一、本文介绍

 PDF地址:https://arxiv.org/pdf/2405.16605v1

代码地址:GitHub - LeapLabTHU/MLLA: Official repository of MLLA

Demystify Mamba in Vision: A Linear AttentionPerspective一文中引入Baseline Mamba,指明Mamba在处理各种高分辨率图像的视觉任务有着很好的效率。发现了强大的Mamba和线性注意力Transformer( linear attention Transformer)非常相似,然后就分析了两者之间的异同。将Mamba模型重述为linear attention Transformer的变体,并且主要有六大差异,分别是:input gate, forget gate,shortcut, no attention normalization, single-head, and modified block design。作者对每个设计都细致的分析了优缺点,评估了性能,最终发现forget gate和block design是Mamba这么给力的主要贡献点。基于以上发现,作者提出了一个类似mamba的线性注意力模型,Mamba-Like Linear Attention (MLLA) ,相当于取其精华,去其糟粕,把mamba两个最为关键的优点设计结合到线性注意力模型当中,具有可并行计算和快速推理的特点。本文将结合YOlOV8检测模型通过添加MLLA模块提升检测精度。

二、宏观架构设计

线性注意 Transformer 模型通常采用图 (a) 中的设计,它由线性注意力模块和 MLP 模块组成。相比之下,Mamba 通过结合 H3和 Gated Attention这两个设计来改进,得到如图 (b) 所示的架构。改进的 Mamba Block 集成了多种操作,例如选择性 SSM、深度卷积、线性映射、激活函数、门控机制等,并且往往比传统的 Transformer 设计更有效。

MLLA (Mamba-Like Linear Attention)的则是通过将Mamba模型的一些核心设计融入线性注意力机制,从而提升模型的性能。具体来说,MLLA主要整合了Mamba中的"忘记门”(forget gate9)和模块设计(block design)这两个关键因素,这些因素被认为是Mamba成功的主要原因。
以下是对MLLA原理的详细分析:
1.忘记门(Forget Gate)
1.忘记门提供了局部偏差和位置信息。所有的忘记门元素严格限制在0到1之间,这意味着模型在接收到当前输入后会持续衰减失前的隐藏状态。这种特性确保了模型对输入序列的顺序敏感。
2.忘记门的局部偏差和位置信息对于图像处理任务来说非常重要,尽管引入忘记门会导致计算需要采用递归的形式,从而降低并行计算的效率。
2.模块设计(Block Design)
1.Mamba的模块设计在保持相似的浮点运算次数(FLOPS)的同时,通过替换注意力子模块为线性注意力来提升性能。结果表明,采用这种模块设计能够显著提高模型的表现。
3.线性注意力的改进:
1.线性注意力被重新设计以整合忘记门和模块设计,这种改进后的模型被称为MLLA。实验结果显示,MLLA在图像分类和高分辨率密集预测任务中均优于各种视觉Mamba模型
4.并行计算和快速推理速度:
1.MLLA通过使用位置编码(ROPE)来替代忘记门,从而在保持并行计算和快速推理速度的同时,提供必要的位置信息。这使得MLLA在处理非自回归的视觉任务时更加有效

结合yolov8改进

核心代码
 

import torch
import torch.nn as nn__all__ = ['MLLAttention']class Mlp(nn.Module):def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):super().__init__()out_features = out_features or in_featureshidden_features = hidden_features or in_featuresself.fc1 = nn.Linear(in_features, hidden_features)self.act = act_layer()self.fc2 = nn.Linear(hidden_features, out_features)self.drop = nn.Dropout(drop)def forward(self, x):x = self.fc1(x)x = self.act(x)x = self.drop(x)x = self.fc2(x)x = self.drop(x)return xclass ConvLayer(nn.Module):def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=0, dilation=1, groups=1,bias=True, dropout=0, norm=nn.BatchNorm2d, act_func=nn.ReLU):super(ConvLayer, self).__init__()self.dropout = nn.Dropout2d(dropout, inplace=False) if dropout > 0 else Noneself.conv = nn.Conv2d(in_channels,out_channels,kernel_size=(kernel_size, kernel_size),stride=(stride, stride),padding=(padding, padding),dilation=(dilation, dilation),groups=groups,bias=bias,)self.norm = norm(num_features=out_channels) if norm else Noneself.act = act_func() if act_func else Nonedef forward(self, x: torch.Tensor) -> torch.Tensor:if self.dropout is not None:x = self.dropout(x)x = self.conv(x)if self.norm:x = self.norm(x)if self.act:x = self.act(x)return xclass RoPE(torch.nn.Module):r"""Rotary Positional Embedding."""def __init__(self, base=10000):super(RoPE, self).__init__()self.base = basedef generate_rotations(self, x):# 获取输入张量的形状*channel_dims, feature_dim = x.shape[1:-1][0], x.shape[-1]k_max = feature_dim // (2 * len(channel_dims))assert feature_dim % k_max == 0, "Feature dimension must be divisible by 2 * k_max"# 生成角度theta_ks = 1 / (self.base ** (torch.arange(k_max, dtype=x.dtype, device=x.device) / k_max))angles = torch.cat([t.unsqueeze(-1) * theta_ks for t intorch.meshgrid([torch.arange(d, dtype=x.dtype, device=x.device) for d in channel_dims],indexing='ij')], dim=-1)# 计算旋转矩阵的实部和虚部rotations_re = torch.cos(angles).unsqueeze(dim=-1)rotations_im = torch.sin(angles).unsqueeze(dim=-1)rotations = torch.cat([rotations_re, rotations_im], dim=-1)return rotationsdef forward(self, x):# 生成旋转矩阵rotations = self.generate_rotations(x)# 将 x 转换为复数形式x_complex = torch.view_as_complex(x.reshape(*x.shape[:-1], -1, 2))# 应用旋转矩阵pe_x = torch.view_as_complex(rotations) * x_complex# 将结果转换回实数形式并展平最后两个维度return torch.view_as_real(pe_x).flatten(-2)class MLLAttention(nn.Module):r""" Linear Attention with LePE and RoPE.Args:dim (int): Number of input channels.num_heads (int): Number of attention heads.qkv_bias (bool, optional):  If True, add a learnable bias to query, key, value. Default: True"""def __init__(self, dim=3, input_resolution=[160, 160], num_heads=4, qkv_bias=True, **kwargs):super().__init__()self.dim = dimself.input_resolution = input_resolutionself.num_heads = num_headsself.qk = nn.Linear(dim, dim * 2, bias=qkv_bias)self.elu = nn.ELU()self.lepe = nn.Conv2d(dim, dim, 3, padding=1, groups=dim)self.rope = RoPE()def forward(self, x):"""Args:x: input features with shape of (B, N, C)"""x = x.reshape((x.size(0), x.size(2) * x.size(3), x.size(1)))b, n, c = x.shapeh = int(n ** 0.5)w = int(n ** 0.5)# self.rope = RoPE(shape=(h, w, self.dim))num_heads = self.num_headshead_dim = c // num_headsqk = self.qk(x).reshape(b, n, 2, c).permute(2, 0, 1, 3)q, k, v = qk[0], qk[1], x# q, k, v: b, n, cq = self.elu(q) + 1.0k = self.elu(k) + 1.0q_rope = self.rope(q.reshape(b, h, w, c)).reshape(b, n, num_heads, head_dim).permute(0, 2, 1, 3)k_rope = self.rope(k.reshape(b, h, w, c)).reshape(b, n, num_heads, head_dim).permute(0, 2, 1, 3)q = q.reshape(b, n, num_heads, head_dim).permute(0, 2, 1, 3)k = k.reshape(b, n, num_heads, head_dim).permute(0, 2, 1, 3)v = v.reshape(b, n, num_heads, head_dim).permute(0, 2, 1, 3)z = 1 / (q @ k.mean(dim=-2, keepdim=True).transpose(-2, -1) + 1e-6)kv = (k_rope.transpose(-2, -1) * (n ** -0.5)) @ (v * (n ** -0.5))x = q_rope @ kv * zx = x.transpose(1, 2).reshape(b, n, c)v = v.transpose(1, 2).reshape(b, h, w, c).permute(0, 3, 1, 2)x = x + self.lepe(v).permute(0, 2, 3, 1).reshape(b, n, c)x = x.transpose(2, 1).reshape((b, c, h, w))return xdef extra_repr(self) -> str:return f'dim={self.dim}, num_heads={self.num_heads}'if __name__ == "__main__":# Generating Sample imageimage_size = (1, 64, 160, 160)image = torch.rand(*image_size)# Modelmodel = MLLAttention(64)out = model(image)print(out.size())

修改一

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

修改二

第二步我们在该目录下创建一个新的py文件名字为'  __init__ .py,然后在其内部导入我们的检测头如
下图所示。

修改三 

第三步我门中到如下文件uitralytics/nn/tasks.py进行导入和注册我们的模块

修改四

按照我的添加在parse model里添加即可。

修改5

修改6 配置yolov8-MLLA.yaml文件

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
 
# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOP
 
# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, Conv, [64, 3, 2]]  # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8
  - [-1, 6, C2f, [256, True]]
  - [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16
  - [-1, 6, C2f, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32
  - [-1, 3, C2f, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]]  # 9
 
# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f, [512]]  # 12
 
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f, [256]]  # 15 (P3/8-small)
 
 
  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f, [512]]  # 18 (P4/16-medium)
 
 
  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f, [1024]]  # 21 (P5/32-large)
  - [-1, 1, MLLAttention, []]  # 22 (P5/32-large) # 添加在大目标检测层后!
 
  - [[15, 18, 22], 1, Detect, [nc]]  # Detect(P3, P4, P5)

7. 训练代码

import warnings
warnings.filterwarnings('ignore')
from ultralytics import YOLOif __name__ == '__main__':model = YOLO('yolov8-MLLA.yaml')# 如何切换模型版本, 上面的ymal文件可以改为 yolov8s.yaml就是使用的v8s,# 类似某个改进的yaml文件名称为yolov8-XXX.yaml那么如果想使用其它版本就把上面的名称改为yolov8l-XXX.yaml即可(改的是上面YOLO中间的名字不是配置文件的)!# model.load('yolov8n.pt') # 是否加载预训练权重,科研不建议大家加载否则很难提升精度model.train(data=r"C:\Users\Administrator\PycharmProjects\yolov5-master\yolov5-master\Construction Site Safety.v30-raw-images_latestversion.yolov8\data.yaml",# 如果大家任务是其它的'ultralytics/cfg/default.yaml'找到这里修改task可以改成detect, segment, classify, posecache=False,imgsz=640,epochs=150,single_cls=False,  # 是否是单类别检测batch=16,close_mosaic=0,workers=0,device='0',optimizer='SGD', # using SGD# resume='runs/train/exp21/weights/last.pt', # 如过想续训就设置last.pt的地址amp=True,  # 如果出现训练损失为Nan可以关闭ampproject='runs/train',name='exp',)

8.开启训练

专栏推荐

专栏将持续收集整理市场上深度学习的相关项目,旨在为准备从事深度学习工作或相关科研活动的伙伴,储备、提升更多的实际开发经验,每个项目实例都可作为实际开发项目写入简历,且都附带完整的代码与数据集。可通过百度云盘进行获取,实现开箱即用

正在跟新中~

深度学习落地实战_机 _ 长的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/49097.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络通讯实验报告

拓扑图 需求 1、通过DHCP服务,给PC4和PC5分配IP地址、网关、掩码、DNS服务器IP地址 2、Client-1要求手工配置IP地址,为192.168.1.1, c 3、telnet客户端可以远程登录telnet服务器进行设备管理,并成功修改telnet服务器的名字为123 &#xff0c…

操作系统——进程与线程(死锁)

1)为什么会产生死锁?产生死锁有什么条件? 2)有什么办法解决死锁? 一、死锁 死锁:多个程序因竞争资源而造成的一种僵局(互相等待对方手里的资源),使得各个进程都被阻塞,…

一篇文章搞懂MySQL的事务与隔离级别

事务 概述 一个事务其实就是一个完整的业务逻辑,是一个最小的工作单元。要么同时成功,要么同时失败,不可再分 假设转账,从A账户向B账户转账10000 A账户的钱减去10000(update语句) B账户的钱加上10000&…

【HarmonyOS学习】用户文件访问

概述 文件所有者为登录到该终端设备的用户,包括用户私有的图片、视频、音频、文档等。 应用对用户文件的创建、访问、删除等行为,需要提前获取用户授权,或由用户操作完成。 用户文件访问框架 是一套提供给开发者访问和管理用户文件的基础框…

无需抠图!AI绘画直接文本生成透明底图层,设计师必看的ComfyUI透明图层生成工作流教程!(附插件模型)

大家好,我是画画的小强 AI 绘画自出现以来一直都在不断发展完善,实现了很多我们在实际应用中迫切需要的功能,比如生成正确的手指、指定的姿势、准确的文本内容等。上周,又一个重磅新功能在开源的 SD 生态内实现了——直接通过文本…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十四章 注册字符设备号

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

Springboot项目打包成镜像、使用docker-compose启动

Springboot项目打包成镜像、使用docker-compose启动 1、创建一个boot项目 1、添加依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSch…

gitee的怎么上传项目

前提 1.先下载Git Bash (如果没有下载的宝子们下载连接如下: 链接: link ) 项目上传到Gitee步骤 1.在Gitee上建立远程仓库 2.填写相关信息 3.进入本地你想要上传的文件目录下&#xff0c;右键单击空白处&#xff0c;点击Git Bash Here 4.配置你的用户名和邮箱 git con…

【leetcode】排列序列

给出集合 [1,2,3,...,n]&#xff0c;其所有元素共有 n! 种排列。 按大小顺序列出所有排列情况&#xff0c;并一一标记&#xff0c;当 n 3 时, 所有排列如下&#xff1a; "123""132""213""231""312""321" 给定…

最简单的typora+gitee+picgo配置图床

typoragiteepicgo图床 你是否因为管理图片而感到头大&#xff1f;是时候了解一下 Typora、Gitee 和 PicGo 这个超级三剑客了&#xff0c;它们可以帮你轻松打造自己的图床&#xff0c;让你的博客图片管理变得简单又有趣。让我们开始这场神奇的图床之旅吧&#xff01; Typora …

7.20 模拟赛总结 [邻项交换] + [决策单调性]

只放题解喽 题解 T1T2T3T4 T1 等价于维护差分数组&#xff0c;数据范围较小&#xff0c;map 套 vector 维护即可 更大的数据范围可以 hash 做 T2 神奇贪心 本题关键在于定序&#xff0c;考虑顺序确定后答案怎么求 设 f i f_i fi​ 表示 第 i i i 件衣服烘干完的时间&…

运放构成电压跟随器,反馈电阻作用;运放电流采集电路,单电源供电,TINA仿真

电压跟随器 使用运放构成电压跟随器可以减小负载对信号源的影响&#xff0c;还可以提高信号带负载的能力&#xff0c;这是因为运放的结构特性&#xff0c;输入电阻大&#xff0c;输出电阻小。 是否决定使用该电压跟随器&#xff0c;就要看信号源&#xff0c;以及负载的阻抗大小…

【视觉SLAM】 十四讲ch5习题

1.*寻找一个相机&#xff08;你手机或笔记本的摄像头即可&#xff09;&#xff0c;标定它的内参。你可能会用到标定板&#xff0c;或者自己打印一张标定用的棋盘格。 参考我之前写过的这篇博客&#xff1a;【OpenCV】 相机标定 calibrateCamera Code来源是《学习OpenCV3》18.…

kaggle竞赛宝典 | 时序表示学习的综述!

本文来源公众号“kaggle竞赛宝典”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;时序表示学习的综述! 1 介绍 本文综述了时间序列数据中的通用表示学习方法&#xff0c;提出了一种新颖的分类方法&#xff0c;并讨论了其对提高…

【区块链+绿色低碳】巴中市生态价值核算创新应用 | FISCO BCOS应用案例

生态产品总值&#xff08;GEP&#xff09;&#xff0c;指一定区域生态系统为人类福祉和经济社会可持续发展提供的产品与服务价值总和&#xff0c;包 括供给产品价值、调节服务价值和文化服务价值。当前&#xff0c;推动生态产品价值有效转化存在“难度量、难抵押、难交易、 难变…

【手撕数据结构】拿捏单链表

目录 单链表介绍链表的初始化打印链表增加节点尾插头插再给定位置之后插入在给定位置之前插入 删除节点尾删头删删除给定位置的节点删除给定位置之后的节点 查找节点 单链表介绍 单链表也叫做无头单向非循环链表&#xff0c;链表也是一种线性结构。他在逻辑结构上一定连续&…

(Qt) 文件读写基础

文章目录 &#x1f5c2;️前言&#x1f4c4;ref&#x1f4c4;访问标记&#x1f5c3;️enum 标记 &#x1f5c2;️Code&#x1f4c4;demo&#x1f4c4;分点讲解&#x1f5c3;️继承体系&#x1f5c3;️打开/关闭&#x1f5c3;️写&#x1f5c3;️读 &#x1f5c2;️END&#x1f…

Java并发的笔记

打算记录自己的学习情况&#xff0c;尽量不摆烂&#xff0c;另外一件事要有始有终&#xff0c;要弄完 如果多个线程处理同一个变量&#xff0c;读跟写都保证不了 2024.7.22》》》》》》》》》》》》 2.1.1volatile的实现原理 volatile不会引起线程上下文的切换和调度 一致性更…

pycharm+pyqt6配置

1、pip install pyqt6 pyqt6-toools 2、pycharm配置 配置&#xff1a;designer Program&#xff1a;&#xff1a;D:\Python39\Lib\site-packages\qt6_applications\Qt\bin\designer.exe Working directory: $ProjectFileDir$ 配置&#xff1a;pyuic6.exe Program&#xff1a…

调度子系统在特定时间执行

时序逻辑调度器设计模式允许您安排Simulink子系统在指定时间执行。以下模型说明了这种设计模式。 时序逻辑调度器图表包含以下逻辑&#xff1a; 时序逻辑调度器的关键行为 时序逻辑调度器图表包含两个状态&#xff0c;它们以不同的速率调度函数调用子系统A1、A2和A3的执行&…