YOLOv5-7.0添加BottleNet transformer

news/2024/7/10 23:34:00 标签: YOLO, transformer, 深度学习

YOLOv5主干特征提取网络为CNN网络,CNN具有平移不变性和局部性,缺乏全局建模长距离建模的能力,引入自然语言领域的Transformer可以形成CNN+TransFormer架构,充分结合两者的优点,提高目标检测效果。

1. BoTNet

论文地址:https://arxiv.org/abs/2101.11605
BoTNet是一种简单但功能强大的主干网络,该架构将注意力模块纳入了包括图像分类,目标检测,实例分割等多种计算机视觉任务。通过仅将ResNet的最后三个的卷积层替换成MHSA层,并不进行其他改变,在墓边检测方面显著改善了极限,同时减少了参数两,从而使得延迟最小化。
在这里插入图片描述Transformer中的MHSA和BoTNet中的MHSA的区别:

  • 归一化,Transformer使用 Layer Normalization,而BoTNet使用 Batch Normalization。
  • 非线性激活,Transformer仅仅使用一个非线性激活在FPN block模块中,BoTNet使用了3个非线性激活。
  • 输出投影,Transformer中的MHSA包含一个输出投影,BoTNet则没有。
  • 优化器,Transformer使用Adam优化器训练,BoTNet使用sgd+ momentum
    在这里插入图片描述

YOLOv5Bottleneck_Transformers_11">2.YOLOv5融合Bottleneck Transformers

2.1 修改common.py,添加CTR3

class MHSA(nn.Module):
    def __init__(self, n_dims, width=14, height=14, heads=4, pos_emb=False):
        super(MHSA, self).__init__()

        self.heads = heads
        self.query = nn.Conv2d(n_dims, n_dims, kernel_size=1)
        self.key = nn.Conv2d(n_dims, n_dims, kernel_size=1)
        self.value = nn.Conv2d(n_dims, n_dims, kernel_size=1)
        self.pos = pos_emb
        if self.pos:
            self.rel_h = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, 1, int(height)]), requires_grad=True)
            self.rel_w = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, int(width), 1]), requires_grad=True)
        self.softmax = nn.Softmax(dim=-1)

    def forward(self, x):
        n_batch, C, width, height = x.size()
        q = self.query(x).view(n_batch, self.heads, C // self.heads, -1)
        k = self.key(x).view(n_batch, self.heads, C // self.heads, -1)
        v = self.value(x).view(n_batch, self.heads, C // self.heads, -1)
        # print('q shape:{},k shape:{},v shape:{}'.format(q.shape,k.shape,v.shape))  #1,4,64,256
        content_content = torch.matmul(q.permute(0, 1, 3, 2), k)  # 1,C,h*w,h*w
        # print("qkT=",content_content.shape)
        c1, c2, c3, c4 = content_content.size()
        if self.pos:
            # print("old content_content shape",content_content.shape) #1,4,256,256
            content_position = (self.rel_h + self.rel_w).view(1, self.heads, C // self.heads, -1).permute(0, 1, 3,
                                                                                                          2)  # 1,4,1024,64

            content_position = torch.matmul(content_position, q)  # ([1, 4, 1024, 256])
            content_position = content_position if (
                        content_content.shape == content_position.shape) else content_position[:, :, :c3, ]
            assert (content_content.shape == content_position.shape)
            # print('new pos222-> shape:',content_position.shape)
            # print('new content222-> shape:',content_content.shape)
            energy = content_content + content_position
        else:
            energy = content_content
        attention = self.softmax(energy)
        out = torch.matmul(v, attention.permute(0, 1, 3, 2))  # 1,4,256,64
        out = out.view(n_batch, C, width, height)
        return out


class BottleneckTransformer(nn.Module):
    # Transformer bottleneck
    # expansion = 1

    def __init__(self, c1, c2, stride=1, heads=4, mhsa=True, resolution=None, expansion=1):
        super(BottleneckTransformer, self).__init__()
        c_ = int(c2 * expansion)
        self.cv1 = Conv(c1, c_, 1, 1)
        # self.bn1 = nn.BatchNorm2d(c2)
        if not mhsa:
            self.cv2 = Conv(c_, c2, 3, 1)
        else:
            self.cv2 = nn.ModuleList()
            self.cv2.append(MHSA(c2, width=int(resolution[0]), height=int(resolution[1]), heads=heads))
            if stride == 2:
                self.cv2.append(nn.AvgPool2d(2, 2))
            self.cv2 = nn.Sequential(*self.cv2)
        # self.bn2 = nn.BatchNorm2d(planes)
        # self.cv3 = nn.Conv2d(planes, expansion * planes, kernel_size=1, bias=False)
        # self.bn3 = nn.BatchNorm2d(expansion * planes)
        # self.shortcut = nn.Sequential()
        self.shortcut = c1 == c2
        if stride != 1 or c1 != expansion * c2:
            self.shortcut = nn.Sequential(
                nn.Conv2d(c1, expansion * c2, kernel_size=1, stride=stride),
                nn.BatchNorm2d(expansion * c2)
            )
        self.fc1 = nn.Linear(c2, c2)

    def forward(self, x):
        # print("transforme  input bottleck shape:",x.shape)
        # out = F.relu(self.bn1(self.conv1(x)))
        # out = F.relu(self.bn2(self.conv2(out)))
        # out = self.bn3(self.conv3(out))
        # out += self.shortcut(x)
        # out = F.relu(out)
        out = x + self.cv2(self.cv1(x)) if self.shortcut else self.cv2(self.cv1(x))
        return out


class CTR3(nn.Module):
    # CSP Bottleneck with 3 convolutions
    def __init__(self, c1, c2, n=1, e=0.5, e2=1, w=20, h=20):  # ch_in, ch_out, number, , expansion,w,h
        super(CTR3, self).__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # act=FReLU(c2)
        self.m = nn.Sequential(
            *[BottleneckTransformer(c_, c_, stride=1, heads=4, mhsa=True, resolution=(w, h), expansion=e2) for _ in
              range(n)])
        # self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)])

    def forward(self, x):
        # print("CTR3-INPUT:",x.shape)
        # return self.cv3
        return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))

2.2修改yolo.py,在parse_model注册CTR3

 if m in {
                Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv, CTR3,
                BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x}:

2.3 修改yaml文件

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license

# Parameters
nc: 8  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# YOLOv5 v7.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, CTR3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]

# YOLOv5 v7.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 23 (P5/32-large)

#   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
   [ [ 17, 20, 23 ], 1, Detect, [ nc, anchors ] ],         # Detect(P3, P4, P5)

  ]


http://www.niftyadmin.cn/n/477960.html

相关文章

想做邮件营销,哪个平台好用?

邮件营销作为传统的营销方式之一,市场上已经出现了很多相关的邮件营销工具。但是,市场的筛选为大家留下了真正好用的邮件营销平台。今天,我们就来介绍一下受到众多好评的,市场上优秀的邮件营销平台——Zoho Campaigns。 一、产品…

【Springboot+Mysql+Excel】文件上传数据库

仓库地址:余温./import-excel-demo 1、下载代码压缩包解压到文件夹 2、使用idea打开 3、安装Maven插件 3、使用maven下载pom.xml中的依赖 4、创建数据库 、数据表: 5、创建Execl文件 6、启动项目 7、输入网址: http://localhost:8081/u…

赛效:WPS文字(Word)中的页面背景如何删除

1:打开一个有背景颜色的文档。 2:在“页面布局”选项卡里点击“背景”,在下拉菜单里点击“删除页面背景”。 3:接下来我们看到,文档背景已经恢复了默认的颜色。 如果你想了解更多办公软件以及办公技巧,可以…

Linux学习之yum安装软件

要是使用rpm安装软件,就需要自己解决依赖包的安装,使用yum进行安装,就可以自动安装依赖包。可以先到阿里云CentOS 镜像网站学习一下如何更改yum源。我这里演示如何更改yum源。 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS…

【pytorch】nn.utils.rnn.pad_sequence的使用

目录 错误使用说明样例代码 错误 The size of tensor a (3) must match the size of tensor b (5) at non-singleton dimension 1 在使用nn.utils.rnn.pad_sequence时,遇到如上错误,原因是使用方式错误. 使用说明 用padding_value填充可变长度张量列表 pad_sequence 沿新维…

20230621 taro+vue3+webpack5+antdv时,在vue文件中特定组件时,devH5环境报错

问题 在某个vue文件下 import { notification } from ant-design-vue;然后在终端开始 yarn dev:h5在浏览器看效果 回出现以下错误 Uncaught (in promise) TypeError: __webpack_require__.hmd is not a functionat ./node_modules/.taro/h5/prebundle/ant-design-vue.js原因…

vue 中node-sass和sass版本问题解决

先开始使用 “node-sass”: “^7.0.1” “sass-loader”: “^10.0.5” 然后使用npm install报错 后面百度,搜到了是因为 node-sass和sass-loader版本不对应造成。 然后修改版本,增加sass引用 “node-sass”: “^7.0.1” “sass-loader”: “^7.3.1”, “…

2023【软件测试】面试题合集整理打包!大放送!!!

跳槽求职。准备好一场面试不仅需要在简历上多下功夫,还需要为面试问答做好充足的准备, 以下是“本人”从面试经验中收集的,然后分门别类整理了这套面试题,很具备参考性,毕竟都是企业真实面试题目。 接下来&#xff0…