YOLO算法改进7【中阶改进篇】:主干网络C3替换为轻量化网络MobileNetV3

news2024/9/25 23:17:20

解决问题:YOLOv5主干特征提取网络采用C3结构,带来较大的参数量,检测速度较慢,应用受限,在某些真实的应用场景如移动或者嵌入式设备,如此大而复杂的模型时难以被应用的。首先是模型过于庞大,面临着内存不足的问题,其次这些场景要求低延迟,或者说响应速度要快,想象一下自动驾驶汽车的行人检测系统如果速度很慢会发生什么可怕的事情。所以,研究小而高效的CNN模型在这些场景至关重要,至少目前是这样,尽管未来硬件也会越来越快。本文尝试将主干特征提取网络替换为更轻量的MobileNet网络,以实现网络模型的轻量化,平衡速度和精度。

一、MobileNetV3简介

MobileNetV3,是谷歌在2019年3月21日提出的轻量化网络架构,在前两个版本的基础上,加入神经网络架构搜索(NAS)和h-swish激活函数,并引入SE通道注意力机制,性能和速度都表现优异,受到学术界和工业界的追捧。
引用大佬的描述:MobileNet V3 = MobileNet v2 + SE结构 + hard-swish activation +网络结构头尾微调
在这里插入图片描述

摘要: 我们提出下一代的mobilenet基于一种互补搜索技术的组合作为一种新颖的建筑设计。MobileNetV3调到手机cpu通过硬件组合感知网络架构搜索(NAS)的补充NetAdapt算法,然后进行改进通过新颖的建筑进步。这篇论文从探索如何自动搜索算法和网络工作设计可以一起利用互补的工作提高整体技术水平的方法。通过在这个过程中,我们创建了两个新的MobileNet模型:MobileNetV3-Large和MobileNetV3-Small针对高资源和低资源用例。这些然后调整模型并将其应用于对象检测和语义分割任务。为了完成任务语义分割(或任何密集像素预测),我们提出了一种新的高效分割解码器空间金字塔池(LR-ASPP)。我们实现新状态的艺术结果移动分类,检测和分割。MobileNetV3-Large则高出3.2%准确的ImageNet分类,同时减少延迟与MobileNetV2相比减少了20%。MobileNetV3-Small是与MobileNetV2模型相比,准确率提高了6.6%具有相当的延迟。MobileNetV3-Large检测与MobileNetV2在COCO检测上的精度大致相同,速度快了25%以上。MobileNetV3-Large
LRASPP在类似情况下比MobileNetV2 R-ASPP快34%城市景观分割的准确性。

论文地址:https://arxiv.org/abs/1905.02244.pdf
代码:https://github.com/LeBron-Jian/DeepLearningNote

MobileNetV1&MobileNetV2&MobileNetV3总结
在这里插入图片描述
MobileNet V3 相关技术如下:
1,用 MnasNet 搜索网络结构
2,用 MobileNetV1 的深度可分离卷积
3,用 MobileNetV2 的倒置残差线性瓶颈结构
4,引入轻量级注意力 SE模块
5,使用新的激活函数 h-swish(x)
6,网络搜索中利用两个策略:资源受限的 NAS 和 NetAdapt
7,修改MobileNet V2 最后部分减小计算
在这里插入图片描述

二、YOLOv5结合MobileNetV3_small

方 法

第一步修改common.py,增加MobileNetV3模块。

class StemBlock(nn.Module):
    def __init__(self, c1, c2, k=3, s=2, p=None, g=1, act=True):
        super(StemBlock, self).__init__()
        self.stem_1 = Conv(c1, c2, k, s, p, g, act)
        self.stem_2a = Conv(c2, c2 // 2, 1, 1, 0)
        self.stem_2b = Conv(c2 // 2, c2, 3, 2, 1)
        self.stem_2p = nn.MaxPool2d(kernel_size=2, stride=2, ceil_mode=True)
        self.stem_3 = Conv(c2 * 2, c2, 1, 1, 0)

    def forward(self, x):
        stem_1_out = self.stem_1(x)
        stem_2a_out = self.stem_2a(stem_1_out)
        stem_2b_out = self.stem_2b(stem_2a_out)
        stem_2p_out = self.stem_2p(stem_1_out)
        out = self.stem_3(torch.cat((stem_2b_out, stem_2p_out), 1))
        return out

class h_sigmoid(nn.Module):
    def __init__(self, inplace=True):
        super(h_sigmoid, self).__init__()
        self.relu = nn.ReLU6(inplace=inplace)

    def forward(self, x):
        return self.relu(x + 3) / 6


class h_swish(nn.Module):
    def __init__(self, inplace=True):
        super(h_swish, self).__init__()
        self.sigmoid = h_sigmoid(inplace=inplace)

    def forward(self, x):
        y = self.sigmoid(x)
        return x * y


class SELayer(nn.Module):
    def __init__(self, channel, reduction=4):
        super(SELayer, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Sequential(
            nn.Linear(channel, channel // reduction),
            nn.ReLU(inplace=True),
            nn.Linear(channel // reduction, channel),
            h_sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x)
        y = y.view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y


class conv_bn_hswish(nn.Module):
    """
    This equals to
    def conv_3x3_bn(inp, oup, stride):
        return nn.Sequential(
            nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
            nn.BatchNorm2d(oup),
            h_swish()
        )
    """

    def __init__(self, c1, c2, stride):
        super(conv_bn_hswish, self).__init__()
        self.conv = nn.Conv2d(c1, c2, 3, stride, 1, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = h_swish()

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))

    def fuseforward(self, x):
        return self.act(self.conv(x))


class MobileNetV3_InvertedResidual(nn.Module):
    def __init__(self, inp, oup, hidden_dim, kernel_size, stride, use_se, use_hs):
        super(MobileNetV3_InvertedResidual, self).__init__()
        assert stride in [1, 2]

        self.identity = stride == 1 and inp == oup
        
        # 输入通道图 = 扩张通道数 则不进行通道扩张
        if inp == hidden_dim:
            self.conv = nn.Sequential(
                # dw
                nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim,
                          bias=False),
                nn.BatchNorm2d(hidden_dim),
                h_swish() if use_hs else nn.ReLU(inplace=True),
                # Squeeze-and-Excite
                SELayer(hidden_dim) if use_se else nn.Sequential(),
                # Eca_layer(hidden_dim) if use_se else nn.Sequential(),#1.13.2022
                # pw-linear
                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
                nn.BatchNorm2d(oup),
            )
        else:
            # 否则先进行扩张  
            self.conv = nn.Sequential(
                # pw
                nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
                nn.BatchNorm2d(hidden_dim),
                h_swish() if use_hs else nn.ReLU(inplace=True),
                # dw
                nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim,
                          bias=False),
                nn.BatchNorm2d(hidden_dim),
                # Squeeze-and-Excite
                SELayer(hidden_dim) if use_se else nn.Sequential(),
                # Eca_layer(hidden_dim) if use_se else nn.Sequential(),  # 1.13.2022
                h_swish() if use_hs else nn.ReLU(inplace=True),
                # pw-linear
                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
                nn.BatchNorm2d(oup),
            )

    def forward(self, x):
        y = self.conv(x)
        if self.identity:
            return x + y
        else:
            return y

第二步:将yolo.py中注册模块。

if m in [Conv,MobileNetV3_InvertedResidual,ShuffleNetV2_InvertedResidual,
               ]:
# 加入h_sigmoid,h_swish,SELayer,conv_bn_hswish,MobileNetV3_InvertedResidual五个模块

第三步:修改yaml文件

backbone:
  # MobileNetV3-large
  # [from, number, module, args]
  [[-1, 1, conv_bn_hswish, [16, 2]],                   # 0-p1/2
   [-1, 1, MobileNetV3_InvertedResidual, [ 16,  16, 3, 1, 0, 0]],  # 1-p1/2
   [-1, 1, MobileNetV3_InvertedResidual, [ 24,  64, 3, 2, 0, 0]],  # 2-p2/4
   [-1, 1, MobileNetV3_InvertedResidual, [ 24,  72, 3, 1, 0, 0]],  # 3-p2/4
   [-1, 1, MobileNetV3_InvertedResidual, [ 40,  72, 5, 2, 1, 0]],  # 4-p3/8
   [-1, 1, MobileNetV3_InvertedResidual, [ 40, 120, 5, 1, 1, 0]],  # 5-p3/8
   [-1, 1, MobileNetV3_InvertedResidual, [ 40, 120, 5, 1, 1, 0]],  # 6-p3/8
   [-1, 1, MobileNetV3_InvertedResidual, [ 80, 240, 3, 2, 0, 1]],  # 7-p4/16
   [-1, 1, MobileNetV3_InvertedResidual, [ 80, 200, 3, 1, 0, 1]],  # 8-p4/16
   [-1, 1, MobileNetV3_InvertedResidual, [ 80, 184, 3, 1, 0, 1]],  # 9-p4/16
   [-1, 1, MobileNetV3_InvertedResidual, [ 80, 184, 3, 1, 0, 1]],  # 10-p4/16
   [-1, 1, MobileNetV3_InvertedResidual, [112, 480, 3, 1, 1, 1]],  # 11-p4/16
   [-1, 1, MobileNetV3_InvertedResidual, [112, 672, 3, 1, 1, 1]],  # 12-p4/16
   [-1, 1, MobileNetV3_InvertedResidual, [160, 672, 5, 1, 1, 1]],  # 13-p4/16
   [-1, 1, MobileNetV3_InvertedResidual, [160, 960, 5, 2, 1, 1]],  # 14-p5/32   原672改为原算法960
   [-1, 1, MobileNetV3_InvertedResidual, [160, 960, 5, 1, 1, 1]],  # 15-p5/32
  ]

根据MobileNetv3的网络结构来修改配置文件。
在这里插入图片描述
根据网络结构我们可以看出MobileNetV3模块包含六个参数[out_ch, hidden_ch, kernel_size, stride, use_se, use_hs]:
out_ch: 输出通道
hidden_ch: 表示在Inverted residuals中的扩张通道数
kernel_size: 卷积核大小
stride: 步长
use_se: 表示是否使用 SELayer,使用了是1,不使用是0
use_hs: 表示使用 h_swish 还是 ReLU,使用h_swish是1,使用 ReLU是0
修改的时候,需要注意/8,/16,/32等位置特征图的变换
在这里插入图片描述
同样的,head部分这几个concat的层也要做修改:
在这里插入图片描述
yaml文件修改后代码如下:

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
 
# Parameters
nc: 80  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # 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
 
   # Mobilenetv3-small backbone
   # MobileNetV3_InvertedResidual [out_ch, hid_ch, k_s, stride, SE, HardSwish]
backbone:
  # [from, number, module, args]
  [[-1, 1, conv_bn_hswish, [16, 2]],             # 0-p1/2   320*320
   [-1, 1, MobileNetV3, [16,  16, 3, 2, 1, 0]],  # 1-p2/4   160*160
   [-1, 1, MobileNetV3, [24,  72, 3, 2, 0, 0]],  # 2-p3/8   80*80
   [-1, 1, MobileNetV3, [24,  88, 3, 1, 0, 0]],  # 3        80*80
   [-1, 1, MobileNetV3, [40,  96, 5, 2, 1, 1]],  # 4-p4/16  40*40
   [-1, 1, MobileNetV3, [40, 240, 5, 1, 1, 1]],  # 5        40*40
   [-1, 1, MobileNetV3, [40, 240, 5, 1, 1, 1]],  # 6        40*40
   [-1, 1, MobileNetV3, [48, 120, 5, 1, 1, 1]],  # 7        40*40
   [-1, 1, MobileNetV3, [48, 144, 5, 1, 1, 1]],  # 8        40*40
   [-1, 1, MobileNetV3, [96, 288, 5, 2, 1, 1]],  # 9-p5/32  20*20
   [-1, 1, MobileNetV3, [96, 576, 5, 1, 1, 1]],  # 10       20*20
   [-1, 1, MobileNetV3, [96, 576, 5, 1, 1, 1]],  # 11       20*20
  ]
 
# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [96, 1, 1]],  # 12                         20*20
   [-1, 1, nn.Upsample, [None, 2, 'nearest']], # 13         40*40
   [[-1, 8], 1, Concat, [1]],  # cat backbone P4            40*40
   [-1, 3, C3, [144, False]],  # 15                         40*40
 
   [-1, 1, Conv, [144, 1, 1]], # 16                         40*40
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],# 17          80*80
   [[-1, 3], 1, Concat, [1]],  # cat backbone P3            80*80
   [-1, 3, C3, [168, False]],  # 19 (P3/8-small)            80*80
 
   [-1, 1, Conv, [168, 3, 2]], # 20                         40*40
   [[-1, 16], 1, Concat, [1]], # cat head P4                40*40
   [-1, 3, C3, [312, False]],  # 22 (P4/16-medium)          40*40
 
   [-1, 1, Conv, [312, 3, 2]], # 23                         20*20
   [[-1, 12], 1, Concat, [1]], # cat head P5                20*20
   [-1, 3, C3, [408, False]],  # 25 (P5/32-large)           20*20
 
   [[19, 22, 25], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

三、YOLOv5结合MobileNetV3_large

MobileNetV3_large和MobileNetV3_small区别在于yaml文件中head中concat连接不同,深度因子和宽度因子不同。接下来我们就直接改动yaml的部分,其余参考上面步骤。

然后根据MobileNetv3的网络结构来修改配置文件。
在这里插入图片描述
修改后代码如下:

# Parameters
nc: 20  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # 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 v6.0 backbone
backbone:
 
  [[-1, 1, conv_bn_hswish, [16, 2]],                  # 0-p1/2
   [-1, 1, MobileNetV3, [ 16,  16, 3, 1, 0, 0]],  # 1-p1/2
   [-1, 1, MobileNetV3, [ 24,  64, 3, 2, 0, 0]],  # 2-p2/4
   [-1, 1, MobileNetV3, [ 24,  72, 3, 1, 0, 0]],  # 3-p2/4
   [-1, 1, MobileNetV3, [ 40,  72, 5, 2, 1, 0]],  # 4-p3/8
   [-1, 1, MobileNetV3, [ 40, 120, 5, 1, 1, 0]],  # 5-p3/8
   [-1, 1, MobileNetV3, [ 40, 120, 5, 1, 1, 0]],  # 6-p3/8
   [-1, 1, MobileNetV3, [ 80, 240, 3, 2, 0, 1]],  # 7-p4/16
   [-1, 1, MobileNetV3, [ 80, 200, 3, 1, 0, 1]],  # 8-p4/16
   [-1, 1, MobileNetV3, [ 80, 184, 3, 1, 0, 1]],  # 9-p4/16
   [-1, 1, MobileNetV3, [ 80, 184, 3, 1, 0, 1]],  # 10-p4/16
   [-1, 1, MobileNetV3, [112, 480, 3, 1, 1, 1]],  # 11-p4/16
   [-1, 1, MobileNetV3, [112, 672, 3, 1, 1, 1]],  # 12-p4/16
   [-1, 1, MobileNetV3, [160, 672, 5, 1, 1, 1]],  # 13-p4/16
   [-1, 1, MobileNetV3, [160, 960, 5, 2, 1, 1]],  # 14-p5/32   原672改为原算法960
   [-1, 1, MobileNetV3, [160, 960, 5, 1, 1, 1]],  # 15-p5/32
  ]
# YOLOv5 v6.0 head
head:
  [ [ -1, 1, Conv, [ 256, 1, 1 ] ],
    [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
    [ [ -1, 13], 1, Concat, [ 1 ] ],  # cat backbone P4
    [ -1, 1, C3, [ 256, False ] ],  # 13
 
    [ -1, 1, Conv, [ 128, 1, 1 ] ],
    [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
    [ [ -1, 6 ], 1, Concat, [ 1 ] ],  # cat backbone P3
    [ -1, 1, C3, [ 128, False ] ],  # 17 (P3/8-small)
 
    [ -1, 1, Conv, [ 128, 3, 2 ] ],
    [ [ -1, 20 ], 1, Concat, [ 1 ] ],  # cat head P4
    [ -1, 1, C3, [ 256, False ] ],  # 20 (P4/16-medium)
 
    [ -1, 1, Conv, [ 256, 3, 2 ] ],
    [ [ -1, 16 ], 1, Concat, [ 1 ] ],  # cat head P5
    [ -1, 1, C3, [ 512, False ] ],  # 23 (P5/32-large)
 
    [ [ 23, 26, 29 ], 1, Detect, [ nc, anchors ] ],  # Detect(P3, P4, P5)
  ]

网络运行结果:
在这里插入图片描述
我们可以看到MobileNetV3-large模型比MobileNetV3-small多了更多的MobileNet_Block结构,残差倒置结构中通道数维度也增大了许多,速度比YOLOv5s慢将近一半,但是参数变少,效果介乎MobileNetV3-small和YOLOv5s之间,可以作为模型对比,凸显自己模型优势。

结 果:如果训练之后发现掉点纯属正常现象,因为轻量化网络在提速减少计算量的同时会降低精度。

:主干网络的替换不仅仅是适用改进YOLOv5,也可以改进其他的YOLO网络以及目标检测网络,比如YOLOv4、v3等。

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

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

相关文章

git在vscode 的使用过程中 创建新分支 修改新分支代码 发现 master分支的代码也被修改了

1.问题 在我进行 代码迭代的时候 因为我主要用的是 vscode 我想创建一个分支 开发其他的功能 我发现一个问题 就是我创建了一个新的分支 修改代码 发现 master 也被修改了 就如同 这两个分支 都一样 指向了master 2.过程 经过我的测试和百度 我发现 怎么都不行 看了看 过程都没…

录制完视频如何去除重复部分?

在录制视频的过程中,有时会出现一些重复的部分,这给视频的制作人员带来了不小的困扰。如果不及时去除重复部分,不仅会影响观众的观看体验,还会浪费观众的时间和从业者的精力。那录制完的视频如何去除重复部分呢?无须担…

为什么我的网络这么卡卡卡卡卡?(网络调试篇)

前言 最近小白迷上了打游戏。 有没有一起上王者的小伙伴? 有没有一起吃鸡的小伙伴? 欧耶, 咱们组队 送人头去吧 为了不让对方太菜, 送人头是与对方最高的敬意。 闲话说到这,本文就结束了。 感谢观看~…

软件工程经济学习题 答案(不保证对错,找不到答案)

一、资金等值计算 1.某IT企业今年向银行贷款20万元以购置一台设备。若银行贷款利率为10%,规定10年内等额偿还,试求每年的偿还金额。 2.某软件企业向银行贷款200万元,按年利率为8%进行复利计息,试求该企业第5年末连本带利一次偿还银…

基于包围盒算法的三维点云数据压缩和曲面重建matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 包围盒构建 4.2 点云压缩 4.3 曲面重建 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ...........................................…

iconify图标集离线使用方案简介

1.需求描述 前端项目,技术栈使用Vue3Element Plus,参考了ruoyi-vue-pro项目与vue-element-plus-admin项目,封装了一个Icon组件,图标使用的是iconify,项目部署在内网环境,不能连接互联网,需要部署一套iconi…

nosql-redis整合测试

nosql-redis整合测试 1、创建项目并导入redis2、配置redis3、写测试类4、在redis中创建key5、访问80826、在集成测试中测试方法 1、创建项目并导入redis 2、配置redis 3、写测试类 4、在redis中创建key 5、访问8082 6、在集成测试中测试方法 package com.example.boot3.redis;…

DDR加终端匹配电阻和不加信号质量的区别

DDR采用菊花链拓扑结构时,由于信号传输线较长通常需要在DDR末端加上终端匹配电阻,端接的方式有很多,但是都是为了解决信号的反射问题,通常为了消除信号的反射可以在信号的源端或者终端进行解决,在源端处消除反射是采用…

Schmitt Trigger本质就是一个带迟滞的比较器

Chapter 18 Special Purpose CMOS Circuits 甚高 24 人赞同了该文章 Chapter 18 Special Purpose CMOS Circuits 这一章讲几个实用电路, Schmitt trigger 输入信号noisy, 输出产生干净的pulse. 然后介绍multivibrator, 拥有astable和monostable两态. input buffer design 对…

drf视图组件

Django REST framwork 提供的视图的主要作用: 控制序列化器的执行(检验、保存、转换数据)控制数据库查询的执行 1.1 视图继承关系 视图的方法与属性: 1.2 视图 REST framework 提供了众多的通用视图基类与扩展类,以…

全国250米DEM数据

全国250米DEM数据 DEM是数字高程模型的英文简称(Digital Elevation Model),是研究分析地形、流域、地物识别的重要原始资料。由于DEM 数据能够反映一定分辨率的局部地形特征,因此通过DEM 可提取大量的地表形态信息,可用于绘制等高线、坡度图、…

git集成github(二)-- 遇见的问题与解决方法

1、share project on github时,弹出Cannot load information for github.com/zouxiaoya:Connection reset问题。 解决方法:pycharm-->setting-->version control-->github中,删除掉当前用户,点击reset重置即可。 2、 pus…

UE和Android互相调用

ue和android互调 这两种方式都是在UE打包的Android工程之上进行的。 一、首先是UE打包Android,勾选下面这项 如果有多个场景需要添加场景 工程文件在这个路径下 然后可以通过Android Studio打开,选择gradle打开 先运行一下,看看是否可以发布…

C语言——最古老的树

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 缺乏明确的目标,一生将庸庸…

Kubectl 部署有状态应用(上)

前面介绍了Deployment以及如何部署无状态应用。 Kubectl 部署无状态应用Deployment Controller详解(上)Deployment Controller详解(下) 本文将继续介绍如何在k8s上部署有状态应用。 有状态和无状态服务的区别 无状态&#xff…

视频监控技术经历了哪些发展阶段?视频监控技术未来趋势展望

随着城市经济的发展和进步,视频监控也已经应用在人们衣食住行的方方面面,成为社会主体的一个重要组成部分。随着视频监控的重要性越来越凸显,大家对视频监控技术的发展也非常关注。今天我们来简单阐述一下,视频监控技术经历的几个…

智能优化算法应用:基于蜣螂算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于蜣螂算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于蜣螂算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蜣螂算法4.实验参数设定5.算法结果6.参考文献7.MA…

Selenium自动化测试框架(附教程+源码)

说起自动化测试,我想大家都会有个疑问,要不要做自动化测试? 自动化测试给我们带来的收益是否会超出在建设时所投入的成本,这个嘛别说是我,即便是高手也很难回答,自动化测试的初衷是美好的,而测试…

德勤中国合伙人姚承懿:只是“线上化”的数字化转型不会成功

投资者们都期待超出预期的增长,倾向规避未知风险。当下的宏观经济形势复杂,外部条件多变,那些善于驾驭风险,给市场以确定性的企业,能够得到投资者更多的青睐。 合规与增长是支撑上市公司市值的关键要素。有统计数据显…

孔夫子二手书采集

文章目录 项目演示软件采集单本数据网页搜索数据对比 使用场景概述部分核心逻辑Vb工程图数据导入与读取下拉框选择参数设置线程 使用方法下载软件授权导入文件预览处理后的数据 项目结构附件说明 项目演示 操作视频详见演示视频,以下为图文演示 软件采集单本数据 …