轻量化YOLOv7系列:结合G-GhostNet | 适配GPU,华为诺亚提出G-Ghost方案升级GhostNet

轻量化YOLOv7系列:结合G-GhostNet | 适配GPU,华为诺亚提出G-Ghost方案升级GhostNet

本文提供了改进 YOLOv7注意力系列包含不同的注意力机制以及多种加入方式,在本文中具有完整的代码和包含多种更有效加入YOLOv8中的yaml结构,读者可以获取到注意力加入的代码和使用经验,总有一种适合你和你的数据集。

🗝️YOLOv7实战宝典--星级指南:从入门到精通,您不可错过的技巧

-- 聚焦于YOLO的 最新版本对颈部网络改进、添加局部注意力、增加检测头部,实测涨点

💡 深入浅出YOLOv7:我的专业笔记与技术总结

-- YOLOv7轻松上手, 适用技术小白,文章代码齐全,仅需 一键train,解决 YOLOv7的技术突破和创新潜能

❤️ YOLOv8创新攻略:突破技术瓶颈,激发AI新潜能"

-- 指导独特且专业的分析, 也支持对YOLOv3、YOLOv4、YOLOv5、YOLOv6等网络的修改

🎈 改进YOLOv7专栏内容《YOLOv7实战宝典》📖 ,改进点包括:    替换多种骨干网络/轻量化网络, 添加40多种注意力包含自注意力/上下文注意力/自顶向下注意力机制/空间通道注意力/,设计不同的网络结构,助力涨点!!!

YOLOv7注意力系列包含不同的注意力机制

需要修改的代码

models/GGhostRegNet.py代码

  1. 新建这个文件,放入网络代码
python 复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F
def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):
    """3x3 convolution with padding"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
                     padding=dilation, groups=groups, bias=False, dilation=dilation)


def conv1x1(in_planes, out_planes, stride=1):
    """1x1 convolution"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)


class GHOSTBottleneck(nn.Module):
    expansion = 1
    __constants__ = ['downsample']

    def __init__(self, inplanes, planes, stride=1, downsample=None, group_width=1,
                 dilation=1, norm_layer=None):
        super(GHOSTBottleneck, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        width = planes * self.expansion
        # Both self.conv2 and self.downsample layers downsample the input when stride != 1
        self.conv1 = conv1x1(inplanes, width)
        self.bn1 = norm_layer(width)
        self.conv2 = conv3x3(width, width, stride, width // min(width, group_width), dilation)
        self.bn2 = norm_layer(width)
        self.conv3 = conv1x1(width, planes)
        self.bn3 = norm_layer(planes)
        self.relu = nn.SiLU(inplace=True)

        self.downsample = downsample
        self.stride = stride


    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)



        out = self.conv3(out)
        out = self.bn3(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out


# class LambdaLayer(nn.Module):
#     def __init__(self, lambd):
#         super(LambdaLayer, self).__init__()
#         self.lambd = lambd
#
#     def forward(self, x):
#         return self.lambd(x)


class Stage(nn.Module):

    def __init__(self, block, inplanes, planes, group_width, blocks, stride=1, dilate=False, cheap_ratio=0.5):
        super(Stage, self).__init__()
        norm_layer = nn.BatchNorm2d
        downsample = None
        self.dilation = 1
        previous_dilation = self.dilation
        self.inplanes = inplanes
        if dilate:
            self.dilation *= stride
            stride = 1
        if stride != 1 or self.inplanes != planes:
            downsample = nn.Sequential(
                conv1x1(inplanes, planes, stride),
                norm_layer(planes),
            )

        self.base = block(inplanes, planes, stride, downsample, group_width,
                          previous_dilation, norm_layer)
        self.end = block(planes, planes, group_width=group_width,
                         dilation=self.dilation,
                         norm_layer=norm_layer)

        group_width = int(group_width * 0.75)
        raw_planes = int(planes * (1 - cheap_ratio) / group_width) * group_width
        cheap_planes = planes - raw_planes
        self.cheap_planes = cheap_planes
        self.raw_planes = raw_planes

        self.merge = nn.Sequential(
            nn.AdaptiveAvgPool2d(1),
            nn.Conv2d(planes + raw_planes * (blocks - 2), cheap_planes,
                      kernel_size=1, stride=1, bias=False),
            nn.BatchNorm2d(cheap_planes),
            nn.SiLU(inplace=True),
            nn.Conv2d(cheap_planes, cheap_planes, kernel_size=1, bias=False),
            nn.BatchNorm2d(cheap_planes),
        )
        self.cheap = nn.Sequential(
            nn.Conv2d(cheap_planes, cheap_planes,
                      kernel_size=1, stride=1, bias=False),
            nn.BatchNorm2d(cheap_planes),
        )
        self.cheap_relu = nn.SiLU(inplace=True)

        layers = []
        # downsample = nn.Sequential(
        #     LambdaLayer(lambda x: x[:, :raw_planes])
        # )

        layers = []
        layers.append(block(raw_planes, raw_planes, 1, downsample, group_width,
                            self.dilation, norm_layer))
        inplanes = raw_planes
        for _ in range(2, blocks - 1):
            layers.append(block(inplanes, raw_planes, group_width=group_width,
                                dilation=self.dilation,
                                norm_layer=norm_layer))

        self.layers = nn.Sequential(*layers)

    def forward(self, input):
        x0 = self.base(input)

        m_list = [x0]
        e = x0[:, :self.raw_planes]
        for l in self.layers:
            e = l(e)
            m_list.append(e)
        m = torch.cat(m_list, 1)
        m = self.merge(m)

        c = x0[:, self.raw_planes:]
        c = self.cheap_relu(self.cheap(c) + m)

        x = torch.cat((e, c), 1)
        x = self.end(x)
        return x


class GGhostRegNet(nn.Module):

    def __init__(self, block, layers, widths, layer_number, num_classes=1000, zero_init_residual=True,
                 group_width=8, replace_stride_with_dilation=None,
                 norm_layer=None):
        super(GGhostRegNet, self).__init__()
        # ---------------------------------
        self.layer_number = layer_number
        # --------------------------------------
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        self._norm_layer = norm_layer

        self.inplanes = widths[0]
        self.dilation = 1
        if replace_stride_with_dilation is None:
            # each element in the tuple indicates if we should replace
            # the 2x2 stride with a dilated convolution instead
            replace_stride_with_dilation = [False, False, False, False]
        if len(replace_stride_with_dilation) != 4:
            raise ValueError("replace_stride_with_dilation should be None "
                             "or a 4-element tuple, got {}".format(replace_stride_with_dilation))
        self.group_width = group_width
        # self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=3, stride=2, padding=1,
        #                        bias=False)
        # self.bn1 = norm_layer(self.inplanes)
        # self.relu = nn.ReLU(inplace=True)
        if self.layer_number in [0]:
            self.layer1 = self._make_layer(block, widths[0], layers[0], stride=1,
                                           dilate=replace_stride_with_dilation[0])


        if self.layer_number in [1]:
            self.inplanes = widths[0]
            if layers[1] > 2:
                self.layer2 = Stage(block, self.inplanes, widths[1], group_width, layers[1], stride=1,
                                    dilate=replace_stride_with_dilation[1], cheap_ratio=0.5)
            else:
                self.layer2 = self._make_layer(block, widths[1], layers[1], stride=1,
                                               dilate=replace_stride_with_dilation[1])
        if self.layer_number in [2]:
            self.inplanes = widths[1]
            self.layer3 = Stage(block, self.inplanes, widths[2], group_width, layers[2], stride=1,
                                dilate=replace_stride_with_dilation[2], cheap_ratio=0.5)

        if self.layer_number in [3]:
            self.inplanes = widths[2]
            if layers[3] > 2:
                self.layer4 = Stage(block, self.inplanes, widths[3], group_width, layers[3], stride=1,
                                    dilate=replace_stride_with_dilation[3], cheap_ratio=0.5)
            else:
                self.layer4 = self._make_layer(block, widths[3], layers[3], stride=1,
                                               dilate=replace_stride_with_dilation[3])
        # self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        # self.dropout = nn.Dropout(0.2)
        # self.fc = nn.Linear(widths[-1] * block.expansion, num_classes)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def _make_layer(self, block, planes, blocks, stride=1, dilate=False):
        norm_layer = self._norm_layer
        downsample = None
        previous_dilation = self.dilation
        if dilate:
            self.dilation *= stride
            stride = 1
        if stride != 1 or self.inplanes != planes:
            downsample = nn.Sequential(
                conv1x1(self.inplanes, planes, stride),
                norm_layer(planes),
            )

        layers = []
        layers.append(block(self.inplanes, planes, stride, downsample, self.group_width,
                            previous_dilation, norm_layer))
        self.inplanes = planes
        for _ in range(1, blocks):
            layers.append(block(self.inplanes, planes, group_width=self.group_width,
                                dilation=self.dilation,
                                norm_layer=norm_layer))

        return nn.Sequential(*layers)

    def _forward_impl(self, x):

        if self.layer_number in [0]:
            x = self.layer1(x)
        if self.layer_number in [1]:
            x = self.layer2(x)
        if self.layer_number in [2]:
            x = self.layer3(x)
        if self.layer_number in [3]:
            x = self.layer4(x)

        return x

    def forward(self, x):
        return self._forward_impl(x)
  1. yolo里引用

创建yaml文件

python 复制代码
# parameters
nc: 80  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple

# anchors
anchors:
  - [12,16, 19,36, 40,28]  # P3/8
  - [36,75, 76,55, 72,146]  # P4/16
  - [142,110, 192,243, 459,401]  # P5/32

# yolov7_MY backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [32, 3, 1]],  # 0
  
   [-1, 1, Conv, [64, 3, 2]],  # 1-P1/2      
   [-1, 1, Conv, [64, 3, 1]],
   
   [-1, 1, Conv, [128, 3, 2]],  # 3-P2/4  
   [-1, 1, Conv, [48, 1, 1]],
#   [-2, 1, Conv, [64, 1, 1]],
#   [-1, 1, Conv, [64, 3, 1]],
#   [-1, 1, Conv, [64, 3, 1]],
#   [-1, 1, Conv, [64, 3, 1]],
#   [-1, 1, Conv, [64, 3, 1]],
#   [[-1, -3, -5, -6], 1, Concat, [1]],
#   [-1, 1, Conv, [256, 1, 1]],  # 11
   [-1, 1, GGhostRegNet, [48, 0]], # 5

   [-1, 1, MP, []],
   [-1, 1, Conv, [48, 1, 1]],
   [-3, 1, Conv, [48, 1, 1]],
   [-1, 1, Conv, [48, 3, 2]],
   [[-1, -3], 1, Concat, [1]],  # 16-P3/8  
   [-1, 1, Conv, [96, 1, 1]],
#   [-2, 1, Conv, [128, 1, 1]],
#   [-1, 1, Conv, [128, 3, 1]],
#   [-1, 1, Conv, [128, 3, 1]],
#   [-1, 1, Conv, [128, 3, 1]],
#   [-1, 1, Conv, [128, 3, 1]],
#   [[-1, -3, -5, -6], 1, Concat, [1]],
#   [-1, 1, Conv, [512, 1, 1]],  # 24
   [-1, 3, GGhostRegNet, [96, 1]], # 12

   [-1, 1, MP, []],
   [-1, 1, Conv, [96, 1, 1]],
   [-3, 1, Conv, [96, 1, 1]],
   [-1, 1, Conv, [96, 3, 2]],
   [[-1, -3], 1, Concat, [1]],  # 29-P4/16  
   [-1, 1, Conv, [240, 1, 1]],
#   [-2, 1, Conv, [256, 1, 1]],
#   [-1, 1, Conv, [256, 3, 1]],
#   [-1, 1, Conv, [256, 3, 1]],
#   [-1, 1, Conv, [256, 3, 1]],
#   [-1, 1, Conv, [256, 3, 1]],
#   [[-1, -3, -5, -6], 1, Concat, [1]],
#   [-1, 1, Conv, [1024, 1, 1]],  # 37
   [-1, 5, GGhostRegNet, [240, 2]], # 19

   [-1, 1, MP, []],
   [-1, 1, Conv, [240, 1, 1]],
   [-3, 1, Conv, [240, 1, 1]],
   [-1, 1, Conv, [240, 3, 2]],
   [[-1, -3], 1, Concat, [1]],  # 42-P5/32  
   [-1, 1, Conv, [528, 1, 1]],
#   [-2, 1, Conv, [256, 1, 1]],
#   [-1, 1, Conv, [256, 3, 1]],
#   [-1, 1, Conv, [256, 3, 1]],
#   [-1, 1, Conv, [256, 3, 1]],
#   [-1, 1, Conv, [256, 3, 1]],
#   [[-1, -3, -5, -6], 1, Concat, [1]],
#   [-1, 1, Conv, [1024, 1, 1]],  # 50
   [-1, 7, GGhostRegNet, [528, 3]], # 26
  ]

# yolov7_MY head
head:
  [[-1, 1, SPPCSPC, [512]], # 27
  
   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [19, 1, Conv, [256, 1, 1]], # route backbone P4
   [[-1, -2], 1, Concat, [1]],
   
   [-1, 1, Conv, [256, 1, 1]],
   [-2, 1, Conv, [256, 1, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
   [-1, 1, Conv, [256, 1, 1]], # 39
   
   [-1, 1, Conv, [128, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [12, 1, Conv, [128, 1, 1]], # route backbone P3
   [[-1, -2], 1, Concat, [1]],
   
   [-1, 1, Conv, [128, 1, 1]],
   [-2, 1, Conv, [128, 1, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
   [-1, 1, Conv, [128, 1, 1]], # 51
      
   [-1, 1, MP, []],
   [-1, 1, Conv, [128, 1, 1]],
   [-3, 1, Conv, [128, 1, 1]],
   [-1, 1, Conv, [128, 3, 2]],
   [[-1, -3, 39], 1, Concat, [1]],
   
   [-1, 1, Conv, [256, 1, 1]],
   [-2, 1, Conv, [256, 1, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
   [-1, 1, Conv, [256, 1, 1]], # 64
      
   [-1, 1, MP, []],
   [-1, 1, Conv, [256, 1, 1]],
   [-3, 1, Conv, [256, 1, 1]],
   [-1, 1, Conv, [256, 3, 2]],
   [[-1, -3, 27], 1, Concat, [1]],
   
   [-1, 1, Conv, [512, 1, 1]],
   [-2, 1, Conv, [512, 1, 1]],
   [-1, 1, Conv, [256, 3, 1]],
   [-1, 1, Conv, [256, 3, 1]],
   [-1, 1, Conv, [256, 3, 1]],
   [-1, 1, Conv, [256, 3, 1]],
   [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
   [-1, 1, Conv, [512, 1, 1]], # 77
   
   [51, 1, RepConv, [256, 3, 1]],
   [64, 1, RepConv, [512, 3, 1]],
   [77, 1, RepConv, [1024, 3, 1]],

   [[78,79,80], 1, IDetect, [nc, anchors]],   # Detect(P3, P4, P5)
  ]

测试是否创建成功

这里是引用

相关推荐
遇到困难睡大觉哈哈10 小时前
HarmonyOS 应用数据持久化概述:Preferences、KV-Store、RelationalStore 到底怎么选?
笔记·华为·harmonyos
Coding茶水间10 小时前
基于深度学习的脑肿瘤检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
人工智能·深度学习·yolo·目标检测·机器学习·计算机视觉
嗝o゚11 小时前
鸿蒙智慧屏与Flutter适配:无硬件功能的兼容处理
flutter·华为·开源·harmonyos
luxy200411 小时前
HarmonyOS简易时钟应用
华为·harmonyos
码上掘金11 小时前
基于YOLO和大语言模型的PCB智能缺陷检测系统
人工智能·yolo·语言模型
嗝o゚12 小时前
Flutter 无障碍功能开发最佳实践
python·flutter·华为
嗝o゚14 小时前
开源鸿蒙 Flutter 应用包瘦身实战
flutter·华为·开源·harmonyos
云和数据.ChenGuang15 小时前
鸿蒙负一屏的技术定位与核心价值
华为·wpf·harmonyos
遇到困难睡大觉哈哈17 小时前
HarmonyOS 关系型数据库 RDB 数据持久化(ArkTS)实战:建库建表、CRUD、事务、FTS、性能优化,一篇搞懂
笔记·华为·harmonyos
微尘hjx17 小时前
【目标检测软件 01】YOLO识别软件功能与操作指南
人工智能·测试工具·yolo·目标检测·计算机视觉·ai·pyqt