YOLOv5改进 | 2023主干篇 | 华为最新VanillaNet主干替换Backbone实现大幅度长点

一、本文介绍

本文给大家来的改进机制是华为最新VanillaNet网络,其是今年最新推出的主干网络,VanillaNet是一种注重极简主义和效率的神经网络架构。它的设计简单,层数较少,避免了像深度架构和自注意力这样的复杂操作(需要注意的是该网络结构的通道数会被放大,GFLOPs的量会很高)。我将其替换整个YOLOv5的Backbone,在一些大目标和小目标检测上均有涨点,效果比上一篇RepViT的效果要好。我的实验数据集是一个包含1000张图片包含大中小的检测目标的数据集上(共有20+类别),下面我会附上基础版本和修改版本的训练对比图,同时我会手把手教你添加该网络结构。

推荐指数:⭐⭐⭐⭐⭐

专栏回顾:YOLOv5改进专栏——持续复现各种顶会内容——内含100+创新 

训练结果对比图->   

(有效性先用YOLOv8上的实验对比,后期会给大家补上)

目录

一、本文介绍

二、VanillaNet原理

2.2  VanillaNet的基本原理

2.2.1 深度训练策略

2.2.2 串联激活函数

三、VanillaNet的核心代码 

  四、手把手教你添加VanillaNet网络结构

修改一

修改二

修改三

修改四

修改五

修改五 

修改六 

修改七

五、VanillaNet的yaml文件

六、成功运行记录 

七、本文总结


二、VanillaNet原理

论文地址: 官方论文地址

代码地址: 官方代码地址


2.2  VanillaNet的基本原理

VanillaNet是一种注重极简主义和效率的神经网络架构。它的设计简单,层数较少,避免了像深度架构和自注意力这样的复杂操作。VanillaNet的关键特性包括深度训练策略,最初使用激活函数训练两个卷积层,随后这个激活函数逐渐简化为恒等映射,允许层合并。此外,VanillaNet还使用并行堆叠的激活函数来提高非线性,从而提升简单网络的性能。

VanillaNet的原理包括以下几个关键点:

1. 深度训练策略:初始阶段采用两个卷积层和一个激活函数进行训练,随着训练进程,激活函数逐渐转化为恒等映射,允许这些层合并,从而减少推断时间。

2. 串联激活函数:VanillaNet引入了并行堆叠激活函数来增强非线性,这对于简单网络的性能至关重要。

下面为大家展示了VanillaNet-6模型的架构

它仅由6个卷积层构成。输入特征的尺寸会在每个阶段降低,而通道数则会翻倍,这一设计借鉴了如AlexNet和VGGNet这类经典神经网络的设计理念。通过这种方式,VanillaNet-6模型能够以较低的计算成本处理图像数据,同时通过增加通道数来保持足够的特征表达能力。


2.2.1 深度训练策略

深度训练策略是指在神经网络训练初期采用比标准配置更多的层和更复杂的结构这通过增加模型的非线性和表示能力来提高训练效果。(这是一种现在比较流行的网络设计方式,在训练的时候使用复杂的结构,推理的时候使用简单的结构)。训练的后期,这些额外层会通过技术手段合并或简化,以减少模型的复杂性和提高推理时的效率。

这种策略允许在初期利用深层结构的强大能力在不牺牲推理速度的前提下,随着训练的进行,逐步优化模型结构,最终达到一个既能保持良好性能又能高效运行的平衡点。这样做的目的是在保持推理效率的同时,利用深度结构在训练过程中提供的额外能力。


2.2.2 串联激活函数

串联激活函数是指在一个神经网络的相同层或连续层中使用多个激活函数,这样可以增强网络处理非线性问题的能力。传统的神经网络可能只在每个卷积层后使用一个激活函数,而串联激活函数的做法是将多个激活函数按序排列,每个函数的输出成为下一个函数的输入。这种串联可以创建更复杂的函数映射,从而允许模型捕捉到更丰富的数据表示和特征。


三、VanillaNet的核心代码 

下面的代码是整个VanillaNet的核心代码,其中有个版本,对应的GFLOPs也不相同,使用方式看章节四。

# Copyright (C) 2023. Huawei Technologies Co., Ltd. All rights reserved.

# This program is free software; you can redistribute it and/or modify it under the terms of the MIT License.

# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MIT License for more details.

import torch
import torch.nn as nn
from timm.layers import weight_init

__all__ = ['vanillanet_5', 'vanillanet_6', 'vanillanet_7', 'vanillanet_8', 'vanillanet_9', 'vanillanet_10',
           'vanillanet_11', 'vanillanet_12', 'vanillanet_13', 'vanillanet_13_x1_5', 'vanillanet_13_x1_5_ada_pool']


class activation(nn.ReLU):
    def __init__(self, dim, act_num=3, deploy=False):
        super(activation, self).__init__()
        self.deploy = deploy
        self.weight = torch.nn.Parameter(torch.randn(dim, 1, act_num * 2 + 1, act_num * 2 + 1))
        self.bias = None
        self.bn = nn.BatchNorm2d(dim, eps=1e-6)
        self.dim = dim
        self.act_num = act_num
        weight_init.trunc_normal_(self.weight, std=.02)

    def forward(self, x):
        if self.deploy:
            return torch.nn.functional.conv2d(
                super(activation, self).forward(x),
                self.weight, self.bias, padding=(self.act_num * 2 + 1) // 2, groups=self.dim)
        else:
            return self.bn(torch.nn.functional.conv2d(
                super(activation, self).forward(x),
                self.weight, padding=self.act_num, groups=self.dim))

    def _fuse_bn_tensor(self, weight, bn):
        kernel = weight
        running_mean = bn.running_mean
        running_var = bn.running_var
        gamma = bn.weight
        beta = bn.bias
        eps = bn.eps
        std = (running_var + eps).sqrt()
        t = (gamma / std).reshape(-1, 1, 1, 1)
        return kernel * t, beta + (0 - running_mean) * gamma / std

    def switch_to_deploy(self):
        if not self.deploy:
            kernel, bias = self._fuse_bn_tensor(self.weight, self.bn)
            self.weight.data = kernel
            self.bias = torch.nn.Parameter(torch.zeros(self.dim))
            self.bias.data = bias
            self.__delattr__('bn')
            self.deploy = True


class Block(nn.Module):
    def __init__(self, dim, dim_out, act_num=3, stride=2, deploy=False, ada_pool=None):
        super().__init__()
        self.act_learn = 1
        self.deploy = deploy
        if self.deploy:
            self.conv = nn.Conv2d(dim, dim_out, kernel_size=1)
        else:
            self.conv1 = nn.Sequential(
                nn.Conv2d(dim, dim, kernel_size=1),
                nn.BatchNorm2d(dim, eps=1e-6),
            )
            self.conv2 = nn.Sequential(
                nn.Conv2d(dim, dim_out, kernel_size=1),
                nn.BatchNorm2d(dim_out, eps=1e-6)
            )

        if not ada_pool:
            self.pool = nn.Identity() if stride == 1 else nn.MaxPool2d(stride)
        else:
            self.pool = nn.Identity() if stride == 1 else nn.AdaptiveMaxPool2d((ada_pool, ada_pool))

        self.act = activation(dim_out, act_num)

    def forward(self, x):
        if self.deploy:
            x = self.conv(x)
        else:
            x = self.conv1(x)
            x = torch.nn.functional.leaky_relu(x, self.act_learn)
            x = self.conv2(x)

        x = self.pool(x)
        x = self.act(x)
        return x

    def _fuse_bn_tensor(self, conv, bn):
        kernel = conv.weight
        bias = conv.bias
        running_mean = bn.running_mean
        running_var = bn.running_var
        gamma = bn.weight
        beta = bn.bias
        eps = bn.eps
        std = (running_var + eps).sqrt()
        t = (gamma / std).reshape(-1, 1, 1, 1)
        return kernel * t, beta + (bias - running_mean) * gamma / std

    def switch_to_deploy(self):
        if not self.deploy:
            kernel, bias = self._fuse_bn_tensor(self.conv1[0], self.conv1[1])
            self.conv1[0].weight.data = kernel
            self.conv1[0].bias.data = bias
            # kernel, bias = self.conv2[0].weight.data, self.conv2[0].bias.data
            kernel, bias = self._fuse_bn_tensor(self.conv2[0], self.conv2[1])
            self.conv = self.conv2[0]
            self.conv.weight.data = torch.matmul(kernel.transpose(1, 3),
                                                 self.conv1[0].weight.data.squeeze(3).squeeze(2)).transpose(1, 3)
            self.conv.bias.data = bias + (self.conv1[0].bias.data.view(1, -1, 1, 1) * kernel).sum(3).sum(2).sum(1)
            self.__delattr__('conv1')
            self.__delattr__('conv2')
            self.act.switch_to_deploy()
            self.deploy = True


class VanillaNet(nn.Module):
    def __init__(self, in_chans=3, num_classes=1000, dims=[96, 192, 384, 768],
                 drop_rate=0, act_num=3, strides=[2, 2, 2, 1], deploy=False, ada_pool=None, **kwargs):
        super().__init__()
        self.deploy = deploy
        if self.deploy:
            self.stem = nn.Sequential(
                nn.Conv2d(in_chans, dims[0], kernel_size=4, stride=4),
                activation(dims[0], act_num)
            )
        else:
            self.stem1 = nn.Sequential(
                nn.Conv2d(in_chans, dims[0], kernel_size=4, stride=4),
                nn.BatchNorm2d(dims[0], eps=1e-6),
            )
            self.stem2 = nn.Sequential(
                nn.Conv2d(dims[0], dims[0], kernel_size=1, stride=1),
                nn.BatchNorm2d(dims[0], eps=1e-6),
                activation(dims[0], act_num)
            )

        self.act_learn = 1

        self.stages = nn.ModuleList()
        for i in range(len(strides)):
            if not ada_pool:
                stage = Block(dim=dims[i], dim_out=dims[i + 1], act_num=act_num, stride=strides[i], deploy=deploy)
            else:
                stage = Block(dim=dims[i], dim_out=dims[i + 1], act_num=act_num, stride=strides[i], deploy=deploy,
                              ada_pool=ada_pool[i])
            self.stages.append(stage)
        self.depth = len(strides)

        self.apply(self._init_weights)
        self.width_list = [i.size(1) for i in self.forward(torch.randn(1, 3, 640, 640))]

    def _init_weights(self, m):
        if isinstance(m, (nn.Conv2d, nn.Linear)):
            weight_init.trunc_normal_(m.weight, std=.02)
            nn.init.constant_(m.bias, 0)

    def change_act(self, m):
        for i in range(self.depth):
            self.stages[i].act_learn = m
        self.act_learn = m

    def forward(self, x):
        results = []
        if self.deploy:
            x = self.stem(x)
        else:
            x = self.stem1(x)
            x = torch.nn.functional.leaky_relu(x, self.act_learn)
            x = self.stem2(x)
        results.append(x)
        for i in range(self.depth):
            x = self.stages[i](x)
            results.append(x)
        return results

    def _fuse_bn_tensor(self, conv, bn):
        kernel = conv.weight
        bias = conv.bias
        running_mean = bn.running_mean
        running_var = bn.running_var
        gamma = bn.weight
        beta = bn.bias
        eps = bn.eps
        std = (running_var + eps).sqrt()
        t = (gamma / std).reshape(-1, 1, 1, 1)
        return kernel * t, beta + (bias - running_mean) * gamma / std

    def switch_to_deploy(self):
        if not self.deploy:
            self.stem2[2].switch_to_deploy()
            kernel, bias = self._fuse_bn_tensor(self.stem1[0], self.stem1[1])
            self.stem1[0].weight.data = kernel
            self.stem1[0].bias.data = bias
            kernel, bias = self._fuse_bn_tensor(self.stem2[0], self.stem2[1])
            self.stem1[0].weight.data = torch.einsum('oi,icjk->ocjk', kernel.squeeze(3).squeeze(2),
                                                     self.stem1[0].weight.data)
            self.stem1[0].bias.data = bias + (self.stem1[0].bias.data.view(1, -1, 1, 1) * kernel).sum(3).sum(2).sum(1)
            self.stem = torch.nn.Sequential(*[self.stem1[0], self.stem2[2]])
            self.__delattr__('stem1')
            self.__delattr__('stem2')

            for i in range(self.depth):
                self.stages[i].switch_to_deploy()

            self.deploy = True



def vanillanet_5(pretrained=False,in_22k=False, **kwargs):
    model = VanillaNet(dims=[128*4, 256*4, 512*4, 1024*4], strides=[2,2,2], **kwargs)
    return model

def vanillanet_6(pretrained=False,in_22k=False, **kwargs):
    model = VanillaNet(dims=[128*4, 256*4, 512*4, 1024*4, 1024*4], strides=[2,2,2,1], **kwargs)
    return model

def vanillanet_7(pretrained=False,in_22k=False, **kwargs):
    model = VanillaNet(dims=[128*4, 128*4, 256*4, 512*4, 1024*4, 1024*4], strides=[1,2,2,2,1], **kwargs)
    return model

def vanillanet_8(pretrained=False, in_22k=False, **kwargs):
    model = VanillaNet(dims=[128*4, 128*4, 256*4, 512*4, 512*4, 1024*4, 1024*4], strides=[1,2,2,1,2,1], **kwargs)
    return model

def vanillanet_9(pretrained=False, in_22k=False, **kwargs):
    model = VanillaNet(dims=[128*4, 128*4, 256*4, 512*4, 512*4, 512*4, 1024*4, 1024*4], strides=[1,2,2,1,1,2,1], **kwargs)
    return model

def vanillanet_10(pretrained=False, in_22k=False, **kwargs):
    model = VanillaNet(
        dims=[128*4, 128*4, 256*4, 512*4, 512*4, 512*4, 512*4, 1024*4, 1024*4],
        strides=[1,2,2,1,1,1,2,1],
        **kwargs)
    return model

def vanillanet_11(pretrained=False, in_22k=False, **kwargs):
    model = VanillaNet(
        dims=[128*4, 128*4, 256*4, 512*4, 512*4, 512*4, 512*4, 512*4, 1024*4, 1024*4],
        strides=[1,2,2,1,1,1,1,2,1],
        **kwargs)
    return model

def vanillanet_12(pretrained=False, in_22k=False, **kwargs):
    model = VanillaNet(
        dims=[128*4, 128*4, 256*4, 512*4, 512*4, 512*4, 512*4, 512*4, 512*4, 1024*4, 1024*4],
        strides=[1,2,2,1,1,1,1,1,2,1],
        **kwargs)
    return model

def vanillanet_13(pretrained=False, in_22k=False, **kwargs):
    model = VanillaNet(
        dims=[128*4, 128*4, 256*4, 512*4, 512*4, 512*4, 512*4, 512*4, 512*4, 512*4, 1024*4, 1024*4],
        strides=[1,2,2,1,1,1,1,1,1,2,1],
        **kwargs)
    return model

def vanillanet_13_x1_5(pretrained=False, in_22k=False, **kwargs):
    model = VanillaNet(
        dims=[128*6, 128*6, 256*6, 512*6, 512*6, 512*6, 512*6, 512*6, 512*6, 512*6, 1024*6, 1024*6],
        strides=[1,2,2,1,1,1,1,1,1,2,1],
        **kwargs)
    return model

def vanillanet_13_x1_5_ada_pool(pretrained=False, in_22k=False, **kwargs):
    model = VanillaNet(
        dims=[128*6, 128*6, 256*6, 512*6, 512*6, 512*6, 512*6, 512*6, 512*6, 512*6, 1024*6, 1024*6],
        strides=[1,2,2,1,1,1,1,1,1,2,1],
        ada_pool=[0,38,19,0,0,0,0,0,0,10,0],
        **kwargs)
    return model

四、手把手教你添加VanillaNet网络结构

这个主干的网络结构添加起来算是所有的改进机制里最麻烦的了,因为有一些网略结构可以用yaml文件搭建出来,有一些网络结构其中的一些细节根本没有办法用yaml文件去搭建,用yaml文件去搭建会损失一些细节部分(而且一个网络结构设计很多细节的结构修改方式都不一样,一个一个去修改大家难免会出错),所以这里让网络直接返回整个网络,然后修改部分 yolo代码以后就都以这种形式添加了,以后我提出的网络模型基本上都会通过这种方式修改,我也会进行一些模型细节改进。创新出新的网络结构大家直接拿来用就可以的。下面开始添加教程->

(同时每一个后面都有代码,大家拿来复制粘贴替换即可,但是要看好了不要复制粘贴替换多了)


修改一

我们复制网络结构代码到“yolov5-master/models”目录下创建一个目录,我这里的名字是modules(如果将文件放在models下面随着改进机制越来越多不太好区分,所以创建一个文件目录将改进机制全部放在里面) ,然后创建一个py文件将代码复制粘贴到里面我这里起的名字是VanillaNet。


修改二

然后我们在我们创建的目录里面创建一个初始化文件'__init__.py',然后在里面导入我们同级目录的所有改进机制

​​

修改三

我们找到如下文件'models/yolo.py'在开头里面导入我们的模块,这里需要注意要将代码放在common导入的文件上面,否则有一些模块会使用我们modules里面的,可能同名导致报错,这里如果你使用多个我的改进机制填写一个即可,不用重复添加。


修改四

添加如下两行代码,根据行数找相似的代码进行添加


修改五

找到七百多行大概把具体看图片,按照图片来修改就行,添加红框内的部分,注意没有()只是函数名,我这里只添加了部分的版本,大家有兴趣这个VanillaNet还有更多的版本可以添加,看我给的代码函数头即可。

        elif m in {自行添加对应的模型即可,下面都是一样的}:
            m = m()
            c2 = m.width_list  # 返回通道列表
            backbone = True


修改五 

下面的两个红框内都是需要改动的。 

        if isinstance(c2, list):
            m_ = m
            m_.backbone = True
        else:
            m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args)  # module
            t = str(m)[8:-2].replace('__main__.', '')  # module type


        np = sum(x.numel() for x in m_.parameters())  # number params
        m_.i, m_.f, m_.type, m_.np = i + 4 if backbone else i, f, t, np # attach index, 'from' index, type


修改六 

如下的也需要修改,全部按照我的来。

代码如下把原先的代码替换了即可。 

        save.extend(x % (i + 4 if backbone else i) for x in ([f] if isinstance(f, int) else f) if x != -1)  # append to savelist
        layers.append(m_)
        if i == 0:
            ch = []
        if isinstance(c2, list):
            ch.extend(c2)
            if len(c2) != 5:
                ch.insert(0, 0)
        else:
            ch.append(c2)

修改七

修改七和前面的都不太一样,需要修改前向传播中的一个部分, 已经离开了parse_model方法了。

可以在图片中开代码行数,没有离开task.py文件都是同一个文件。 同时这个部分有好几个前向传播都很相似,大家不要看错了,是70多行左右的!!!,同时我后面提供了代码,大家直接复制粘贴即可,有时间我针对这里会出一个视频。

找到如下的代码,这里不太好找,我给大家上传一个原始的样子。

然后我们用后面的代码进行替换,替换完之后的样子如下-> 

​​

代码如下->

    def _forward_once(self, x, profile=False, visualize=False):
        y, dt = [], []  # outputs
        for m in self.model:
            if m.f != -1:  # if not from previous layer
                x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layers
            if profile:
                self._profile_one_layer(m, x, dt)
            if hasattr(m, 'backbone'):
                x = m(x)
                if len(x) != 5:  # 0 - 5
                    x.insert(0, None)
                for index, i in enumerate(x):
                    if index in self.save:
                        y.append(i)
                    else:
                        y.append(None)
                x = x[-1]  # 最后一个输出传给下一层
            else:
                x = m(x)  # run
                y.append(x if m.i in self.save else None)  # save output
            if visualize:
                feature_visualization(x, m.type, m.i, save_dir=visualize)
        return x

到这里就完成了修改部分,但是这里面细节很多,大家千万要注意不要替换多余的代码,导致报错,也不要拉下任何一部,都会导致运行失败,而且报错很难排查!!!很难排查!!! 

五、VanillaNet的yaml文件

复制如下yaml文件进行运行!!! 

# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license

# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # 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

backbone:
  # [from, number, module, args]
  [[-1, 1, vanillanet_5, []],  # 0-4-P1/
   [-1, 1, SPPF, [1024, 5]],  # 5
  ]

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

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

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

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

   [[13, 16, 19], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]


六、成功运行记录 

下面是成功运行的截图,已经完成了有1个epochs的训练,图片太大截不全第2个epochs了。 

​​ 


七、本文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv5改进有效涨点专栏,本专栏目前为新开的平均质量分97分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~)如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

 专栏回顾:YOLOv5改进专栏——持续复现各种顶会内容——内含100+创新

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker中部署mysql

原文链接: Docker 安装mysql8.0_docker安装mysql8.0-CSDN博客 1:拉取mysql镜像 docker pull mysql:8.0指定8.0版本的,因为我之前装的是5.6,不支持窗口函数,8版本之后的才支持,所以更换版本。 2&#xf…

C# WPF上位机开发(报表导出)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于在工厂上班的小伙伴来说,导出生产数据、生成报表,这是很习以为常的一个工作。之前的文章中,虽然我们也介绍…

格密码:隐藏超平面问题与uSVP问题 (Ajtai密码)

目录 一. 技术发展 二. 隐藏超平面问题(hidden hyperplanes problem,HHP) 三. 唯一最短向量问题,unique shortest vector problem,uSVP 四. Ajtai-Dwork密码系统(改进版) 4.1 公钥 4.2 私钥 4.3 加密…

Serverless架构:无服务器应用与AWS Lambda-读书笔记

Serverless架构:无服务器应用与AWS Lambda-读书笔记 好的架构可以成就软件,缺乏架构则会破坏软件。 一、Serverless 架构的来龙去脉 在典型的Web应用程序中,服务器接受前端的HTTP请求并处理请求。在保存到数据库之前,数据可能会…

<JavaEE> TCP 的通信机制(六) -- 异常情况处理 和 总结

目录 十、异常情况处理 1)进程崩溃终止 2)主机正常关机 3)机器掉电/网络断开 1> 接收端掉线 2> 发送端掉线 TCP 通信机制 总结 阅读指针 -> 《 TCP 的通信机制 -- 延时应答、捎带应答、面向字节流 》<JavaEE&…

如何使用mac电脑,1、使用快捷命令打开访达,2、使用终端命令创建文件,3、使用命令打开创建的文件,并且在vscode中打开

如何使用mac电脑 1、使用快捷命令打开访达 optioncommand空格键 快速进入访达 shiftcmmandn 创建一个空目录 2、使用终端命令创建文件 2.1进入文件夹 在终端页面输入“cd /Users/yunf/Desktop/”并按回车键(此时进入到桌面文件夹,如果需要进入到其它…

Qt(二):使用udp发送与接收图片

使用Qt来通过UDP协议发送和接收图片可以分为几个步骤。以下是一个基本的指南: 发送图片准备图片数据:首先,你需要将图片转换为可以在网络上传输的数据格式。通常,这涉及到将图片转换为字节数组。设置UDP套接字:在Qt中…

html-css-js移动端导航栏底部固定+i18n国际化全局

需求:要做一个移动端的仿照小程序的导航栏页面操作,但是这边加上了i18n国家化,由于页面切换的时候会导致国际化失效,所以写了这篇文章 1.效果 切换页面的时候中英文也会跟着改变,不会导致切换后回到默认的语言 2.实现…

Linux 查看系统类型和版本(内核版本 | 发行版本)

Linux 查看系统类型和版本 首先普及下linux系统的版本内容1. 查看linux系统内核版本2. 查看linux系统发行版本 首先普及下linux系统的版本内容 内核版本和发行版本区别 内核版本就是指 Linux 中最基层的代码,版本号如 Linux version 3.10.0-327.22.2.el7.x86_64发行…

docker compose 部署 grafana + loki + vector 监控kafka消息

Centos7 随笔记录记录 docker compose 统一管理 granfana loki vector 监控kafka 信息。 当然如果仅仅是想通过 Grafana 监控kafka,推荐使用 Grafana Prometheus 通过JMX监控kafka 目录 1. 目录结构 2. 前提已安装Docker-Compose 3. docker-compose 自定义服…

论文降重同义词替换的效果评估与优化建议 papergpt

大家好,今天来聊聊论文降重同义词替换的效果评估与优化建议,希望能给大家提供一点参考。 以下是针对论文重复率高的情况,提供一些修改建议和技巧,可以借助此类工具: 标题:论文降重同义词替换的效果评估与优…

华为鸿蒙应用--登录页:网络请求、自定义Loading、MD5密码加密、emitter订阅状态变化、持久化登录状态、隐藏软键盘-ArkTs

HarmonyOS系列 华为鸿蒙应用--底部导航栏Tabs(自适应手机和平板)-ArkTs_华为鸿蒙应用 csdn 底部导航栏-CSDN博客 华为鸿蒙应用--欢迎页SplashPage倒计时跳过(自适应手机和平板)-ArkTs_app.media.ic_splash_page_background-CSDN…

开箱即用的企业级数据和业务管理中后台前端框架Ant Design Pro 5的开箱使用和偏好配置

Ant Design Pro 介绍 Ant Design Pro 是一个开箱即用的企业级前端解决方案,基于 Ant Design 设计体系,提供了丰富的组件和功能,帮助开发者更快速地开发和部署企业级应用。 Ant Design Pro 使用 React、umi 和 dva 这三个主要的前端开发技术…

EXPLORING DIFFUSION MODELS FOR UNSUPERVISED VIDEO ANOMALY DETECTION 论文阅读

EXPLORING DIFFUSION MODELS FOR UNSUPERVISED VIDEO ANOMALY DETECTION 论文阅读 ABSTRACT1. INTRODUCTION2. RELATEDWORK3. METHOD4. EXPERIMENTAL ANALYSIS AND RESULTS4.1. Comparisons with State-Of-The-Art (SOTA)4.2. Diffusion Model Analysis4.3. Qualitative Result…

Kubernetes 学习总结(41)—— 云原生容器网络详解

背景 随着网络技术的发展,网络的虚拟化程度越来越高,特别是云原生网络,叠加了物理网络、虚机网络和容器网络,数据包在网络 OSI 七层网络模型、TCP/IP 五层网络模型的不同网络层进行封包、转发和解包。网络数据包跨主机网络、容器…

百度营销发布“品牌智能体”,打造“五项全能”的品牌数字分身

生成式AI时代,品牌营销如何持续出彩?全能的品牌数字分身长什么样?12月27日,百度营销“品牌智能体生成式AI产品发布会” 在北京举行。会上,百度营销正式发布“品牌智能体”,全新的“品牌智能体”依托于百度生…

HCIA-Datacom题库(自己整理分类的)——OSPF协议多选

ospf的hello报文功能是 邻居发现 同步路由器的LSDB 更新LSA信息 维持邻居关系 下列关于OSPF区域描述正确的是 在配置OSPF区域正确必须给路由器的loopback接配置IP地址 所有的网络都应在区域0中宣告 骨干区域的编号不能为2 区域的编号范围是从0.0.0.0到255.255.255.255…

Grafana 配置告警

配置告警 配置告警 1. Grafana 配置文件配置 #################################### SMTP / Emailing ########################## [smtp] enabled true host smtp.qq.com:587 user 9**qq.com # If the password contains # or ; you have to wrap it with triple quotes…

2702 高级打字机

因为Undo操作只能撤销Type操作,所以Undo x 实际上就是删除文章末尾x个字母。用一个栈即可解决(每个字母最多进出一次)。 这种情况下只需要设计一个合理的数据结构依次执行操作即可。 版本树:Undo x撤销最近的x次修改操作&#xf…

idea提示unable to import maven project

问题描述: idea导入maven依赖时提示unable to import maven project 打开log日志如下: 问题原因以及解决方案: maven版本与idea版本不兼容,切换maven版本即可
最新文章