YOLOv8改进 | TripletAttention三重注意力机制(附代码+机制原理+添加教程)

一、本文介绍

本文给大家带来的改进是Triplet Attention三重注意力机制。这个机制,它通过三个不同的视角来分析输入的数据,就好比三个人从不同的角度来观察同一幅画,然后共同决定哪些部分最值得注意。三重注意力机制的主要思想是在网络中引入了一种新的注意力模块,这个模块包含三个分支,分别关注图像的不同维度。比如说,一个分支可能专注于图像的宽度,另一个分支专注于高度,第三个分支则聚焦于图像的深度,即色彩和纹理等特征。这样一来,网络就能够更全面地理解图像内容,就像是得到了一副三维眼镜,能够看到图片的立体效果一样。

 推荐指数:⭐⭐⭐

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备    

训练结果对比图->  

这次试验我用的数据集大概有七八百张照片训练了150个epochs,虽然没有完全拟合但是效果只能说一般吧,所以大家可以进行尝试毕竟不同的数据集上效果也可能差很多。

目录

一、本文介绍

二、Triplet Attention机制原理

2.1 Triplet Attention的基本原理 

2.2 Triplet Attention和其它简单注意力机制的对比 

2.3 Triplet Attention的实现流程

三、Triplet Attention的完整代码

3.1 Triplet Attention的核心代码

3.2 修改了Triplet Attention机制的C2f和Bottleneck 

四、手把手教你添加Triplet Attention

4.1 Triplet Attention的添加教程

4.2 Triplet Attention的yaml文件和训练截图

4.2.1 Triplet Attention的yaml文件一(推荐)

4.2.2 Triplet Attention的yaml文件二

4.2.2 D-LKA的训练过程截图 

五、Triplet Attention可添加的位置

5.1 推荐Triplet Attention可添加的位置 

5.2 图示D-LKA可添加的位置 

六、本文总结


二、Triplet Attention机制原理

论文地址:官方论文地址

代码地址:官方代码地址


2.1 Triplet Attention的基本原理 

三重注意力(Triplet Attention)的基本原理是利用三支结构捕获输入数据的跨维度交互,从而计算注意力权重。这个方法能够构建输入通道或空间位置之间的相互依赖性,而且计算代价小。三重注意力由三个分支组成,每个分支负责捕获空间维度H或W与通道维度C之间的交互特征。通过对每个分支中的输入张量进行排列变换,然后通过Z池操作和一个大小为k×k的卷积层,生成注意力权重。这些权重是通过一个S形激活层生成的,然后应用于排列变换后的输入张量,再变换回原来的输入形状 

三重注意力(Triplet Attention)的主要改进点包括:

  1. 跨维度的注意力权重计算: 通过一个创新的三支结构捕获通道、高度、宽度三个维度之间的交互关系来计算注意力权重。

  2. 旋转操作和残差变换: 通过旋转输入张量和应用残差变换来建立不同维度间的依赖,这是三重注意力机制中的关键步骤。

  3. 维度间依赖性的重要性: 强调在计算注意力权重时,捕获跨维度依赖性的重要性,这是三重注意力的核心直觉和设计理念。

下面的图片是三重注意力的一个抽象表示图,展示了三个分支如何捕获跨维度交互。图中的每个子图表示三重注意力中的一个分支: 

1. 分支(a): 这个分支直接处理输入张量,没有进行旋转,然后通过残差变换来提取特征。

2. 分支(b): 这个分支首先沿着宽度(W)和通道(C)的维度旋转输入张量,然后进行残差变换。

3. 分支(c): 这个分支沿着高度(H)和通道(C)的维度旋转输入张量,之后同样进行残差变换。

总结:通过这样的设计,三重注意力模型能够有效地捕获输入张量中的空间和通道维度之间的交互关系。这种方法使模型能够构建通道与空间位置之间的相互依赖性,提高模型对特征的理解能力。


2.2 Triplet Attention和其它简单注意力机制的对比 

下面的图片是论文中三重注意力机制和其它注意力机制的一个对比大家有兴趣可以看看,横向扩展以下自己的知识库。

这张图片是一幅对比不同注意力模块的图示,其中包括:

1.Squeeze Excitation (SE) Module:
这个模块使用全局平均池化 (Global Avg Pool) 生成通道描述符,接着通过两个全连接层(1x1 Conv),中间使用ReLU激活函数,最后通过Sigmoid函数生成每个通道的权重。

2. Convolutional Block Attention Module (CBAM):
首先使用全局平均池化和全局最大池化(GAP + GMP)结合,再通过一个卷积层和ReLU激活函数,最后经过另一个卷积层和Sigmoid函数生成注意力权重。

3. Global Context (GC) Module:
从一个1x1卷积层开始,经过Softmax函数进行归一化,接着进行另一个1x1卷积,然后使用LayerNorm和最终的1x1卷积,通过广播加法结合原始特征图。

4. Triplet Attention (我们的方法):
分为三个分支,每个分支进行不同的处理:通道池化后的7x7卷积,Z池化,再接一个7x7卷积,然后是批量归一化和Sigmoid函数。每个分支都有一个Permute操作来调整维度。最后,三个分支的结果通过平均池化聚合起来生成最终的注意力权重。

每种模块都设计用于处理特征图(C x H x W),其中C是通道数,H是高度,W是宽度。这些模块通过不同方式计算注意力权重,增强网络对特征的重要部分的关注度,从而在各种视觉任务中提高性能。图片中的符号⊗代表矩阵乘法,⊕代表广播元素级加法。


2.3 Triplet Attention的实现流程

下面的图片是三重注意力(Triplet Attention)的具体实现流程图。图中详细展示了三个分支如何处理输入张量,并最终合成三重注意力。下面是对这个过程的描述: 

  1. 上部分支: 负责计算通道维度C和空间维度W的注意力权重。这个分支对输入张量进行Z池化(Z-Pool)操作,然后通过一个卷积层(Conv),接着用Sigmoid函数生成注意力权重。

  2. 中部分支: 负责捕获通道维度C与空间维度H和W之间的依赖性。这个分支首先进行相同的Z池化和卷积操作,然后同样通过Sigmoid函数生成注意力权重。

  3. 下部分支: 用于捕获空间维度之间的依赖性。这个分支保持输入的身份(Identity,即不改变输入),执行Z池化和卷积操作,之后也通过Sigmoid函数生成注意力权重。

每个分支在生成注意力权重后,会对输入进行排列(Permutation),然后将三个分支的输出进行平均聚合(Avg),最终得到三重注意力输出。

这种结构通过不同的旋转和排列操作,能够综合不同维度上的信息,更好地捕获数据的内在特征,同时这种方法在计算上是高效的,并且可以作为一个模块加入到现有的网络架构中,增强网络对复杂数据结构的理解和处理能力。


三、Triplet Attention的完整代码

3.1 Triplet Attention的核心代码

大家复制代码的时候需要注意这是一种无参数的注意力机制,所以在看第四章添加教程的时候需要按照无参数的注意力机制进行添加。 

class BasicConv(nn.Module):def __init__(self, in_planes, out_planes, kernel_size, stride=1, padding=0, dilation=1, groups=1, relu=True,bn=True, bias=False):super(BasicConv, self).__init__()self.out_channels = out_planesself.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=padding,dilation=dilation, groups=groups, bias=bias)self.bn = nn.BatchNorm2d(out_planes, eps=1e-5, momentum=0.01, affine=True) if bn else Noneself.relu = nn.ReLU() if relu else Nonedef forward(self, x):x = self.conv(x)if self.bn is not None:x = self.bn(x)if self.relu is not None:x = self.relu(x)return xclass ZPool(nn.Module):def forward(self, x):return torch.cat((torch.max(x, 1)[0].unsqueeze(1), torch.mean(x, 1).unsqueeze(1)), dim=1)class AttentionGate(nn.Module):def __init__(self):super(AttentionGate, self).__init__()kernel_size = 7self.compress = ZPool()self.conv = BasicConv(2, 1, kernel_size, stride=1, padding=(kernel_size - 1) // 2, relu=False)def forward(self, x):x_compress = self.compress(x)x_out = self.conv(x_compress)scale = torch.sigmoid_(x_out)return x * scaleclass TripletAttention(nn.Module):def __init__(self, no_spatial=False):super(TripletAttention, self).__init__()self.cw = AttentionGate()self.hc = AttentionGate()self.no_spatial = no_spatialif not no_spatial:self.hw = AttentionGate()def forward(self, x):x_perm1 = x.permute(0, 2, 1, 3).contiguous()x_out1 = self.cw(x_perm1)x_out11 = x_out1.permute(0, 2, 1, 3).contiguous()x_perm2 = x.permute(0, 3, 2, 1).contiguous()x_out2 = self.hc(x_perm2)x_out21 = x_out2.permute(0, 3, 2, 1).contiguous()if not self.no_spatial:x_out = self.hw(x)x_out = 1 / 3 * (x_out + x_out11 + x_out21)else:x_out = 1 / 2 * (x_out11 + x_out21)return x_out


3.2 修改了Triplet Attention机制的C2f和Bottleneck 

这个机制可以直接使用在主干上,也可以用在残差中也就是下面这个代码具体那种看你自己选择,同时大家也可以放在其他的位置即插即用。 

class Bottleneck_TripletAt(nn.Module):"""Standard bottleneck."""def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):"""Initializes a bottleneck module with given input/output channels, shortcut option, group, kernels, andexpansion."""super().__init__()c_ = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, c_, k[0], 1)self.cv2 = Conv(c_, c2, k[1], 1, g=g)self.TripleAt = TripletAttention()self.add = shortcut and c1 == c2def forward(self, x):"""'forward()' applies the YOLO FPN to input data."""return x + self.TripleAt(self.cv2(self.cv1(x))) if self.add else self.TripleAt(self.cv2(self.cv1(x)))class C2f_TripletAt(nn.Module):"""Faster Implementation of CSP Bottleneck with 2 convolutions."""def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):"""Initialize CSP bottleneck layer with two convolutions with arguments ch_in, ch_out, number, shortcut, groups,expansion."""super().__init__()self.c = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, 2 * self.c, 1, 1)self.cv2 = Conv((2 + n) * self.c, c2, 1)  # optional act=FReLU(c2)self.m = nn.ModuleList(Bottleneck_TripletAt(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))def forward(self, x):"""Forward pass through C2f layer."""y = list(self.cv1(x).chunk(2, 1))y.extend(m(y[-1]) for m in self.m)return self.cv2(torch.cat(y, 1))def forward_split(self, x):"""Forward pass using split() instead of chunk()."""y = list(self.cv1(x).split((self.c, self.c), 1))y.extend(m(y[-1]) for m in self.m)return self.cv2(torch.cat(y, 1))


四、手把手教你添加Triplet Attention

4.1 Triplet Attention的添加教程

添加教程这里不再重复介绍、因为专栏内容有许多,添加过程又需要截特别图片会导致文章大家读者也不通顺如果你已经会添加注意力机制了,可以跳过本章节,如果你还不会,大家可以看我下面的文章,里面详细的介绍了拿到一个任意机制(C2f、Conv、Bottleneck、Loss、DetectHead)如何添加到你的网络结构中去。

这里需要注意的是我上面提供了两段代码一个是C2f-Triplet Attention一个是Triplet Attention的本体代码,这两种方法的添加方式有些不同。

最后强调一下Triplet Attention是一种无参数的注意力机制如果你想要放在主干上就按照无参数的注意力机制配置就可以,但是如果你想要放在残差中配置C2f的时候就需要按照C2f的配置来添加。

添加教程->YOLOv8改进 | 如何在网络结构中添加注意力机制、C2f、卷积、Neck、检测头


4.2 Triplet Attention的yaml文件和训练截图

4.2.1 Triplet Attention的yaml文件一(推荐)

下面的配置文件为我修改的C2f-Triplet Attention的位置(上面的实验结果图三是用这个方法跑出来的)。

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# 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 GFLOPss: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPsm: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPsl: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPsx: [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, Conv, [64, 3, 2]]  # 0-P1/2- [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4- [-1, 3, C2f, [128, True]]- [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8- [-1, 6, C2f, [256, True]]- [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16- [-1, 6, C2f, [512, True]]- [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32- [-1, 3, C2f, [1024, True]]- [-1, 1, SPPF, [1024, 5]]  # 9# YOLOv8.0n head
head:- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 6], 1, Concat, [1]]  # cat backbone P4- [-1, 3, C2f, [512]]  # 12- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 4], 1, Concat, [1]]  # cat backbone P3- [-1, 3, C2f_TripletAt, [256]]  # 15 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 12], 1, Concat, [1]]  # cat head P4- [-1, 3, C2f_TripletAt, [512]]  # 18 (P4/16-medium)- [-1, 1, Conv, [512, 3, 2]]- [[-1, 9], 1, Concat, [1]]  # cat head P5- [-1, 3, C2f_TripletAt, [1024]]  # 21 (P5/32-large)- [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)


4.2.2 Triplet Attention的yaml文件二

这个文件是另一种添加的方式,添加的位置是检测头和Neck中间的位置,对应实验结果的图二(中间)。

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# 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 GFLOPss: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPsm: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPsl: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPsx: [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, Conv, [64, 3, 2]]  # 0-P1/2- [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4- [-1, 3, C2f, [128, True]]- [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8- [-1, 6, C2f, [256, True]]- [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16- [-1, 6, C2f, [512, True]]- [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32- [-1, 3, C2f, [1024, True]]- [-1, 1, SPPF, [1024, 5]]  # 9# YOLOv8.0n head
head:- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 6], 1, Concat, [1]]  # cat backbone P4- [-1, 3, C2f, [512]]  # 12- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 4], 1, Concat, [1]]  # cat backbone P3- [-1, 3, C2f, [256]]  # 15 (P3/8-small)- [-1, 1, TripletAttention, []] # 16- - [-1, 1, Conv, [256, 3, 2]]- [[-1, 12], 1, Concat, [1]]  # cat head P4- [-1, 3, C2f, [512]]  # 19 (P4/16-medium)- [-1, 1, TripletAttention, []] # 20- - [-1, 1, Conv, [512, 3, 2]]- [[-1, 9], 1, Concat, [1]]  # cat head P5- [-1, 3, C2f, [1024]]  # 23 (P5/32-large)- [-1, 1, TripletAttention, []] # 24- - [[16, 20, 24], 1, Detect, [nc]]  # Detect(P3, P4, P5)


4.2.2 D-LKA的训练过程截图 

下面是添加了D-LKA的训练截图。

(最近有人说我改的代码是没有发全的,我不知道这群人是怎么说出这种话的,希望大家如果用我的代码成功的可以在评论区支持一下,我也好发更多的改进毕竟免费给大家看。同时有问题皆可在评论区留言我看到都会回复) 

大家可以看下面的运行结果和添加的未知所以不存在我发的代码不全或者运行不了的问题大家有问题也可以在评论区评论我看到都会为大家解答(我知道的)。

​​​​​


五、Triplet Attention可添加的位置

5.1 推荐Triplet Attention可添加的位置 

Triplet Attention是一种即插即用的模块,其可以添加的位置有很多,添加的位置不同效果也不同,所以我下面推荐几个添加的位,置大家可以进行参考,当然不一定要按照我推荐的地方添加。

  1. 残差连接中:在残差网络的残差连接中加入Triplet Attention(yaml文件一)。

  2. Neck部分:YOLOv8的Neck部分负责特征融合,这里添加修改后的C2f_Triplet Attention可以帮助模型更有效地融合不同层次的特征(yaml文件二)

文字大家可能看我描述不太懂,大家可以看下面的网络结构图中我进行了标注。


5.2 图示D-LKA可添加的位置 

2949694815404620bdfb5875286c8e73.png​​​​​


六、本文总结

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

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备

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

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

相关文章

C陷阱与缺陷——第6章 预处理器

在严格意义上的编译过程开始之前,C语言预处理器首先对程序代码做了必要的转换处理。预处理器的主要作用是: 我们有时需要将某个特定数量在程序中出现的所有实例统统加以修改大多数C语言实现在函数调用时都会带来重大的系统开销 1. 不能忽视宏定义中的空…

Kontakt v7.7.2(音频采样器)

Native Instruments Kontakt 7是一款强大的软件采样器,它允许用户从各种来源采样音频并进行编辑和处理。它包含大量预设采样库,包括乐器、合成器、鼓组和声音效果等。此外,Kontakt 7还允许用户创建自己的采样库,以便根据自己的需要…

电脑版的便签软件使用哪一款?

您会选择使用电脑便签软件吗?很多人在日常工作及生活中会选择用电脑便签来督促自己按时完成工作任务,而且选择电脑便签是一个难题,毕竟当前电脑便签类工具非常多,如果想要找一款功能比较强大且又简单易用的便签工具,那…

HarmonyOS学习--创建和运行Hello World

创建和运行Hello World 打开DevEco Studio,在欢迎页单击Create Project,创建一个新工程。根据工程创建向导,选择创建Application应用或Atomic Service元服务。选择“Empty Ability”模板,然后单击Next。关于工程模板的介绍和支持…

A股股票交易费用

A股股票交易费用如下: 经手费:(上证/深证)按成交额双边收取0.0487‰,交给交易所。 监管费:(深证)按成交额双边收取0.02‰,交易所代收,交给证监会。 证管费&…

QGraphicsView实现简易地图7『异步加载-多瓦片-无底图』

前文链接:QGraphicsView实现简易地图6『异步加载-单瓦片-无底图』 前一篇文章提到的异步单瓦片加载,是指线程每准备好一个瓦片数据后,立刻抛出信号让主线程加载。而本篇异步多瓦片加载是指线程准备好所有瓦片数据后,一起抛出信号让…

将文件夹中所有文件名取出

dir C:\Users\是啊\Desktop\实验五/b>C:\Users\是啊\Desktop\1111.xls C:\Users\是啊\Desktop\实验五(这个是文件夹路径) /b (参数) C:\Users\是啊\Desktop\1111.xls(文件名输出的文件路径)

用VR+科普点亮科技之光VR航天科普体验巡展

11月22日至26日,第十一届中国(绵阳)科技城国际科技博览会圆满闭幕。本届科博会以“科技引领创新转化开放合作”为主题,创新办展办会模式,搭建高能级科技合作交流平台,展示了国内外科技创新发展成就和最新成果,举办了多…

内核无锁队列kfifo

文章目录 1、抛砖引玉2、内核无锁队列kfifo2.1 kfifo结构2.2 kfifo分配内存2.3 kfifo初始化2.4 kfifo释放2.5 kfifo入队列2.6 kfifo出队列2.7 kfifo的判空和判满2.8 关于内存屏障 1、抛砖引玉 昨天遇到这样一个问题,有多个生产者,多个消费者&#xff0c…

【从零认识ECS云服务器 | 快速上线个人网站】二、使用ECS云服务器

第二章 使用ECS 2.1 获取ECS 方式一:通过试用中心免费领取ECS实例 满足以下全部条件的阿里云用户,可免费试用云服务器ECS: 阿里云注册会员用户并完成阿里云企业认证或个人认证用户。申请用户是云服务器ECS产品的新用户,可以申…

查询不用order by时结果默认怎么排序

总结: 如果在使用没有指定order by,那么基本上依赖于底层实现的,具体排序规则不定,所以排序的顺序也不固定,可能会随着时间发生变化。 在实际工作中,如果有查询列表展示数据的功能和需求,开发前一定要先确…

Linux 进程地址空间

文章目录 进程地址空间进程地址空间结构页表虚拟内存写时拷贝 进程地址空间 进程地址空间难以定义,因为它更像是一个中间件。 程序从磁盘中加载到内存,程序的执行需要硬件资源,所以每个程序启动时会创建至少一条进程,进程作为组…

HarmonyOS 修改App的默认加载的界面(ArkTS版本)(十七)

根据鸿蒙系统APP的应用生命周期结构(鸿蒙4.0开发笔记之ArkTS语法基础之应用生命周期)来看。 1、首先在roject/entry/src/main/ets/entryability/EntryAbility.ts文件中找到UI加载函数:onWindowStageCreate(…){…},然后找到windo…

力扣100 相同的数(两种解法)

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p [1,2,3], q [1,2,3] 输出:true 示例 2&…

【数据分享】11个城市的出租车(网约车)数据(免费获取)

出租车(网约车)GPS数据是我们最常使用的交通大数据之一,但是出租车(网约车)GPS数据没有公开的获取渠道,有些学者可能能通过与相关机构合作拿到数据,但是对于绝大多数普通人是没有这个机会的&…

【理解ARM架构】中断处理 | CPU模式

🐱作者:一只大喵咪1201 🐱专栏:《理解ARM架构》 🔥格言:你只管努力,剩下的交给时间! 目录 🍜中断🍨GPIO中断代码实现 🍜CPU🍨CONTROL…

2024王道考研计算机组成原理——存储系统

微信打开的时候会有一个人站在地球上,这个过程就是把程序从辅存转移到主存,数据只有调入主存当中才可以被CPU访问 cache:主存速度还是慢,为了进一步缓解CPU和主存之间的速度矛盾 在微信打视频聊天的时候,在这一段比较…

弘扬中华文化 感受戏曲魅力——安徽演艺小分队赴和田交流演出

为进一步弘扬中华优秀传统文化,促进皖和两地交往交流交融,12月2日,安徽省演艺小分队走进和田新夜市登台演出,黄梅戏、独唱、民乐演奏、杂技等丰富多样的表演,为观众们送上了一场文化盛宴。 安徽演艺小分队赴和田交流演…

一篇文章带你详细了解C++智能指针

一篇文章带你详细了解C智能指针 为什么要有智能指针内存泄漏1.什么是内存泄漏,它的危害是什么2.内存泄漏的分类3.如何避免内存泄漏 智能指针的使用及原理1.RAII2.智能指针的原理3.auto_ptr4.unique_ptr5.shared_ptr6.weak_ptr 为什么要有智能指针 C引入智能指针的主…

WindowsServer服务器系列:定时备份 MySQL

一、编写脚本 echo 取日期、时间变量值 set yy%date:~0,4% set mm%date:~5,2% set dd%date:~8,2% if /i %time:~0,2% lss 10 set hh0%time:~1,1% if /i %time:~0,2% geq 10 set hh%time:~0,2% set mn%time:~3,2% set ss%time:~6,2% set date%yy%%mm%%dd% set time%hh%%mn%%ss…