YOLO目标检测创新改进与实战案例专栏
专栏目录: YOLO有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例
专栏链接: YOLO基础解析+创新改进+实战案例
摘要
近期在遥感目标检测的研究中,主要集中于提高定向边界框的表示能力,但却忽略了遥感场景中独有的先验知识。这类先验知识是有用的,因为在没有参考足够长范围上下文的情况下,微小的遥感目标可能会被错误地检测到,而不同类型的对象所需的长范围上下文可能会有所不同。在本文中,我们考虑到了这些先验,并提出了大型选择性核网络(LSKNet)。LSKNet能够动态调整其大的空间接收场,以更好地模拟遥感场景中各种对象的范围上下文。据我们所知,这是首次在遥感目标检测领域探索大型和选择性核机制。无需任何额外复杂设计,我们的轻量级LSKNet在标准的遥感分类、目标检测和语义分割基准测试中设立了新的最先进水平。
创新点
- LSKblock Attention:LSKNet引入了LSKblock Attention作为一种注意力机制,通过空间选择性机制动态调整感受野,以更有效地处理不同目标类型的广泛上下文。这种机制允许模型根据输入自适应地确定大型核的权重,从而在空间维度上调整每个目标的感受野。
- 大型选择性核网络:LSKNet是首个在遥感目标检测领域探索大型和选择性核机制的模型。它通过加权处理大型深度核的特征,并在空间上将它们合并,以适应不同目标类型的不同上下文细微差异。
- 适应性感受野调整:LSKNet能够动态调整感受野以更好地模拟远程感知场景中各种对象的范围上下文,从而更有效地处理不同目标类型的广泛上下文。
- 性能优越:LSKNet在标准基准数据集上取得了新的最先进成绩,如HRSC2016、DOTA-v1.0和FAIR1M-v1.0,证明了其在遥感目标检测任务中的卓越性能和有效性。
创新点
极化滤波(Polarized filteringPolarized):在通道和空间维度保持比较高的分辨率(在通道上保持C/2的维度,在空间上保持[H,W]的维度 ),进一步减少低分辨率、低通道数和上采样造成的信息损失。
增强(Enhancement):采用细粒度回归输出分布的非线性函数。
yolov8 引入
@ROTATED_BACKBONES.register_module()
class LSKNet(BaseModule):
def __init__(self, img_size=224, in_chans=3, embed_dims=[64, 128, 256, 512],
mlp_ratios=[8, 8, 4, 4], drop_rate=0., drop_path_rate=0., norm_layer=partial(nn.LayerNorm, eps=1e-6),
depths=[3, 4, 6, 3], num_stages=4,
pretrained=None,
init_cfg=None,
norm_cfg=None):
super().__init__(init_cfg=init_cfg)
assert not (init_cfg and pretrained), \
'init_cfg and pretrained cannot be set at the same time'
if isinstance(pretrained, str):
warnings.warn('DeprecationWarning: pretrained is deprecated, '
'please use "init_cfg" instead')
self.init_cfg = dict(type='Pretrained', checkpoint=pretrained)
elif pretrained is not None:
raise TypeError('pretrained must be a str or None')
self.depths = depths
self.num_stages = num_stages
dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))] # stochastic depth decay rule
cur = 0
for i in range(num_stages):
patch_embed = OverlapPatchEmbed(img_size=img_size if i == 0 else img_size // (2 ** (i + 1)),
patch_size=7 if i == 0 else 3,
stride=4 if i == 0 else 2,
in_chans=in_chans if i == 0 else embed_dims[i - 1],
embed_dim=embed_dims[i], norm_cfg=norm_cfg)
block = nn.ModuleList([Block(
dim=embed_dims[i], mlp_ratio=mlp_ratios[i], drop=drop_rate, drop_path=dpr[cur + j],norm_cfg=norm_cfg)
for j in range(depths[i])])
norm = norm_layer(embed_dims[i])
cur += depths[i]
setattr(self, f"patch_embed{i + 1}", patch_embed)
setattr(self, f"block{i + 1}", block)
setattr(self, f"norm{i + 1}", norm)
def init_weights(self):
print('init cfg', self.init_cfg)
if self.init_cfg is None:
for m in self.modules():
if isinstance(m, nn.Linear):
trunc_normal_init(m, std=.02, bias=0.)
elif isinstance(m, nn.LayerNorm):
constant_init(m, val=1.0, bias=0.)
elif isinstance(m, nn.Conv2d):
fan_out = m.kernel_size[0] * m.kernel_size[
1] * m.out_channels
fan_out //= m.groups
normal_init(
m, mean=0, std=math.sqrt(2.0 / fan_out), bias=0)
else:
super(LSKNet, self).init_weights()
def freeze_patch_emb(self):
self.patch_embed1.requires_grad = False
@torch.jit.ignore
def no_weight_decay(self):
return {
'pos_embed1', 'pos_embed2', 'pos_embed3', 'pos_embed4', 'cls_token'} # has pos_embed may be better
def get_classifier(self):
return self.head
def reset_classifier(self, num_classes, global_pool=''):
self.num_classes = num_classes
self.head = nn.Linear(self.embed_dim, num_classes) if num_classes > 0 else nn.Identity()
def forward_features(self, x):
B = x.shape[0]
outs = []
for i in range(self.num_stages):
patch_embed = getattr(self, f"patch_embed{i + 1}")
block = getattr(self, f"block{i + 1}")
norm = getattr(self, f"norm{i + 1}")
x, H, W = patch_embed(x)
for blk in block:
x = blk(x)
x = x.flatten(2).transpose(1, 2)
x = norm(x)
x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()
outs.append(x)
return outs
def forward(self, x):
x = self.forward_features(x)
# x = self.head(x)
return x
task与yaml配置
详见:https://blog.csdn.net/shangyanaf/article/details/137614259