YOLOv11改进 | 主干/Backbone篇 | 添加最新的LSKNet遥感目标检测网络主干 (可根据yolov11版本自行放缩通道数独家创新)

一、本文介绍

本文给大家带来的改进内容是 LSKNet (Large Kernel Selection, LK Selection),其是一种专为遥感目标检测设计的 网络架构 ,其核心思想是动态调整其大的空间感受野,以更好地捕捉遥感场景中不同对象的范围上下文。实验部分我在一个包含三十多个类别的数据集上进行实验,其中包含大目标检测和小目标检测, mAP的平均涨点幅度在0.04-0.1之间(也有极个别的情况没有涨点), 同时官方的版本只提供了一个大版本,我在其基础上提供一个轻量化版本给大家选择,本文会先给大家对比试验的结果,供大家参考。

(本文内容可根据yolov11的N、S、M、L、X进行二次缩放,轻量化更上一层)。


目录

一、本文介绍

二、LSKNet原理

2.1  LSKNet的基本原理

2.2 大型核选择(LK Selection)子块

2.3 前馈网络(FFN)子块

三、LSKNet核心代码

四、手把手教你添加LSKNet

4.1 修改一

4.2 修改二

4.3 修改三

4.4 修改四

4.5 修改五

4.6 修改六

4.7 修改七

4.8 修改八

注意!!! 额外的修改!

打印计算量问题解决方案

注意事项!!!

五、LSKNet的yaml文件

5.1 LSKNet的yaml文件版本1

5.2 训练文件

六、成功运行记录

七、本文总结


二、LSKNet原理

论文地址: 官方论文地址

代码地址: 官方代码地址


2.1  LSKNet的基本原理

LSKNet(Large Selective Kernel Network) 是一种专为遥感目标检测设计的网络架构,其 核心优势在于能够动态调整其大的空间感受野 ,以更好地捕捉遥感场景中不同对象的范围上下文。这是第一次在遥感目标检测领域探索大型和选择性核机制。

LSKNet(大型选择性核网络)的 基本原理 包括以下关键组成部分:

1. 大型核选择(LK Selection)子块: 这个子块能够动态地调整网络的感受野,以便根据需要捕获不同尺度的上下文信息。这使得网络能够根据 遥感图像 中对象的不同尺寸和复杂性调整其处理能力。

2. 前馈网络(FFN)子块: 该子块用于通道混合和特征精炼。它由一个完全连接的层、一个深度卷积、一个GELU激活 函数 以及第二个完全连接的层组成。这些组件一起工作,提高了特征的质量并为分类和检测提供了必要的信息。

这两个子块 共同构成LSKNet块 ,能够提供大范围的上下文信息,同时保持对细节的敏感度,这对于遥感目标检测尤其重要。

下面我将为大家展示四种不同的选择性机制模块的架构比较:

对于LSK模块:

1. 有一个 分解 步骤,似乎是用来处理大尺寸的卷积核(Large K)。
2. 接着是一个 空间选择 *步骤,可能用于选择或优化空间信息的特定部分。

这与其他三种 模型 的架构相比较,显示了 LSK模块在处理空间信息方面可能有其独特的方法 。具体来说,LSK模块似乎强调了在大尺寸卷积核上进行操作,这可能有助于捕获遥感图像中较大范围的上下文信息,这对于检测图像中的对象特别有用。空间选择步骤可能进一步增强了模型对于输入空间特征的选择能力,从而使其能够更加有效地聚焦于图像的重要部分。


2.2 大型核选择(LK Selection)子块

LSKNet的 大型核选择(Large Kernel Selection, LK Selection)子块 是其架构的核心组成部分之一。这个子块的功能是 根据需要动态调整网络的感受野大小 通过这种方式,LSKNet能够根据遥感图像中不同对象的大小和上下文范围,调整处理这些对象所需的空间信息范围。

大型核选择子块与 前馈网络(Feed-forward Network, FFN)子块 一起工作。FFN子块用于通道混合和特征细化,它包括一个序列,这个序列由一个全连接层、一个深度卷积、一个GELU激活函数以及第二个全连接层组成。这种设计允许LSKNet块进行特征深度融合和增强,进一步提升了遥感目标检测的性能

下面我将通过LSK(Large Selective Kernel)模块的概念性插图,展示LSKNet如何 通过大型核选择子块和空间选择机制来处理遥感数据 ,从而使网络能够适应不同对象的长范围上下文需求。

1. Large Kernel Decomposition: 原始输入 X ​经过大核分解,使用两种不同的大型卷积核(Large K)进行处理,以捕获不同尺度的空间信息。

2. Channel Concatenation: 两个不同的卷积输出 U_1 ​和 U_2 ​通过通道拼接组合在一起,这样可以在后续步骤中同时利用不同的空间特征。

3. Mixed Pooling: 拼接后的特征图经过平均池化和最大池化的组合操作,然后与自注意力(SA)机制一起使用,以进一步强化特征图的关键区域。

4. Convolution and Spatial Selection: 通过卷积操作和自注意力(SA)生成新的特征图,然后通过空间选择机制进一步增强对目标区域的关注。

5. Element Product and Sigmoid: 使用Sigmoid函数生成一个掩码 S ​,然后将这个掩码与特征图 F ​进行元素乘积操作,得到最终的输出特征图 Y ​。这一步骤用于加权特征图中更重要的区域,以增强网络对遥感图像中特定对象的检测能力。

整个LSK模块的设计强调了 对遥感图像中不同空间尺度和上下文信息的有效捕获 ,这对于在复杂背景下准确检测小型或密集排布的目标至关重要。通过上述步骤的复合操作,LSK模块能够提升遥感目标检测的性能。


2.3 前馈网络(FFN)子块

LSKNet的 前馈网络(Feed-forward Network, FFN) 子块用于通道混合和特征精炼。该子块包含以下组成部分:

1. 全连接层: 用于特征变换,提供网络额外的学习能力。
2. 深度卷积(depth-wise convolution): 用于在通道间独立地应用空间滤波,减少参数量的同时保持效果。
3. GELU激活函数: 一种高斯误差线性单元,用于引入非线性,提高模型的表达能力。
4. 第二个全连接层: 进一步变换和精炼特征。

这个FFN子块紧随LK Selection子块之后,作用是在 保持特征空间信息 的同时, 增强网络在特征通道上的表示能力 。通过这种设计,FFN子块有效地对输入特征进行了深度加工,提升了最终特征的质量,从而有助于提高整个网络在遥感目标检测任务中的性能。


三、LSKNet核心代码

将此代码复制粘贴到''ultralytics/nn/modules''目录下新建一个py文件我这里起名字为LSKNet.py,然后把代码复制粘贴进去即可,使用教程看章节四。

  1. import torch
  2. import torch.nn as nn
  3. from torch.nn.modules.utils import _pair as to_2tuple
  4. from timm.models.layers import DropPath, to_2tuple
  5. from functools import partial
  6. import warnings
  7. __all__ = [
  8. "LSKNET_Tiny", "LSKNET_Large"
  9. ]
  10. class Mlp(nn.Module):
  11. def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
  12. super().__init__()
  13. out_features = out_features or in_features
  14. hidden_features = hidden_features or in_features
  15. self.fc1 = nn.Conv2d(in_features, hidden_features, 1)
  16. self.dwconv = DWConv(hidden_features)
  17. self.act = act_layer()
  18. self.fc2 = nn.Conv2d(hidden_features, out_features, 1)
  19. self.drop = nn.Dropout(drop)
  20. def forward(self, x):
  21. x = self.fc1(x)
  22. x = self.dwconv(x)
  23. x = self.act(x)
  24. x = self.drop(x)
  25. x = self.fc2(x)
  26. x = self.drop(x)
  27. return x
  28. class LSKblock(nn.Module):
  29. def __init__(self, dim):
  30. super().__init__()
  31. self.conv0 = nn.Conv2d(dim, dim, 5, padding=2, groups=dim)
  32. self.conv_spatial = nn.Conv2d(dim, dim, 7, stride=1, padding=9, groups=dim, dilation=3)
  33. self.conv1 = nn.Conv2d(dim, dim // 2, 1)
  34. self.conv2 = nn.Conv2d(dim, dim // 2, 1)
  35. self.conv_squeeze = nn.Conv2d(2, 2, 7, padding=3)
  36. self.conv = nn.Conv2d(dim // 2, dim, 1)
  37. def forward(self, x):
  38. attn1 = self.conv0(x)
  39. attn2 = self.conv_spatial(attn1)
  40. attn1 = self.conv1(attn1)
  41. attn2 = self.conv2(attn2)
  42. attn = torch.cat([attn1, attn2], dim=1)
  43. avg_attn = torch.mean(attn, dim=1, keepdim=True)
  44. max_attn, _ = torch.max(attn, dim=1, keepdim=True)
  45. agg = torch.cat([avg_attn, max_attn], dim=1)
  46. sig = self.conv_squeeze(agg).sigmoid()
  47. attn = attn1 * sig[:, 0, :, :].unsqueeze(1) + attn2 * sig[:, 1, :, :].unsqueeze(1)
  48. attn = self.conv(attn)
  49. return x * attn
  50. class Attention(nn.Module):
  51. def __init__(self, d_model):
  52. super().__init__()
  53. self.proj_1 = nn.Conv2d(d_model, d_model, 1)
  54. self.activation = nn.GELU()
  55. self.spatial_gating_unit = LSKblock(d_model)
  56. self.proj_2 = nn.Conv2d(d_model, d_model, 1)
  57. def forward(self, x):
  58. shorcut = x.clone()
  59. x = self.proj_1(x)
  60. x = self.activation(x)
  61. x = self.spatial_gating_unit(x)
  62. x = self.proj_2(x)
  63. x = x + shorcut
  64. return x
  65. class Block(nn.Module):
  66. def __init__(self, dim, mlp_ratio=4., drop=0., drop_path=0., act_layer=nn.GELU, norm_cfg=None):
  67. super().__init__()
  68. if norm_cfg:
  69. self.norm1 = nn.BatchNorm2d(norm_cfg, dim)
  70. self.norm2 = nn.BatchNorm2d(norm_cfg, dim)
  71. else:
  72. self.norm1 = nn.BatchNorm2d(dim)
  73. self.norm2 = nn.BatchNorm2d(dim)
  74. self.attn = Attention(dim)
  75. self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
  76. mlp_hidden_dim = int(dim * mlp_ratio)
  77. self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)
  78. layer_scale_init_value = 1e-2
  79. self.layer_scale_1 = nn.Parameter(
  80. layer_scale_init_value * torch.ones((dim)), requires_grad=True)
  81. self.layer_scale_2 = nn.Parameter(
  82. layer_scale_init_value * torch.ones((dim)), requires_grad=True)
  83. def forward(self, x):
  84. x = x + self.drop_path(self.layer_scale_1.unsqueeze(-1).unsqueeze(-1) * self.attn(self.norm1(x)))
  85. x = x + self.drop_path(self.layer_scale_2.unsqueeze(-1).unsqueeze(-1) * self.mlp(self.norm2(x)))
  86. return x
  87. class OverlapPatchEmbed(nn.Module):
  88. """ Image to Patch Embedding
  89. """
  90. def __init__(self, img_size=224, patch_size=7, stride=4, in_chans=3, embed_dim=768, norm_cfg=None):
  91. super().__init__()
  92. patch_size = to_2tuple(patch_size)
  93. self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=stride,
  94. padding=(patch_size[0] // 2, patch_size[1] // 2))
  95. if norm_cfg:
  96. self.norm = nn.BatchNorm2d(norm_cfg, embed_dim)
  97. else:
  98. self.norm = nn.BatchNorm2d(embed_dim)
  99. def forward(self, x):
  100. x = self.proj(x)
  101. _, _, H, W = x.shape
  102. x = self.norm(x)
  103. return x, H, W
  104. class LSKNet(nn.Module):
  105. def __init__(self, factor=0.5, img_size=224, in_chans=3, dim=None, embed_dims=[64, 128, 256, 512],
  106. mlp_ratios=[8, 8, 4, 4], drop_rate=0., drop_path_rate=0., norm_layer=partial(nn.LayerNorm, eps=1e-6),
  107. depths=[3, 4, 6, 3], num_stages=4,
  108. pretrained=None,
  109. init_cfg=None,
  110. norm_cfg=None):
  111. super().__init__()
  112. assert not (init_cfg and pretrained), \
  113. 'init_cfg and pretrained cannot be set at the same time'
  114. if isinstance(pretrained, str):
  115. warnings.warn('DeprecationWarning: pretrained is deprecated, '
  116. 'please use "init_cfg" instead')
  117. self.init_cfg = dict(type='Pretrained', checkpoint=pretrained)
  118. elif pretrained is not None:
  119. raise TypeError('pretrained must be a str or None')
  120. self.depths = depths
  121. self.num_stages = num_stages
  122. embed_dims = [int(dim * factor) for dim in embed_dims]
  123. dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))] # stochastic depth decay rule
  124. cur = 0
  125. for i in range(num_stages):
  126. patch_embed = OverlapPatchEmbed(img_size=img_size if i == 0 else img_size // (2 ** (i + 1)),
  127. patch_size=7 if i == 0 else 3,
  128. stride=4 if i == 0 else 2,
  129. in_chans=in_chans if i == 0 else embed_dims[i - 1],
  130. embed_dim=embed_dims[i], norm_cfg=norm_cfg)
  131. block = nn.ModuleList([Block(
  132. dim=embed_dims[i], mlp_ratio=mlp_ratios[i], drop=drop_rate, drop_path=dpr[cur + j], norm_cfg=norm_cfg)
  133. for j in range(depths[i])])
  134. norm = norm_layer(embed_dims[i])
  135. cur += depths[i]
  136. setattr(self, f"patch_embed{i + 1}", patch_embed)
  137. setattr(self, f"block{i + 1}", block)
  138. setattr(self, f"norm{i + 1}", norm)
  139. self.width_list = [i.size(1) for i in self.forward(torch.randn(1, 3, 640, 640))]
  140. def freeze_patch_emb(self):
  141. self.patch_embed1.requires_grad = False
  142. @torch.jit.ignore
  143. def no_weight_decay(self):
  144. return {'pos_embed1', 'pos_embed2', 'pos_embed3', 'pos_embed4', 'cls_token'} # has pos_embed may be better
  145. def get_classifier(self):
  146. return self.head
  147. def reset_classifier(self, num_classes, global_pool=''):
  148. self.num_classes = num_classes
  149. self.head = nn.Linear(self.embed_dim, num_classes) if num_classes > 0 else nn.Identity()
  150. def forward_features(self, x):
  151. B = x.shape[0]
  152. outs = []
  153. for i in range(self.num_stages):
  154. patch_embed = getattr(self, f"patch_embed{i + 1}")
  155. block = getattr(self, f"block{i + 1}")
  156. norm = getattr(self, f"norm{i + 1}")
  157. x, H, W = patch_embed(x)
  158. for blk in block:
  159. x = blk(x)
  160. x = x.flatten(2).transpose(1, 2)
  161. x = norm(x)
  162. x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()
  163. outs.append(x)
  164. return outs
  165. def forward(self, x):
  166. x = self.forward_features(x)
  167. # x = self.head(x)
  168. return x
  169. class DWConv(nn.Module):
  170. def __init__(self, dim=768):
  171. super(DWConv, self).__init__()
  172. self.dwconv = nn.Conv2d(dim, dim, 3, 1, 1, bias=True, groups=dim)
  173. def forward(self, x):
  174. x = self.dwconv(x)
  175. return x
  176. def _conv_filter(state_dict, patch_size=16):
  177. """ convert patch embedding weight from manual patchify + linear proj to conv"""
  178. out_dict = {}
  179. for k, v in state_dict.items():
  180. if 'patch_embed.proj.weight' in k:
  181. v = v.reshape((v.shape[0], 3, patch_size, patch_size))
  182. out_dict[k] = v
  183. return out_dict
  184. def LSKNET_Tiny(factor):
  185. model = LSKNet(factor=factor, depths = [2, 2, 2, 2])
  186. return model
  187. def LSKNET_Large(factor):
  188. model = LSKNet(factor=factor, depths=[3, 4, 6, 3])
  189. return model
  190. if __name__ == '__main__':
  191. model = LSKNET_Large(factor=0.5)
  192. inputs = torch.randn((1, 3, 640, 640))
  193. for i in model(inputs):
  194. print(i.size())


四、手把手教你添加LSKNet

4.1 修改一

第一步还是建立文件,我们找到如下ultralytics/nn文件夹下建立一个目录名字呢就是'Addmodules'文件夹( !然后在其内部建立一个新的py文件将核心代码复制粘贴进去即可


4.2 修改二

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


4.3 修改三

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


4.4 修改四

添加如下两行代码!!!


4.5 修改五

找到七百多行大概把具体看图片,按照图片来修改就行,添加红框内的部分,注意没有()只是函数名。

  1. elif m in {自行添加对应的模型即可,下面都是一样的}:
  2. m = m(*args)
  3. c2 = m.width_list # 返回通道列表
  4. backbone = True


4.6 修改六

下面的两个红框内都是需要改动的。

  1. if isinstance(c2, list):
  2. m_ = m
  3. m_.backbone = True
  4. else:
  5. m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args) # module
  6. t = str(m)[8:-2].replace('__main__.', '') # module type
  7. m.np = sum(x.numel() for x in m_.parameters()) # number params
  8. m_.i, m_.f, m_.type = i + 4 if backbone else i, f, t # attach index, 'from' index, type


4.7 修改七

如下的也需要修改,全部按照我的来。

代码如下把原先的代码替换了即可。

  1. if verbose:
  2. LOGGER.info(f'{i:>3}{str(f):>20}{n_:>3}{m.np:10.0f} {t:<45}{str(args):<30}') # print
  3. save.extend(x % (i + 4 if backbone else i) for x in ([f] if isinstance(f, int) else f) if x != -1) # append to savelist
  4. layers.append(m_)
  5. if i == 0:
  6. ch = []
  7. if isinstance(c2, list):
  8. ch.extend(c2)
  9. if len(c2) != 5:
  10. ch.insert(0, 0)
  11. else:
  12. ch.append(c2)


4.8 修改八

修改八和前面的都不太一样,需要修改前向传播中的一个部分, 已经离开了parse_model方法了。

可以在图片中开代码行数,没有离开task.py文件都是同一个文件。 同时这个部分有好几个前向传播都很相似,大家不要看错了, 是70多行左右的!!!,同时我后面提供了代码,大家直接复制粘贴即可,有时间我针对这里会出一个视频。

​​

代码如下->

  1. def _predict_once(self, x, profile=False, visualize=False, embed=None):
  2. """
  3. Perform a forward pass through the network.
  4. Args:
  5. x (torch.Tensor): The input tensor to the model.
  6. profile (bool): Print the computation time of each layer if True, defaults to False.
  7. visualize (bool): Save the feature maps of the model if True, defaults to False.
  8. embed (list, optional): A list of feature vectors/embeddings to return.
  9. Returns:
  10. (torch.Tensor): The last output of the model.
  11. """
  12. y, dt, embeddings = [], [], [] # outputs
  13. for m in self.model:
  14. if m.f != -1: # if not from previous layer
  15. x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f] # from earlier layers
  16. if profile:
  17. self._profile_one_layer(m, x, dt)
  18. if hasattr(m, 'backbone'):
  19. x = m(x)
  20. if len(x) != 5: # 0 - 5
  21. x.insert(0, None)
  22. for index, i in enumerate(x):
  23. if index in self.save:
  24. y.append(i)
  25. else:
  26. y.append(None)
  27. x = x[-1] # 最后一个输出传给下一层
  28. else:
  29. x = m(x) # run
  30. y.append(x if m.i in self.save else None) # save output
  31. if visualize:
  32. feature_visualization(x, m.type, m.i, save_dir=visualize)
  33. if embed and m.i in embed:
  34. embeddings.append(nn.functional.adaptive_avg_pool2d(x, (1, 1)).squeeze(-1).squeeze(-1)) # flatten
  35. if m.i == max(embed):
  36. return torch.unbind(torch.cat(embeddings, 1), dim=0)
  37. return x

到这里就完成了修改部分,但是这里面细节很多,大家千万要注意不要替换多余的代码,导致报错,也不要拉下任何一部,都会导致运行失败,而且报错很难排查!!!很难排查!!!


注意!!! 额外的修改!

关注我的其实都知道,我大部分的修改都是一样的,这个网络需要额外的修改一步,就是s一个参数,将下面的s改为640!!!即可完美运行!!


打印计算量问题解决方案

我们找到如下文件'ultralytics/utils/torch_utils.py'按照如下的图片进行修改,否则容易打印不出来计算量。


注意事项!!!

如果大家在验证的时候报错形状不匹配的错误可以固定 验证集 的图片尺寸,方法如下 ->

找到下面这个文件ultralytics/ models /yolo/detect/train.py然后其中有一个类是DetectionTrainer class中的build_dataset函数中的一个参数rect=mode == 'val'改为rect=False


五、LSKNet的yaml文件

复制如下yaml文件进行运行!!!


5.1 LSKNet的yaml文件版本1

此版本训练信息:YOLO11-LSKNet summary: 405 layers, 2,225,071 parameters, 2,225,055 gradients, 5.9 GFLOPs

使用说明:# 下面 [-1, 1, LSKNet, [0.25]] 参数位置的0.25是通道放缩的系数, YOLOv11N是0.25 YOLOv11S是0.5 YOLOv11M是1. YOLOv11l是1 YOLOv11是1.5大家根据自己训练的YOLO版本设定即可.
# 本文支持版本有  LSKNET_Tiny, LSKNET_Large

  1. # Ultralytics YOLO 🚀, AGPL-3.0 license
  2. # YOLO11 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
  3. # Parameters
  4. nc: 80 # number of classes
  5. scales: # model compound scaling constants, i.e. 'model=yolo11n.yaml' will call yolo11.yaml with scale 'n'
  6. # [depth, width, max_channels]
  7. n: [0.50, 0.25, 1024] # summary: 319 layers, 2624080 parameters, 2624064 gradients, 6.6 GFLOPs
  8. s: [0.50, 0.50, 1024] # summary: 319 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPs
  9. m: [0.50, 1.00, 512] # summary: 409 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPs
  10. l: [1.00, 1.00, 512] # summary: 631 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPs
  11. x: [1.00, 1.50, 512] # summary: 631 layers, 56966176 parameters, 56966160 gradients, 196.0 GFLOPs
  12. # 下面 [-1, 1, LSKNet, [0.25]] 参数位置的0.25是通道放缩的系数, YOLOv11N是0.25 YOLOv11S是0.5 YOLOv11M是1. YOLOv11l是1 YOLOv111.5大家根据自己训练的YOLO版本设定即可.
  13. # 本文支持版本有 LSKNET_Tiny, LSKNET_Large
  14. # YOLO11n backbone
  15. backbone:
  16. # [from, repeats, module, args]
  17. - [-1, 1, LSKNET_Tiny, [0.25]] # 0-4 P1/2 这里是四层大家不要被yaml文件限制住了思维.
  18. - [-1, 1, SPPF, [1024, 5]] # 5
  19. - [-1, 2, C2PSA, [1024]] # 6
  20. # YOLO11n head
  21. head:
  22. - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  23. - [[-1, 3], 1, Concat, [1]] # cat backbone P4
  24. - [-1, 2, C3k2, [512, False]] # 9
  25. - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  26. - [[-1, 2], 1, Concat, [1]] # cat backbone P3
  27. - [-1, 2, C3k2, [256, False]] # 12 (P3/8-small)
  28. - [-1, 1, Conv, [256, 3, 2]]
  29. - [[-1, 9], 1, Concat, [1]] # cat head P4
  30. - [-1, 2, C3k2, [512, False]] # 15 (P4/16-medium)
  31. - [-1, 1, Conv, [512, 3, 2]]
  32. - [[-1, 6], 1, Concat, [1]] # cat head P5
  33. - [-1, 2, C3k2, [1024, True]] # 18 (P5/32-large)
  34. - [[12, 15, 18], 1, Detect, [nc]] # Detect(P3, P4, P5)


5.2 训练文件

  1. import warnings
  2. warnings.filterwarnings('ignore')
  3. from ultralytics import YOLO
  4. if __name__ == '__main__':
  5. model = YOLO('ultralytics/cfg/models/v8/yolov8-C2f-FasterBlock.yaml')
  6. # model.load('yolov8n.pt') # loading pretrain weights
  7. model.train(data=r'替换数据集yaml文件地址',
  8. # 如果大家任务是其它的'ultralytics/cfg/default.yaml'找到这里修改task可以改成detect, segment, classify, pose
  9. cache=False,
  10. imgsz=640,
  11. epochs=150,
  12. single_cls=False, # 是否是单类别检测
  13. batch=4,
  14. close_mosaic=10,
  15. workers=0,
  16. device='0',
  17. optimizer='SGD', # using SGD
  18. # resume='', # 如过想续训就设置last.pt的地址
  19. amp=False, # 如果出现训练损失为Nan可以关闭amp
  20. project='runs/train',
  21. name='exp',
  22. )


六、成功运行记录

下面是成功运行的截图,已经完成了有1个epochs的训练,图片太大截不全第2个epochs,这里改完之后打印出了点问题,但是不影响任何功能,后期我找时间修复一下这个问题。

​​


七、本文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv11改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充, 目前本专栏免费阅读(暂时,大家尽早关注不迷路~) 如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

​​