yolov11n主干网络换为MobileNetv3
- nn.modules.block.py 添加以下代码
# ###### Mobilenetv3
class h_sigmoid(nn.Module):def __init__(self, inplace=True):super(h_sigmoid, self).__init__()self.relu = nn.ReLU6(inplace=inplace)def forward(self, x):return self.relu(x+3) / 6class h_swish(nn.Module):def __init__(self, inplace=True):super(h_swish, self).__init__()self.sigmoid = h_sigmoid(inplace=True)def forward(self, x):return x * self.sigmoid(x)class SELayer(nn.Module):def __init__(self, channel, reduction=4):super(SELayer, self).__init__()#Squeeze操作self.avg_pool = nn.AdaptiveAvgPool2d(1)# Excitation操作(FC+ReLU+FC+Sigmoid)self.fc = nn.Sequential(nn.Linear(channel, channel // reduction),nn.ReLU(inplace=True),nn.Linear(channel // reduction, channel),h_sigmoid())def forward(self,x):b, c, _, _ = x.size()y = self.avg_pool(x)y = y.view(b, c)y = self.fc(y).view(b, c, 1, 1)return x * yclass conv_bn_hswish(nn.Module):"""This equals todef conv_3x3_bn(inp, oup, stride):return nn.Sequential(nn.Conv2d(inp, oup, 3, stride, 1, bias=False),nn.BatchNorm2d(oup),h_swish())"""def __init__(self, c1, c2, stride):super(conv_bn_hswish, self).__init__()self.conv = nn.Conv2d(c1, c2, 3, stride, 1, bias=False)self.bn = nn.BatchNorm2d(c2)self.act = h_swish()def forward(self, x):return self.act(self.bn(self.conv(x)))def fuseforward(self, x):return self.act(self.conv(x))class MobileNetV3(nn.Module):def __init__(self, inp, oup, hidden_dim, kernel_size, stride, use_se, use_hs):super(MobileNetV3, self).__init__()assert stride in [1, 2], "stride must be 1 or 2"# 残差连接条件:只有步长为1且输入输出通道相同时才使用self.identity = stride == 1 and inp == oup# 定义卷积序列(无条件,确保self.conv始终存在)self.conv = nn.Sequential(# 1x1卷积:调整通道数到hidden_dim(无论inp和hidden_dim是否相等)nn.Conv2d(inp, hidden_dim, kernel_size=1, stride=1, padding=0, bias=False),nn.BatchNorm2d(hidden_dim),# 激活函数:根据use_hs选择h_swish或ReLUh_swish() if use_hs else nn.ReLU(inplace=True),# 深度可分离卷积(DW卷积)nn.Conv2d(hidden_dim, hidden_dim,kernel_size=kernel_size,stride=stride,padding=(kernel_size - 1) // 2, # 保证输出尺寸合理groups=hidden_dim, # 分组数=输入通道数,即深度卷积bias=False),nn.BatchNorm2d(hidden_dim),# SE模块(如果需要)SELayer(hidden_dim) if use_se else nn.Identity(), # 用Identity替代空Sequential更规范# 激活函数h_swish() if use_hs else nn.ReLU(inplace=True),# 1x1卷积:将通道数从hidden_dim调整到输出oupnn.Conv2d(hidden_dim, oup, kernel_size=1, stride=1, padding=0, bias=False),nn.BatchNorm2d(oup),)def forward(self, x):y = self.conv(x) # 此时self.conv一定存在,不会报错if self.identity:return x + y # 残差连接else:return y
2.在nn.modules.init.py 导入模块
from .block import 和__all__两个部分都添加
如:“h_sigmoid”,
“h_swish”,
“SELayer”,
“conv_bn_hswish”,
“MobileNetV3”,

3.在nn.tasks.py里面
from ultralytics.nn.modules import() 里面添加那五个类

然后搜索parse_model 在base_modules里面添加那五个


4. 然后新建yolo11-MobileNetV3.yaml
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license# Ultralytics YOLO11 object detection model with P3/8 - P5/32 outputs
# Model docs: https://docs.ultralytics.com/models/yolo11
# Task docs: https://docs.ultralytics.com/tasks/detect# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolo11n.yaml' will call yolo11.yaml with scale 'n'# [depth, width, max_channels]n: [0.50, 0.25, 1024] # summary: 181 layers, 2624080 parameters, 2624064 gradients, 6.6 GFLOPss: [0.50, 0.50, 1024] # summary: 181 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPsm: [0.50, 1.00, 512] # summary: 231 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPsl: [1.00, 1.00, 512] # summary: 357 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPsx: [1.00, 1.50, 512] # summary: 357 layers, 56966176 parameters, 56966160 gradients, 196.0 GFLOPs# YOLO11n backbone
# 替换MobileNetV3-small后的YOLOv11配置
# 格式:[from, repeats, module, args],args=[输出通道, 卷积核, 步长, 膨胀率, SE是否启用, 激活函数]# YOLO11n backbone
backbone:# [from, repeats, module, args]- [-1, 1, conv_bn_hswish, [16, 2]] # 0-P1/2 320*320- [-1, 1, MobileNetV3, [16, 16, 3, 2, 1, 0]] # 1-P2/4 160*160- [-1, 1, MobileNetV3, [24, 72, 3, 2, 0, 0]] # 2-P3/8 80*80- [-1, 1, MobileNetV3, [24, 88, 3, 1, 0, 0]] # 3 80*80- [-1, 1, MobileNetV3, [40, 96, 5, 2, 1, 1]] #4-p4/16 40*40- [-1, 1, MobileNetV3, [40, 240, 5, 1, 1, 1]] # 5 40*40- [-1, 1, MobileNetV3, [40, 240, 5, 1, 1, 1]] #6 40*40- [-1, 1, MobileNetV3, [48, 120, 5, 1, 1, 1]] #7 40*40- [-1, 1, MobileNetV3, [48, 144, 5, 1, 1, 1]] #8 40*40- [-1, 1, MobileNetV3, [96, 288, 5, 2, 1, 1]] #9-p5/32 20*20- [-1, 1, MobileNetV3, [96, 576, 5, 1, 1, 1]] #10 20*20- [-1, 1, MobileNetV3, [96, 576, 5, 1, 1, 1]] #11 20*20# YOLO11n head
head:- [-1, 1, nn.Upsample, [None, 2, "nearest"]]#12 40*40- [[-1, 6], 1, Concat, [1]] #13 cat backbone P4 40*40- [-1, 2, C3k2, [512, False]] #14 40*40- [-1, 1, nn.Upsample, [None, 2, "nearest"]]#15 80*80- [[-1, 3], 1, Concat, [1]] #16 cat backbone P3 80*80- [-1, 2, C3k2, [256, False]] #17 (P3/8-small) 80*80- [-1, 1, Conv, [256, 3, 2]]#18- [[-1, 13], 1, Concat, [1]] #19 cat head P4 40*40- [-1, 2, C3k2, [512, False]] # 20 (P4/16-medium) 40*40- [-1, 1, Conv, [512, 3, 2]] #21- [[-1, 10], 1, Concat, [1]] #22 cat head P5 20*20- [-1, 2, C3k2, [1024, True]] #23 (P5/32-large) 20*20- [[17, 20, 23], 1, Detect, [nc]] # Detect(P3, P4, P5)
5.测试model_test.py
from tests import CFG, SOURCE, TMP
from ultralytics import YOLO
from ultralytics.utils import (ROOT,is_dir_writeable,
)IS_TMP_WRITEABLE = is_dir_writeable(TMP) # WARNING: must be run once tests start as TMP does not exist on tests/init
CFG = r'E:\deeplearning\ultralytics-8.3.163\ultralytics\cfg\models\11\yolo11-MobileNetv3.yaml'
SOURCE = ROOT / r'E:\deeplearning\ultralytics-8.3.163\ultralytics\assets'def test_model_forward():"""Test the forward pass of the YOLO model."""model = YOLO(CFG)model(SOURCE)
运行结果:

6. 训练模型


