YOLOv8改进 | 主干网络 | 用EfficientNet卷积替换backbone【教程+代码 】

news2024/9/19 17:20:01

 秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转


💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡


专栏目录 :《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有80+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进——点击即可跳转


卷积神经网络通常在固定的资源预算下开发,如果资源更充足,则会进行扩展以提高准确性。在EfficientNet的论文中,作者系统地研究了模型扩展,并发现仔细平衡网络的深度、宽度和分辨率可以带来更好的性能。基于这一观察,提出了一种新的扩展方法,该方法使用简单但高效的复合系数统一扩展深度/宽度/分辨率的各个维度。证明了将此方法应用于扩展MobileNets和ResNet的有效性。为了更进一步,我们使用神经架构搜索来设计一个新的基准网络,并对其进行扩展以获得一系列模型,称为EfficientNets,这些模型的准确性和效率都优于先前的ConvNets。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址YOLOv8改进——更新各种有效涨点方法——点击即可跳转 订阅学习不迷路   

目录

1. 原理

2.  将EfficientNet添加到YOLOv8中

2.1 EfficientNet的代码实现

2.2 更改init.py文件

2.3 添加yaml文件

2.4 在task.py中进行注册

2.5 执行程序

3. 完整代码分享

4. GFLOPs

5. 进阶

6. 总结


1. 原理

论文地址:EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks——点击即可跳转 

官方代码:官方代码仓库——点击即可跳转 

EfficientNet是一种针对卷积神经网络(CNN)模型的高效缩放方法,其核心思想在于通过复合缩放策略,平衡地调整网络的深度(depth)、宽度(width)和分辨率(resolution),从而在有限资源下最大化模型的准确性和效率。

1. 复合缩放方法

传统的CNN模型通常通过增加深度、宽度或者输入图像的分辨率来提升性能,但这些方法往往只针对单一维度进行缩放,导致效果不理想。EfficientNet提出了一个新的方法:复合缩放,即同时以固定比例缩放网络的深度、宽度和分辨率。这种方法背后的直觉是:输入图像越大,网络需要更多的层次来扩大感受野,更多的通道来捕捉更细粒度的特征。

具体来说,假设你有2N倍的计算资源,那么你可以按如下方式进行缩放:

  • 深度按比例αN增加

  • 宽度按比例βN增加

  • 分辨率按比例γN增加

这三者的比例(α, β, γ)通过在小模型上的网格搜索确定,并应用到大模型上。

2. 神经架构搜索 (NAS)

EfficientNet不仅仅是提出了复合缩放方法,还使用神经架构搜索(Neural Architecture Search, NAS)设计了一个高效的基础网络结构,这个基础网络经过复合缩放后可以生成一系列高性能的模型(EfficientNet-B0到B7)。这些模型在ImageNet等基准数据集上展示了卓越的性能。例如,EfficientNet-B7达到了84.3%的ImageNet top-1准确率,同时参数量比之前的最佳模型小8.4倍,推理速度快6.1倍。

3. 效果与性能

通过复合缩放方法生成的EfficientNet系列模型显著超过了之前的各种卷积网络,不仅在ImageNet数据集上取得了极高的准确率,还在多个迁移学习任务上表现出色。此外,EfficientNet系列的模型在参数量和计算量方面表现得非常高效,适合在资源受限的环境中使用。

总结

EfficientNet通过提出复合缩放方法,以及结合神经架构搜索,成功设计出了一系列在准确性和效率上都领先的卷积神经网络模型。这种方法的核心在于找到一个合理的平衡点,统一缩放网络的各个维度,从而充分利用计算资源,提升模型性能.

2.  将EfficientNet添加到YOLOv8中

2.1 EfficientNet的代码实现

关键步骤一: 在/ultralytics/ultralytics/nn/modules/下面新建efficeient.py,将下面代码粘贴到文件内

import torch.nn as nn
import torch


# SE-Net Adaptive avg pooling --> fc --> fc --> Sigmoid
class SeBlock(nn.Module):
    def __init__(self, in_channel, reduction=4):
        super().__init__()
        self.Squeeze = nn.AdaptiveAvgPool2d(1)

        self.Excitation = nn.Sequential()
        self.Excitation.add_module('FC1', nn.Conv2d(in_channel, in_channel // reduction, kernel_size=1))  # 1*1卷积与此效果相同
        self.Excitation.add_module('ReLU', nn.ReLU())
        self.Excitation.add_module('FC2', nn.Conv2d(in_channel // reduction, in_channel, kernel_size=1))
        self.Excitation.add_module('Sigmoid', nn.Sigmoid())

    def forward(self, x):
        y = self.Squeeze(x)
        ouput = self.Excitation(y)
        return x*(ouput.expand_as(x))

# EfficientNetLite
class drop_connect:
    def __init__(self, drop_connect_rate):
        self.drop_connect_rate = drop_connect_rate

    def forward(self, x, training):
        if not training:
            return x
        keep_prob = 1.0 - self.drop_connect_rate
        batch_size = x.shape[0]
        random_tensor = keep_prob
        random_tensor += torch.rand([batch_size, 1, 1, 1], dtype=x.dtype, device=x.device)
        binary_mask = torch.floor(random_tensor) # 1
        x = (x / keep_prob) * binary_mask
        return x

class stem(nn.Module):
    def __init__(self, c1, c2, act='ReLU6'):
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, kernel_size=3, stride=2, padding=1, bias=False)
        self.bn = nn.BatchNorm2d(num_features=c2)
        if act == 'ReLU6':
            self.act = nn.ReLU6(inplace=True)
    
    def forward(self, x):
        return self.act(self.bn(self.conv(x)))

class MBConvBlock(nn.Module):
    def __init__(self, inp, final_oup, k, s, expand_ratio, drop_connect_rate, has_se=False):
        super(MBConvBlock, self).__init__()

        self._momentum = 0.01
        self._epsilon = 1e-3
        self.input_filters = inp
        self.output_filters = final_oup
        self.stride = s
        self.expand_ratio = expand_ratio
        self.has_se = has_se
        self.id_skip = True  # skip connection and drop connect
        se_ratio = 0.25

        # Expansion phase
        oup = inp * expand_ratio  # number of output channels
        if expand_ratio != 1:
            self._expand_conv = nn.Conv2d(in_channels=inp, out_channels=oup, kernel_size=1, bias=False)
            self._bn0 = nn.BatchNorm2d(num_features=oup, momentum=self._momentum, eps=self._epsilon)

        # Depthwise convolution phase
        self._depthwise_conv = nn.Conv2d(
            in_channels=oup, out_channels=oup, groups=oup,  # groups makes it depthwise
            kernel_size=k, padding=(k - 1) // 2, stride=s, bias=False)
        self._bn1 = nn.BatchNorm2d(num_features=oup, momentum=self._momentum, eps=self._epsilon)

        # Squeeze and Excitation layer, if desired
        if self.has_se:
            num_squeezed_channels = max(1, int(inp * se_ratio))
            self.se = SeBlock(oup, 4)

        # Output phase
        self._project_conv = nn.Conv2d(in_channels=oup, out_channels=final_oup, kernel_size=1, bias=False)
        self._bn2 = nn.BatchNorm2d(num_features=final_oup, momentum=self._momentum, eps=self._epsilon)
        self._relu = nn.ReLU6(inplace=True)

        self.drop_connect = drop_connect(drop_connect_rate)

    def forward(self, x, drop_connect_rate=None):
        """
        :param x: input tensor
        :param drop_connect_rate: drop connect rate (float, between 0 and 1)
        :return: output of block
        """

        # Expansion and Depthwise Convolution
        identity = x
        if self.expand_ratio != 1:
            x = self._relu(self._bn0(self._expand_conv(x)))
        x = self._relu(self._bn1(self._depthwise_conv(x)))

        # Squeeze and Excitation
        if self.has_se:
            x = self.se(x)

        x = self._bn2(self._project_conv(x))

        # Skip connection and drop connect
        if self.id_skip and self.stride == 1  and self.input_filters == self.output_filters:
            if drop_connect_rate:
                x = self.drop_connect(x, training=self.training)
            x += identity  # skip connection
        return x

EfficientNet处理图像的主要流程可以分为以下几个关键步骤:

1. 输入图像的预处理

首先,输入图像会被标准化处理,这通常包括缩放到特定的分辨率以及归一化。EfficientNet的复合缩放策略决定了不同版本的EfficientNet模型(如B0到B7)会使用不同的输入分辨率。通过对分辨率的缩放,EfficientNet能够在不同大小的输入图像上保持性能与效率的平衡。

2. 卷积操作和特征提取

图像经过预处理后,会被输入到EfficientNet的网络结构中。EfficientNet的网络结构基于MobileNetV2中的Inverted Residual Blocks,但通过神经架构搜索(NAS)进一步优化,使其在性能和效率之间取得更好的平衡。

在这些卷积层中,EfficientNet会依次进行以下操作:

  • 标准卷积:用于提取低级特征。

  • 深度可分离卷积:这是一个轻量级的卷积层,由标准卷积分解而来,分为深度卷积(针对每个通道的空间卷积)和点卷积(对通道进行线性组合)。这种卷积方式既高效又节省计算资源。

  • Inverted Residual Block:它是EfficientNet的基础构建块,这些块使用跳跃连接(skip connections)和扩展因子来捕捉不同层次的特征。

3. 复合缩放策略的应用

在整个网络结构中,EfficientNet通过复合缩放策略来调整网络的宽度(通道数)、深度(层数)和分辨率(输入图像大小)。这种方法确保网络可以在增加计算资源时,合理地扩展各个维度,从而提高模型的表达能力和分类准确性。

4. 特征聚合与全连接层

在卷积层完成特征提取后,EfficientNet会通过全局平均池化层将所有提取到的特征聚合成一个固定大小的向量。然后,这个向量会被传递到全连接层进行分类预测。全连接层的输出维度与分类任务的类别数量一致(例如,ImageNet有1000个类,因此输出层维度为1000)。

5. 输出分类结果

最终,全连接层的输出会经过softmax激活函数,将结果转化为概率分布,每个类的概率代表该图像属于这个类的可能性。模型输出最高概率的类别作为预测结果。

总结

EfficientNet处理图像的流程包括:对输入图像进行预处理,通过优化的卷积层和Inverted Residual Blocks提取多层次特征,应用复合缩放策略调整网络结构,最后通过全局池化和全连接层进行分类。整个过程体现了EfficientNet在保持高效计算的同时,充分利用网络深度、宽度和输入分辨率的优化策略。

2.2 更改init.py文件

关键步骤二:修改modules文件夹下的__init__.py文件,先导入函数

然后在下面的__all__中声明函数

2.3 添加yaml文件

关键步骤三:在/ultralytics/ultralytics/cfg/models/v8下面新建文件yolov8_EfficientNet.yaml文件,粘贴下面的内容

  •  目标检测yaml文件 
# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs

# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, stem, [32, 'ReLU6']]             # 0-P1/2
  - [-1, 1, MBConvBlock, [16, 3, 1, 1, 0]]   # 1
  - [-1, 1, MBConvBlock, [24, 3, 2, 6, 0.028, True]]   # 2-P2/4
  - [-1, 1, MBConvBlock, [24, 3, 1, 6, 0.057]]
  - [-1, 1, MBConvBlock, [40, 5, 2, 6, 0.085]]   # 4-P3/8
  - [-1, 1, MBConvBlock, [40, 5, 1, 6, 0.114]]
  - [-1, 1, MBConvBlock, [80, 3, 2, 6, 0.142]]   # 6-P4/16
  - [-1, 1, MBConvBlock, [80, 3, 1, 6, 0.171]]
  - [-1, 1, MBConvBlock, [80, 3, 1, 6, 0.200]]
  - [-1, 1, MBConvBlock, [112, 5, 1, 6, 0.228]]  # 9
  - [-1, 1, MBConvBlock, [112, 5, 1, 6, 0.257]]
  - [-1, 1, MBConvBlock, [112, 5, 1, 6, 0.285]]
  - [-1, 1, MBConvBlock, [192, 5, 2, 6, 0.314]]  # 12-P5/32
  - [-1, 1, MBConvBlock, [192, 5, 1, 6, 0.342]]
  - [-1, 1, MBConvBlock, [192, 5, 1, 6, 0.371]]
  - [-1, 1, MBConvBlock, [192, 5, 1, 6, 0.400]]
  - [-1, 1, MBConvBlock, [320, 3, 1, 6, 0.428]]  # 16


# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 11], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f, [512]]  # 19

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 5], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f, [256]]  # 22 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 19], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f, [512]]  # 25 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 16], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f, [1024]]  # 28 (P5/32-large)

  - [[22, 25, 28], 1, Detect, [nc]]  # Detect(P3, P4, P5)
  • 语义分割yaml文件
# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs

# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, stem, [32, 'ReLU6']]             # 0-P1/2
  - [-1, 1, MBConvBlock, [16, 3, 1, 1, 0]]   # 1
  - [-1, 1, MBConvBlock, [24, 3, 2, 6, 0.028, True]]   # 2-P2/4
  - [-1, 1, MBConvBlock, [24, 3, 1, 6, 0.057]]
  - [-1, 1, MBConvBlock, [40, 5, 2, 6, 0.085]]   # 4-P3/8
  - [-1, 1, MBConvBlock, [40, 5, 1, 6, 0.114]]
  - [-1, 1, MBConvBlock, [80, 3, 2, 6, 0.142]]   # 6-P4/16
  - [-1, 1, MBConvBlock, [80, 3, 1, 6, 0.171]]
  - [-1, 1, MBConvBlock, [80, 3, 1, 6, 0.200]]
  - [-1, 1, MBConvBlock, [112, 5, 1, 6, 0.228]]  # 9
  - [-1, 1, MBConvBlock, [112, 5, 1, 6, 0.257]]
  - [-1, 1, MBConvBlock, [112, 5, 1, 6, 0.285]]
  - [-1, 1, MBConvBlock, [192, 5, 2, 6, 0.314]]  # 12-P5/32
  - [-1, 1, MBConvBlock, [192, 5, 1, 6, 0.342]]
  - [-1, 1, MBConvBlock, [192, 5, 1, 6, 0.371]]
  - [-1, 1, MBConvBlock, [192, 5, 1, 6, 0.400]]
  - [-1, 1, MBConvBlock, [320, 3, 1, 6, 0.428]]  # 16


# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 11], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f, [512]]  # 19

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 5], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f, [256]]  # 22 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 19], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f, [512]]  # 25 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 16], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f, [1024]]  # 28 (P5/32-large)

  - [[22, 25, 28], 1, Segment, [nc, 32, 256]] # Segment(P3, P4, P5)

温馨提示:因为本文只是对yolov8基础上添加模块,如果要对yolov8n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。不明白的同学可以看这篇文章: yolov8yaml文件解读——点击即可跳转  


# YOLOv8n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
max_channels: 1024 # max_channels
 
# YOLOv8s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
max_channels: 1024 # max_channels
 
# YOLOv8l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
max_channels: 512 # max_channels
 
# YOLOv8m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple
max_channels: 768 # max_channels
 
# YOLOv8x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple
max_channels: 512 # max_channels

2.4 在task.py中进行注册

关键步骤四:在task.py的parse_model函数中进行注册,

elif m in [stem, MBConvBlock]:
            c1, c2 = ch[f], args[0]
            if c2 != nc:
                c2 = make_divisible(min(c2, max_channels) * width, 8)
            args = [c1, c2, *args[1:]]

2.5 执行程序

在train.py中,将model的参数路径设置为yolov8_EfficientNet.yaml的路径

建议大家写绝对路径,确保一定能找到

from ultralytics import YOLO
 
# Load a model
# model = YOLO('yolov8n.yaml')  # build a new model from YAML
# model = YOLO('yolov8n.pt')  # load a pretrained model (recommended for training)
 
model = YOLO(r'/projects/ultralytics/ultralytics/cfg/models/v8/yolov8_EfficientNet.yaml')  # build from YAML and transfer weights
 
# Train the model
model.train(batch=16)

 🚀运行程序,如果出现下面的内容则说明添加成功🚀 

                    from n    params  module                                    arguments                     
  0                  -1  1       232  ultralytics.nn.modules.EfficientNet.stem     [3, 8, 'ReLU6']               
  1                  -1  1       168  ultralytics.nn.modules.EfficientNet.MBConvBlock[8, 8, 3, 1, 1, 0]            
  2                  -1  1      2620  ultralytics.nn.modules.EfficientNet.MBConvBlock[8, 8, 3, 2, 6, 0.028, True]  
  3                  -1  1      1408  ultralytics.nn.modules.EfficientNet.MBConvBlock[8, 8, 3, 1, 6, 0.057]        
  4                  -1  1      2576  ultralytics.nn.modules.EfficientNet.MBConvBlock[8, 16, 5, 2, 6, 0.085]       
  5                  -1  1      5888  ultralytics.nn.modules.EfficientNet.MBConvBlock[16, 16, 5, 1, 6, 0.114]      
  6                  -1  1     10624  ultralytics.nn.modules.EfficientNet.MBConvBlock[16, 80, 3, 2, 6, 0.142]      
  7                  -1  1     83200  ultralytics.nn.modules.EfficientNet.MBConvBlock[80, 80, 3, 1, 6, 0.171]      
  8                  -1  1     83200  ultralytics.nn.modules.EfficientNet.MBConvBlock[80, 80, 3, 1, 6, 0.2]        
  9                  -1  1     67744  ultralytics.nn.modules.EfficientNet.MBConvBlock[80, 32, 5, 1, 6, 0.228]      
 10                  -1  1     17920  ultralytics.nn.modules.EfficientNet.MBConvBlock[32, 32, 5, 1, 6, 0.257]      
 11                  -1  1     17920  ultralytics.nn.modules.EfficientNet.MBConvBlock[32, 32, 5, 1, 6, 0.285]      
 12                  -1  1     21024  ultralytics.nn.modules.EfficientNet.MBConvBlock[32, 48, 5, 2, 6, 0.314]      
 13                  -1  1     36096  ultralytics.nn.modules.EfficientNet.MBConvBlock[48, 48, 5, 1, 6, 0.342]      
 14                  -1  1     36096  ultralytics.nn.modules.EfficientNet.MBConvBlock[48, 48, 5, 1, 6, 0.371]      
 15                  -1  1     36096  ultralytics.nn.modules.EfficientNet.MBConvBlock[48, 48, 5, 1, 6, 0.4]        
 16                  -1  1     40768  ultralytics.nn.modules.EfficientNet.MBConvBlock[48, 80, 3, 1, 6, 0.428]      
 17                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']          
 18            [-1, 11]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 19                  -1  1    113408  ultralytics.nn.modules.block.C2f             [112, 128, 1]                 
 20                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']          
 21             [-1, 5]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 22                  -1  1     34176  ultralytics.nn.modules.block.C2f             [144, 64, 1]                  
 23                  -1  1     36992  ultralytics.nn.modules.conv.Conv             [64, 64, 3, 2]                
 24            [-1, 19]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 25                  -1  1    123648  ultralytics.nn.modules.block.C2f             [192, 128, 1]                 
 26                  -1  1    147712  ultralytics.nn.modules.conv.Conv             [128, 128, 3, 2]              
 27            [-1, 16]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 28                  -1  1    448000  ultralytics.nn.modules.block.C2f             [208, 256, 1]                 
 29        [22, 25, 28]  1    897664  ultralytics.nn.modules.head.Detect           [80, [64, 128, 256]]          
YOLOv8_efficeinet summary: 265 layers, 2265180 parameters, 2265164 gradients

3. 完整代码分享

https://pan.baidu.com/s/1vqFzDmSDLP85P8laBxkYmA?pwd=i5ck

提取码: i5ck 

4. GFLOPs

关于GFLOPs的计算方式可以查看百面算法工程师 | 卷积基础知识——Convolution

未改进的YOLOv8nGFLOPs

img

改进后的GFLOPs

现在手上没有卡了,等过段时候有卡了把这补上,需要的同学自己测一下

5. 进阶

可以与其他的注意力机制或者损失函数等结合,进一步提升检测效果

6. 总结

EfficientNet的主要原理在于提出了一种复合缩放策略,通过统一调整卷积神经网络的深度、宽度和输入分辨率,以实现性能和计算效率的最佳平衡。传统的模型通常只在单一维度上进行缩放(如增加网络的深度或宽度),然而这种方法往往效果有限,难以充分利用额外的计算资源。EfficientNet创新性地提出同时按固定比例缩放这三个维度,从而更好地适应大规模计算需求。在此基础上,研究人员还通过神经架构搜索(NAS)设计了一个高效的基础网络,并通过复合缩放生成了一系列模型。这些模型在多个基准数据集(如ImageNet)上展现了显著的性能提升,同时显著减少了参数量和计算开销,证明了这种方法在准确性和效率方面的优越性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1994766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我们终究会懂得自己并非无所不能

今天参加“全民健身日”公开水域游泳比赛,第一次在游泳上有一种无力感。 以前以为自己游泳怎么都不会累,大不了踩踩水,或者在水上漂着。今天竟然途中可耻地抱着“跟屁虫”休息了。 是不是承认自己的无能,也是一种进步?…

【简历】苏州某大学211硕士:25届Java简历指导通过率低

注:为保证用户信息安全,姓名和学校等信息已经进行同层次变更,内容部分细节也进行了部分隐藏 简历说明 这是一份25届211硕士同学的Java简历,这个学历他的目标必然是冲大厂。 不过他的简历几乎没什么提问点,211在大厂…

1.2 C 语言环境:MinGW 与 CLion 的安装与配置

目录 1 C 语言的由来 2 安装 MinGW 编译器 3 Windows 中安装 CLion 开发环境 3.1 安装 CLion 开发环境 3.2 运行试用 30 天 3.3 新建项目​ 3.4 汉化 4 Mac 中安装 Clion 开发环境 4.1 安装 CLion 开发环境 4.2 运行试用 30 天 4.3 新建项目 ​4.4 汉化 5 向日葵的…

【Linux】系列入门摘抄笔记-6-tar打包压缩和vim编辑器

打包、压缩和解压命令 压缩文件一定要严格区分扩展名 tar 打包程序 tar [主选项+辅选项] [包名] [目标文件或目录]描述:tar命令是Linux下最常用的打包程序。使用tar命令打出来的包称为tar包,因为tar包文件的后缀通常是“.tar”。 每条tar命令只能有一个主选项,而辅助选项…

C语言实现-排序1

文章目录 🎯引言👓排序1.排序的概念以及运用1.1概念1.2运用1.3常见的排序算法 2.排序算法的实现2.1插入排序2.1.1直接插入排序2.1.2希尔排序 2.2选择排序2.2.1直接选择排序2.2.2堆排序 🥇结语 🎯引言 欢迎来到HanLop博客的C语言数…

C#如何对某个词在字符串中出现的次数进⾏计数(LINQ)

文章目录 基础知识实现方法基础计数LINQ优化处理标点符号总结 LINQ(Language-Integrated Query)是C#和VB.NET中强大的查询语言,它可以用来查询集合、SQL数据库、XML文档等。在C#中,我们可以使用LINQ来简化对字符串中特定单词出现次…

C语言实现游戏2048(超详细!!!超易懂!!!)

2048是众所周知的一款经典游戏,在曾经没有智能电脑和手机的年代,也陪伴了我们许多年。那今天就让我们用C语言来回顾一下这款游戏吧~ 一、游戏2048的思路 2048游戏的玩法是在初始的时候,给玩家一个4*4格子的,其中内容全为空的棋盘…

基于SpringBoot+Vue的供应商管理系统(带1w+文档)

基于SpringBootVue的供应商管理系统(带1w文档) 基于SpringBootVue的供应商管理系统(带1w文档) 现今,互联网在我们的日常生活占据着日益重要的地位,我们也越来越离不开对移动设备、电脑等上网设备的使用。传统的供应商管理系统模式主要依靠管理人员纯手工…

PyQt6简易案例代码GUI界面小工具——实现二维码生成器+自定义前后背景色(练手正合适)

目录 专栏导读PyQt6的介绍PyQt6的主要特点包括:使用PyQt6开发应用程序的一般步骤: 库的安装1、初始化与界面设计2、设置前景色、背景色功能完整代码总结 专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双…

IP地址的构成

1. IPv4地址 IPv4地址是最早且目前仍然广泛使用的IP地址版本。由32位二进制数构成,应为32为二进制数太长了,所以我们通常用四个十进制数字来表示,每个数字之间用”.”分隔。这些数字的范围是0到255。IPv4地址的格式为: “A.B.C.…

2024世界机器人大会将于8月21日至25日在京举行

2024年的世界机器人大会预定于8月21日至25日,在北京经济技术开发区的北人亦创国际会展中心隆重举办。 本届大会以“共育新质生产力 共享智能新未来”为核心主题,将汇聚来自全球超过300位的机器人行业专家、国际组织代表、杰出科学家以及企业家&#xff0…

再启新征程——灵川县“灵秀山川”区域公共品牌发布会顺利举办

灵川县,自古便享有“楚越通衢,风气之先”的美誉,见证了无数文化的交流与融合。这里,土地肥沃,资源丰富,如同大自然的无尽宝库,孕育了琳琅满目的优质农特产品。立足于本地优势资源,灵…

Python | Leetcode Python题解之第329题矩阵中的最长递增路径

题目: 题解: class Solution:DIRS [(-1, 0), (1, 0), (0, -1), (0, 1)]def longestIncreasingPath(self, matrix: List[List[int]]) -> int:if not matrix:return 0rows, columns len(matrix), len(matrix[0])outdegrees [[0] * columns for _ in…

数字人直播间搭建教程比较:哪种方案更可行?

当前,数字人直播的应用潜力不断显现,各大中小型企业对其关注度和接受度持续上升,连带着各种数字人直播间搭建教程的阅读量也日益上涨。而不少创业者也因此发现了它所蕴含的市场需求和收益空间,并有了通过为企业搭建数字人直播间以…

三防平板定制化:驱动产业高效化发展的新动能

在数字化转型的浪潮中,三防平板作为一种坚固耐用、功能强大的移动设备,正逐渐成为各行各业提升效率、优化管理的关键工具。通过硬件和软件的定制化服务,三防平板不仅能满足特定行业的需求,更能在复杂的工作环境中展现出卓越的性能…

haproxy实验

目录 为什么要用haproxy? haproxy的基本部署实验: 环境准备: 详细步骤: haproxy-多进程与多线程实验: haproxy的全局global配置实验: 为什么要用haproxy? LVS:没有后端检测&a…

Linux学习笔记:Linux基础知识汇总(kill 进程-vi编辑检索-查看当前文件夹的大小-修复硬盘等)

常见指令 Linux 的 find 命令可以用于在指定目录下查找符合条件的文件或目录。find 命令的基本语法为: find [path] [expression]其中,path 指定要查找的目录路径,expression 指定查找条件。下面是一些常用的 find 命令用法和示例&#xff…

代理IP在社媒营销中的重要作用

伴随着互联网的发展,社交媒体成了人们日常生活中不可或缺的一部分。用户在社交媒体中的活跃度和对内容的分享促进信息内容在短期内迅速传播,使得社交媒体变成了店家推广与销售的重要途径。 随着社交媒体用户基数的不断扩大和社交平台功能的日益丰富&…

煤炭行业信息化运维方案:基于一体化监控管理平台的探讨

随着煤炭行业信息化和智能化进程的加速,煤炭企业面临着前所未有的运维挑战。如何在复杂多变的IT环境中确保系统的稳定运行,提高运维效率,降低运营成本,成为煤炭企业亟待解决的问题。本文将以煤炭行业信息化运维现状为背景&#xf…

C#如何将自己封装的nuget包引入到项目中

问题 自己封装好了一个nuget包,但是不想上传到外网,想局域网使用,有两种方案 搭建私有nuget仓库放到离线文件夹中直接使用 第一种方式请请参考proget安装 下面主要是第二种方式 准备 新建类库项目 using System;namespace ClassLibrary…