当前位置: 首页 > news >正文

YOLOv5算法改进(15)— 更换Neck之AFPN

前言:Hello大家好,我是小哥谈。在YOLOv5中添加AFPN(Adaptive Feature Pyramid Network)可以提高目标检测的准确性。AFPN是一种用于目标检测任务的功能增强模块,它能够自适应地融合来自不同层级的特征图,以提供更好的目标定位和尺度适应能力。🌈  

前期回顾:

          YOLOv5算法改进(1)— 如何去改进YOLOv5算法

          YOLOv5算法改进(2)— 添加SE注意力机制

          YOLOv5算法改进(3)— 添加CBAM注意力机制

          YOLOv5算法改进(4)— 添加CA注意力机制

          YOLOv5算法改进(5)— 添加ECA注意力机制

          YOLOv5算法改进(6)— 添加SOCA注意力机制

          YOLOv5算法改进(7)— 添加SimAM注意力机制

          YOLOv5算法改进(8)— 替换主干网络之MobileNetV3

          YOLOv5算法改进(9)— 替换主干网络之ShuffleNetV2

          YOLOv5算法改进(10)— 替换主干网络之GhostNet

          YOLOv5算法改进(11)— 替换主干网络之EfficientNetv2

          YOLOv5算法改进(12)— 替换主干网络之Swin Transformer

          YOLOv5算法改进(13)— 替换主干网络之PP-LCNet

          YOLOv5算法改进(14)— 更换Neck之BiFPN

          目录

🚀1.论文

🚀2.AFPN网络架构及添加步骤

🚀3.更换AFPN的方法

💥💥步骤1:在common.py中添加AFPN模块

💥💥步骤2:修改yolo.py文件

💥💥步骤3:创建自定义的yaml文件

💥💥步骤4:验证是否加入成功

🚀1.论文

多尺度特征提取的一种常见策略是采用经典的自上而下和自下而上的特征金字塔网络。然而,这些方法遭受特征信息的丢失或退化,削弱了非相邻 Level 的融合效果。本文提出了一种渐近特征金字塔网络(AFPN)来支持非相邻层的直接交互。AFPN是通过融合两个相邻的Low-Level特征来启动的,并渐进地将High-Level特征纳入融合过程。通过这种方式,可以避免非相邻 Level 之间的较大语义差距。考虑到在每个空间位置的特征融合过程中可能出现多目标信息冲突,进一步利用自适应空间融合操作来缓解这些不一致。🌟

本文将所提出的AFPN纳入两阶段和一阶段目标检测框架,并使用MS-COCO 2017验证和测试数据集进行评估。实验评估表明,与其他最先进的特征金字塔网络相比,论文作者的方法获得了更具竞争力的结果。🌟

论文主要贡献:♨️♨️♨️

1.作者引入了一种渐进特征金字塔网络(AFPN),它有助于跨非相邻 Level 的直接特征融合,从而防止特征信息在传输和交互过程中的丢失或退化。

2.为了抑制不同层次特征之间的信息矛盾,作者在多层次特征融合过程中引入了自适应空间融合操作。

3.在MS COCO 2017验证和测试数据集上的大量实验表明,与其他特征金字塔网络相比,作者的方法表现出优越的计算效率,同时获得了更具竞争力的结果。

论文题目:《AFPN: Asymptotic Feature Pyramid Network for Object Detection》

论文地址:  https://arxiv.org/abs/2306.15988v1

代码实现:  GitHub - gyyang23/AFPN


🚀2.AFPN网络架构及添加步骤

论文所提出的AFPN架构如下图所示。在Backbone网络自下而上的特征提取过程中,AFPN渐进地集成了Low-LevelHigh-Level顶级特征。具体来说,AFPN最初融合了Low-Level特征,然后融合了深层特征,最后融合了最High-Level的特征,即最抽象的特征。非相邻层次特征之间的语义差距大于相邻层次特征间的语义差距,尤其是底部和顶部特征,这直接导致了非相邻层次特征的融合效果较差由于AFPN的架构是渐进的,这将使不同 Level 特征的语义信息在渐进融合过程中更加接近,从而缓解上述问题📚

为了对齐维度并为特征融合做准备,作者使用1×1卷积双线性插值方法对特征进行上采样。另一方面,作者根据所需的下采样率使用不同的卷积核Stride来执行下采样。例如,作者应用Stride为2的2×2卷积来实现2次下采样,应用Stride为4的4×4卷积来实现4次下采样以及应用Stride为8的8×8卷积来实现8倍下采样。在特征融合之后,作者使用4个残差单元继续学习特征,这些残差单元类似于ResNet。每个残差单元包括2个3×3卷积。由于YOLO中只使用了3个 Level 的特征,因此没有8次上采样和8次下采样。🌴

在YOLOv5中添加AFPN(Adaptive Feature Pyramid Network)可以提高目标检测的准确性。AFPN是一种用于目标检测任务的功能增强模块,它能够自适应地融合来自不同层级的特征图,以提供更好的目标定位和尺度适应能力。

要在YOLOv5中添加AFPN,可以按照以下步骤进行操作:👇

🍀(1)首先,在YOLOv5的模型架构中引入AFPN模块。为此,您可以修改模型的backbone部分。通常,YOLOv5使用CSPDarknet53作为backbone,您可以在该部分添加AFPN。

🍀(2)在引入AFPN之后,您需要确定要从backbone中选择哪些特征图进行融合。一般来说,可以选择较高层级和较低层级的特征图进行融合,以获得更好的目标定位和尺度适应。

🍀(3)接下来,您需要实现AFPN模块的具体结构。AFPN通常由上采样和特征图融合两部分组成。上采样部分可以使用双线性插值或者转置卷积等方法进行实现。特征图融合部分可以使用逐元素相加或者卷积等方法进行实现。

🍀(4)最后,在YOLOv5的检测头部之前,将AFPN模块的输出与backbone的输出进行融合。这样可以将更多信息引入到检测头部,提升目标检测的准确性。

说明:♨️♨️♨️

请注意,在实现AFPN时,您需要根据YOLOv5的具体版本和代码结构进行适当的修改。这里提供的步骤仅供参考,具体实现可能因版本而异。建议您查阅相关文档和代码,以了解如何在YOLOv5中添加AFPN的详细实现方法。另外,需要注意的是,添加AFPN可能会增加模型的计算和内存开销,因此在使用时需要根据实际情况进行权衡和优化。


🚀3.更换AFPN的方法

💥💥步骤1:在common.py中添加AFPN模块

 
class Upsample(nn.Module):"""Applies convolution followed by upsampling."""
# ---1.渐进架构部分(融合前的准备)--- #def __init__(self, c1, c2, scale_factor=2):super().__init__()# self.cv1 = Conv(c1, c2, 1)# self.upsample = nn.Upsample(scale_factor=scale_factor, mode='nearest')  # or model='bilinear' non-deterministicif scale_factor == 2:self.cv1 = nn.ConvTranspose2d(c1, c2, 2, 2, 0, bias=True)  # 如果下采样率为2,就用Stride为2的2×2卷积来实现2次下采样elif scale_factor == 4:self.cv1 = nn.ConvTranspose2d(c1, c2, 4, 4, 0, bias=True)  # 如果下采样率为4,就用Stride为4的4×4卷积来实现4次下采样def forward(self, x):# return self.upsample(self.cv1(x))return self.cv1(x)# ---2.自适应空间融合(ASFF)--- #
class ASFF2(nn.Module):"""ASFF2 module for YOLO AFPN head https://arxiv.org/abs/2306.15988"""def __init__(self, c1, c2, level=0):super().__init__()c1_l, c1_h = c1[0], c1[1]self.level = levelself.dim = c1_l, c1_hself.inter_dim = self.dim[self.level]compress_c = 8#如果是第0层if level == 0:
# self.stride_level_1调整level-1出来的特征图,通道调整为和level-0出来的特征图一样大小self.stride_level_1 = Upsample(c1_h, self.inter_dim)
#如果是第1层if level == 1:
# self.stride_level_0通道调整为和level-1出来的特征图一样大小self.stride_level_0 = Conv(c1_l, self.inter_dim, 2, 2, 0)  # stride=2 下采样为2倍# 两个卷积为了学习权重self.weight_level_0 = Conv(self.inter_dim, compress_c, 1, 1)self.weight_level_1 = Conv(self.inter_dim, compress_c, 1, 1)
# 用于调整拼接后的两个权重的通道self.weights_levels = nn.Conv2d(compress_c * 2, 2, kernel_size=1, stride=1, padding=0)self.conv = Conv(self.inter_dim, self.inter_dim, 3, 1)def forward(self, x):x_level_0, x_level_1 = x[0], x[1]# 如果在第0层
# level-0出来的特征图保持不变
# 调整level-1的特征图,使得其channel、width、height与level-0一致if self.level == 0:level_0_resized = x_level_0level_1_resized = self.stride_level_1(x_level_1)
# 如果在第1层,同上elif self.level == 1:level_0_resized = self.stride_level_0(x_level_0)level_1_resized = x_level_1# 将N*C*H*W的level-0特征图卷积得到权重,权重level_0_weight_v:N*256*H*Wlevel_0_weight_v = self.weight_level_0(level_0_resized)level_1_weight_v = self.weight_level_1(level_1_resized)# 将各个权重矩阵按照通道拼接
# levels_weight_v:N*3C*H*Wlevels_weight_v = torch.cat((level_0_weight_v, level_1_weight_v), 1)# 将拼接后的矩阵调整,每个通道对应着不同的level_0_resized,level_1_resized的权重levels_weight = self.weights_levels(levels_weight_v)# 在通道维度,对权重做归一化,也就是对于二通道tmp:tmp[0][0]+tmp[1][0]=1levels_weight = F.softmax(levels_weight, dim=1)# 将levels_weight各个通道分别乘level_0_resized level_1_resized 
# 点乘用到了广播机制fused_out_reduced = level_0_resized * levels_weight[:, 0:1] + level_1_resized * levels_weight[:, 1:2]return self.conv(fused_out_reduced)# ASFF3的运算流程同上
class ASFF3(nn.Module):"""ASFF3 module for YOLO AFPN head https://arxiv.org/abs/2306.15988"""def __init__(self, c1, c2, level=0):super().__init__()c1_l, c1_m, c1_h = c1[0], c1[1], c1[2]self.level = levelself.dim = c1_l, c1_m, c1_hself.inter_dim = self.dim[self.level]compress_c = 8if level == 0:self.stride_level_1 = Upsample(c1_m, self.inter_dim)self.stride_level_2 = Upsample(c1_h, self.inter_dim, scale_factor=4)if level == 1:self.stride_level_0 = Conv(c1_l, self.inter_dim, 2, 2, 0)  # downsample 2xself.stride_level_2 = Upsample(c1_h, self.inter_dim)if level == 2:self.stride_level_0 = Conv(c1_l, self.inter_dim, 4, 4, 0)  # downsample 4xself.stride_level_1 = Conv(c1_m, self.inter_dim, 2, 2, 0)  # downsample 2xself.weight_level_0 = Conv(self.inter_dim, compress_c, 1, 1)self.weight_level_1 = Conv(self.inter_dim, compress_c, 1, 1)self.weight_level_2 = Conv(self.inter_dim, compress_c, 1, 1)self.weights_levels = nn.Conv2d(compress_c * 3, 3, kernel_size=1, stride=1, padding=0)self.conv = Conv(self.inter_dim, self.inter_dim, 3, 1)def forward(self, x):x_level_0, x_level_1, x_level_2 = x[0], x[1], x[2]if self.level == 0:level_0_resized = x_level_0level_1_resized = self.stride_level_1(x_level_1)level_2_resized = self.stride_level_2(x_level_2)elif self.level == 1:level_0_resized = self.stride_level_0(x_level_0)level_1_resized = x_level_1level_2_resized = self.stride_level_2(x_level_2)elif self.level == 2:level_0_resized = self.stride_level_0(x_level_0)level_1_resized = self.stride_level_1(x_level_1)level_2_resized = x_level_2level_0_weight_v = self.weight_level_0(level_0_resized)level_1_weight_v = self.weight_level_1(level_1_resized)level_2_weight_v = self.weight_level_2(level_2_resized)levels_weight_v = torch.cat((level_0_weight_v, level_1_weight_v, level_2_weight_v), 1)w = self.weights_levels(levels_weight_v)w = F.softmax(w, dim=1)fused_out_reduced = level_0_resized * w[:, :1] + level_1_resized * w[:, 1:2] + level_2_resized * w[:, 2:]return self.conv(fused_out_reduced)

具体如下图所示:

💥💥步骤2:修改yolo.py文件

修改yolo.py文件,在 parse_model函数中找到 elif m is Concat: 语句,在其后面加上下列代码:👇

        elif m is ASFF2:c1, c2 = [ch[f[0]], ch[f[1]]], args[0]c2 = make_divisible(c2 * gw, 8)args = [c1, c2, *args[1:]]elif m is ASFF3:c1, c2 = [ch[f[0]], ch[f[1]], ch[f[2]]], args[0]c2 = make_divisible(c2 * gw, 8)args = [c1, c2, *args[1:]]

具体如下图所示:

💥💥步骤3:创建自定义的yaml文件

models文件夹中复制yolov5s.yaml,粘贴并重命名为yolov5s_AFPN.yaml

yaml文件完整代码如下:

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license# Parameters
nc: 80  # 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 v6.1 backbone
backbone:# [from, repeats, module, args][[-1, 1, Conv, [64, 3, 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, 6, C3, [512]],[-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32[-1, 3, C3, [1024]],[-1, 1, SPPF, [1024, 5]],]  # 9# YOLOv5 v6.1 head
head:[[4, 1, Conv, [128, 1, 1]], # 10 downsample backbone P3[6, 1, Conv, [256, 1, 1]], # 11 downsample backbone P4[[10, 11], 1, ASFF2, [128, 0]], # 12[[10, 11], 1, ASFF2, [256, 1]], # 13[-2, 1, C3, [128, False]], # 14[-2, 1, C3, [256, False]], # 15[9, 1, Conv, [512, 1, 1]], # 16 downsample backbone P5[[14, 15, 16], 1, ASFF3, [128, 0]], # 17[[14, 15, 16], 1, ASFF3, [256, 1]], # 18[[14, 15, 16], 1, ASFF3, [512, 2]], # 19[17, 1, C3, [256, False]],  # 20 (P3/8-small)[18, 1, C3, [512, False]],  # 21 (P4/16-medium)[19, 1, C3, [1024, False]],  # 22 (P5/32-large)[[20, 21, 22], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)]

💥💥步骤4:验证是否加入成功

yolo.py文件里,配置我们刚才自定义的yolov5s_AFPN.yaml

然后运行yolo.py我运行时出现报错信息。 ❌

报错信息如图所示:

解决方法:

需要导入包

import torch.nn.functional as F

导入后,则报错消失。然后继续运行yolo.py,得到运行结果。

这样就算添加成功了。🎉🎉🎉  

我没有试验过这种方法效果如何,有实验过的小伙伴可以把效果在评论区打出来!我们共同讨论下!🍉 🍓 🍑 🍈 🍌 🍐 


相关文章:

YOLOv5算法改进(15)— 更换Neck之AFPN

前言:Hello大家好,我是小哥谈。在YOLOv5中添加AFPN(Adaptive Feature Pyramid Network)可以提高目标检测的准确性。AFPN是一种用于目标检测任务的功能增强模块,它能够自适应地融合来自不同层级的特征图,以提…...

Vue2项目练手——通用后台管理项目第七节

Vue2项目练手——通用后台管理项目 用户管理分页使用的组件Users.vuemock.js 关键字搜索区Users.vue 权限管理登录页面样式修改Login.vue 登录权限使用token对用户鉴,使用cookie对当前信息保存(类似localstorage)Login.vuerouter/index.js 登…...

《Web安全基础》04. 文件操作安全

web 1:文件操作安全2:文件上传漏洞2.1:简介2.2:防护与绕过2.3:WAF 绕过2.3.1:数据溢出2.3.2:符号变异2.3.3:数据截断2.3.4:重复数据 3:文件包含漏洞4&#xf…...

docker-compose安装nginx

基于docker-compose安装nginx 目录 一、目录结构 1、docker-compose.yml 2、nginx.conf 3、default.conf 4、index.html 二、访问测试 一、目录结构 1、docker-compose.yml version: 3 services:nginx:image: registry.cn-hangzhou.aliyuncs.com/zhengqing/nginx:1.21.1…...

报错处理:MySQL无法启动

报错环境: Linux MySQL 具体报错: Cant connect to local MySQL server through socket /var/run/mysqld/mysqld.sock 排错思路: 当尝试启动MySQL服务时,如果出现无法连接到MySQL服务的错误,可能是由于MySQL服务未正确…...

Vue中表单手机号验证与手机号归属地查询

下面是一篇关于Vue中如何进行表单手机号验证与手机号归属地查询的Markdown格式的文章,包含代码示例。 Vue中表单手机号验证与手机号归属地查询 手机号验证和归属地查询是许多Web应用程序中常见的功能之一。在Vue.js中,我们可以轻松地实现这两个功能。本…...

初高(重要的是高中)中数学知识点综合

1. 集合 1.1 集合的由来和确定性 确定对象构成的整体称为集合(组成集合的元素必须是确定的 ),每个集合内的对象个体成为元素(Element)。确定性: 给定一个集合,任何一个对象是不是这个集合内的元素,就已经确…...

Fiddler 系列教程(二) Composer创建和发送HTTP Request跟手机抓包

Fiddler Composer介绍 Composer的官方帮助文档:http://www.fiddler2.com/fiddler/help/composer.asp Fiddler的作者把HTTP Request发射器取名叫Composer(中文意思是:乐曲的创造者), 很有诗意 Fiddler Composer的功能就是用来创建HTTP Request 然后发送…...

淘宝平台开放接口API接口

淘宝平台开放接口API接口是指淘宝平台提供给第三方开发者的一组接口,用于实现与淘宝平台的数据交互和功能扩展。通过API接口,第三方开发者可以获取淘宝平台上的商品信息、订单信息、用户信息等数据,也可以实现商品的发布、订单的创建和支付等…...

缓存夺命连环问

1. 为什么要用缓存? 用缓存,主要有两个用途:高性能、高并发。 高性能 假设这么个场景,你有个操作,一个请求过来,吭哧吭哧你各种乱七八糟操作 MySQL,半天查出来一个结果,耗时 600m…...

模型生成自动化测试用例

自动产生的测试用例本就应该由程序自动执行,这其实也就是NModel推荐的模式。先回过头来看看文章中制作的模型,模型里面将登录、注销、用户名以及密码等要素都抽象出来了,而NModel是以这些抽象出来的动作(登录、注销)和…...

归并排序-面试例子

小数和问题 描述 在一个数组中,一个数左边比它小的数的总和,叫数的小和,所有数的小和累加起来,叫数组小和。求数组小和。 例子 5 2 6 1 7 小和原始的求法是:任何一个数左边比它小的数累加起来。 5左边比它小数累加…...

docker 生成镜像的几个问题

docker 生成镜像的几个问题 根据jdk8.tar.gz 打包Jdk8 镜像失败运行镜像报错差不多是网络ip错误,在网上说重启docker即可解决运行mysql5.7.25 镜像失败向daemon.json文件添加内容导致docker重启失败docker run 命令常用参数根据jdk8.tar.gz 打包Jdk8 镜像失败 首选做准备工作…...

云计算时代的采集利器

大家好!在今天的知识分享中,我们将探讨一个在云计算环境中的爬虫应用利器——独享IP。如果你是一名爬虫程序员,或者对数据采集和网络爬虫有浓厚的兴趣,那么这篇文章将向你展示独享IP在云计算环境下的应用价值。 1. 什么是独享IP&…...

【Unity编辑器扩展】| Inspector监视器面板扩展

前言【Unity编辑器扩展】| Inspector监视器面板扩展一、ContextMenu和ContextMenuItem二、Custom Editors 自定义编辑器三、Property Drawer 属性绘制器总结前言 前面我们介绍了Unity中编辑器扩展的一些基本概念及基础知识,还有编辑器扩展中用到的相关特性Attribute介绍。后面…...

Redis配置

关系型数据库和非关系型数据库 ①了解关系和非关系 关系型数据库 一个结构化的数据库,创建在关系模型基础上,一般面向于记录,包括Oracle、MySQL、SQL Server、Microsoft Access、DB2、postgreSQL等 非关系型数据库 除了主流的关系型数据库…...

CSDN每日一练 |『小艺照镜子』『Ctrl+X,Ctrl+V』『括号上色』2023-09-11

CSDN每日一练 |『小艺照镜子』『Ctrl+X,Ctrl+V』『括号上色』2023-09-11 一、题目名称:小艺照镜子二、题目名称:Ctrl+X,Ctrl+V三、题目名称:括号上色一、题目名称:小艺照镜子 时间限制:1000ms内存限制:256M 题目描述: 已知字符串str。 输出字符串str中最长回文串的长度…...

React 全栈体系(四)

第二章 React面向组件编程 六、组件的生命周期 1. 效果 需求:定义组件实现以下功能&#xff1a; 让指定的文本做显示 / 隐藏的渐变动画从完全可见&#xff0c;到彻底消失&#xff0c;耗时2S点击“不活了”按钮从界面中卸载组件 <!DOCTYPE html> <html lang"e…...

各种UI库使用总结

各种UI库使用总结 工作了这么年&#xff0c;使用了一些UI库&#xff0c;简单的总结一下&#xff0c;UI库也是五花八门&#xff0c;根据自己的产品&#xff0c;应用场景吧&#xff0c;没有绝对合适的&#xff0c;各有各的应用场景吧&#xff01; QT 这几年前后在一些嵌入式上…...

2023Web前端开发面试手册

​​​​​​​​ HTML基础 1. HTML 文件中的 DOCTYPE 是什么作用&#xff1f; HTML超文本标记语言: 是一个标记语言, 就有对应的语法标准 DOCTYPE 即 Document Type&#xff0c;网页文件的文档类型标准。 主要作用是告诉浏览器的解析器要使用哪种 HTML规范 或 XHTML规范…...

一文了解数据科学Notebook

编者按&#xff1a; 主要介绍什么是Notebook&#xff0c;Notebook在数据科学领域的应用的重要性与优势&#xff0c;以及数据科学家/算法团队在选择Notebook时需考虑哪些关键因素。同时&#xff0c;基于Notebook的筛选考量维度&#xff0c;对常见的Notebook进初步对比分析&#…...

2020年12月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:数组指定部分逆序重放 将一个数组中的前k项按逆序重新存放。例如,将数组8,6,5,4,1前3项逆序重放得到5,6,8,4,1。 时间限制:1000 内存限制:65536 输入 输入为两行: 第一行两个整数,以空格分隔,分别为数组元素的个数n(1 < n…...

关于ChatGPT的个人的一些观点

问题 1 Q: 你认为ChatGPT是一款非常有用的工具吗&#xff1f; A: 我认为ChatGPT是一款非常有用的工具。它可以帮助人们解决各种问题&#xff0c;包括技术问题、心理问题、生活问题等等。同时&#xff0c;ChatGPT也可以成为人们分享想法和交流的平台&#xff0c;增强人与人之间…...

Solidity 小白教程:13. 继承

Solidity 小白教程&#xff1a;13. 继承 这一讲&#xff0c;我们介绍solidity中的继承&#xff08;inheritance&#xff09;&#xff0c;包括简单继承&#xff0c;多重继承&#xff0c;以及修饰器&#xff08;modifier&#xff09;和构造函数&#xff08;constructor&#xff…...

队列(Queue)的顶级理解

目录 1.队列(Queue) 的概念 2.单链表模拟实现队列 2.1创建队列 2.2入队列 2.3判断是否为空 2.4出队列 2.5获取队头元素 2.6完整代码&#xff1a; 2.7双向链表模拟实现队列代码 3.数组模拟实现队列代码 3.1创建队列 3.2判断是否为满 3.3检查是否为空 3.4插入元素 3…...

选择 Guava EventBus 还是 Spring Framework ApplicationEvent

文章首发地址 Spring Framework ApplicationEvent Spring Framework 的 ApplicationEvent 是 Spring 框架提供的一种事件机制&#xff0c;用于实现发布和订阅事件的功能。它基于观察者模式&#xff0c;允许应用程序内的组件之间进行松耦合的通信。 下面是关于 Spring Frame…...

Linux下go环境安装、环境配置并执行第一个go程序

一、安装 1.Golang对Linux的内核版本要求 GO对Linux内核版本最低要求是 2.6.23&#xff0c;对应要求操作系统版本是&#xff1a; RHEL 6.0CentOS 6.0即&#xff0c;不支持 (RHEL 和 CentOS) 的 (4.x or 5.x)。2.下载golang的代码版本 Golang的官网下载地址&#xff1a;https:…...

自定义Dynamics 365实施和发布业务解决方案 - 5. 高级自定义

本章的目的是探索可应用于Dynamics365的高级自定义。这包括使用插件和自定义工作流活动实现复杂的业务流程。此外,您还将了解如何使用SPKL任务运行器来部署这些,这在第2章中进行了讨论。最后,您还将看到使用Web API查询数据。 准备工作 若要从高级自定义开始,必须首先创建…...

软件测试下的AI之路(2)

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…...

前端面试的话术集锦第 7 篇:高频考点(浏览器渲染原理 安全防范)

这是记录前端面试的话术集锦第七篇博文——高频考点(浏览器渲染原理 & 安全防范),我会不断更新该博文。❗❗❗ 1. 浏览器渲染原理 注意:该章节都是⼀个⾯试题。 1.1 渲染过程 1.1.1 浏览器接收到HTML⽂件并转换为DOM树 当我们打开⼀个⽹⻚时,浏览器都会去请求对应的…...

如何用手机做钓鱼网站/五种常用的网站推广方法

前言 今年上半年其实就已经有了换工作的想法,奈何疫情原因和岗位缩减&#xff0c;加之信心不足&#xff0c;到六月底投递了百度的Android岗位,本以为像我这种非211、985没工作经验的渣渣只能被直接pass,结果却意外的收到了电话,真是受宠若惊.经过电面,技术三面,然后就是等通知…...

网站建设及域名/如何写软文推广产品

根据SqlServer2000 Analysis Services提供的帮助材料展开&#xff0c;略作说明并且根据各个函数的侧重点编写相应的MDX&#xff1b;这些成果主要源于我的老大浩哥&#xff0c;再次向他表示感谢。数组函数 函数 描述 SetToArray 将一个或多个集合转换为数组&#xff0c;以用于…...

深圳好的网站建设公司/网络外包

ospf全称&#xff1a;OSPF ( Open Shortest Path First )开放式最短路径优先OSPF 知识点&#xff1a;OSPF 基本配置&#xff0c;OSPF 5 种报文 &#xff0c;7种邻居状态&#xff0c;4 种网络类型&#xff0c;4 种特殊区域&#xff0c;7类LSA&#xff0c;4 种 link type&#xf…...

建设公司网站/一个新品牌怎样营销推广

直接赋值&#xff1a;其实就是对象的引用(别名&#xff0c;其实就是一个人今天叫张三 明天叫张狗子的意思)。浅拷贝(copy)&#xff1a;拷贝父对象&#xff0c;不会拷贝对象的内部的子对象。深拷贝(deepcopy)&#xff1a; copy 模块的 deepcopy 方法&#xff0c;完全拷贝了父对象…...

重庆丰都建设局网站/360开户推广

转自&#xff1a;https://sherlockliao.github.io/2017/05/01/git/ 平时使用git老是要去查找用法&#xff0c;十分不方便&#xff0c;于是决定写一篇文章记录一下git里面常用的命令&#xff0c;持续更新。 git init 将目录变成git repository git add readme.txt 添加readme.t…...

电商网站建设与管理 教案/淘宝怎么设置关键词搜索

小编典典尝试使用以下Dockerfile进行构建。FROM my/baseWORKDIR /srvADD ./requirements.txt /srv/requirements.txtRUN pip install -r requirements.txtADD . /srvRUN python setup.py installENTRYPOINT ["run_server"]如果.(您的项目)有某些更改&#xff0c;则do…...