论文阅读笔记(通道注意力)

论文阅读笔记(通道注意力)

  • 摘要
  • Abstract
  • 1. SENet
    • 1.1 研究背景
    • 1.2 创新点
    • 1.3 SE块的构建过程
      • 1.3.1 注意力和门机制
      • 1.3.2 SE块具体运行过程
      • 1.3.3 通道间依赖关系的提取
      • 1.3.4 自适应重新校正(Excitation)
    • 1.4 SE结合先进架构的灵活应用
    • 1.5 实验
    • 1.6 模型的实现
    • 1.7 结论
  • 2. SE-Resnet50 代码实现
  • 总结

摘要

本周阅读了 Squeeze-and-Excitation Networks 这篇文献,该文献提出了SENet架构,SENet(Squeeze-and-Excitation Networks)是一种深度学习架构,它通过引入注意力机制来增强卷积神经网络(CNN)的特征学习能力。其核心是SE模块,它通过显式地建模特征通道之间的相互依赖关系,使网络能够自适应地调整每个通道的响应。SE模块通过学习每个特征通道的重要性权重,然后根据这些权重对特征进行重标定,从而提升有用的特征并抑制无关的特征。本文将详细介绍SENet架构。

Abstract

This week read the paper Squeeze-and-Excitation Networks, which proposes the SENet architecture, a deep learning architecture that enhances the feature learning of Convolutional Neural Networks (CNNs) by introducing an attention mechanism to enhance their feature learning capability. At its core is the SE module, which enables the network to adaptively adjust the response of each channel by explicitly modeling the interdependencies between feature channels.The SE module enhances useful features and suppresses irrelevant features by learning the importance weights of each feature channel and then recalibrating the features according to these weights. In this paper, we describe the SENet architecture in detail.

论文出处:Squeeze-and-Excitation Networks

1. SENet

1.1 研究背景

卷积神经网络(CNN)已被证明是处理各种视觉任务的有效模型。 对于每个卷积层,学习一组滤波器来表达沿输入通道的局部空间连接模式。卷积滤波器有望通过在局部感受野内将空间和通道信息融合在一起而成为信息组合。 通过堆叠一系列与非线性和下采样交错的卷积层,CNN 能够捕获具有全局感受野的分层模式作为强大的图像描述。

在本文中,作者通过引入一个新的架构单元(我们将其称为“挤压和激励”(SE)块)来研究架构设计的另一个方面 - 通道关系。作者提出了一种允许网络执行特征重新校准的机制,通过该机制它可以学习使用全局信息来选择性地强调信息丰富的特征并抑制不太有用的特征。通过简单地堆叠一组 SE 构建块就可以生成 SE 网络。 SE 块还可以用作架构中任何深度的原始块的直接替代品。

最后一届ImageNet 2017竞赛 Image Classification任务的冠军.作者采用SENet block和ResNeXt结合在ILSVRC 2017的分类项目中拿到第一,在ImageNet数据集上将top-5 error降低到2.251%,原先的最好成绩是2.991%。

1.2 创新点

SENet的核心思想是通过网络根据损失函数学习特征权重,使得有效的特征图(feature map)权重更大,而对当前任务效果较小或无效的特征图权重减小。以下便是这篇文献的创新点:

  1. SENet引入了SE模块,该模块嵌入到现有的分类网络中,通过显式地建模特征通道之间的相互依赖关系来提升网络性能。
  2. SE模块中的Squeeze操作通过全局平均池化(Global Average Pooling)将每个特征通道压缩成一个实数,这个实数具有全局感受野,使得网络能够捕捉全局上下文信息。
  3. SENet在多个视觉任务和数据集上展示了其有效性,例如在ImageNet和COCO数据集上取得优异的性能,同时在ILSVRC 2017竞赛中获得分类任务第一名。

1.3 SE块的构建过程

在这里插入图片描述
对于任何给定的变换(例如卷积或一组卷积)
在这里插入图片描述
我们可以构造一个相应的SE块来执行特征重新校准(对变换完了的新特征进行重新校准)。如图所示。执行步骤如下:

  1. 特征U首先通过squeeze操作,该操作跨越空间维度W×H聚合特征映射来产生通道描述符(也就是聚合一张Fm)。这个描述符嵌入了通道特征响应的全局分布(对一张Fm的描述),使来自网络全局感受野的信息能够被其较低层利用(指这个模块的较底层部分,就是一提取完就给最近的层用)。
  2. 这之后是一个excitation(激励)操作,其中通过基于通道依赖性的自门机制为每个通道学习特定采样的激活,控制每个通道的激励。
  3. 然后特征映射U被重新加权以生成SE块的输出,然后可以将其直接输入到随后的层中。

SE网络可以通过简单地堆叠SE构建块的集合来生成。SE块也可以用作架构中任意深度的原始块的直接替换。然而,虽然构建块的模板是通用的,正如我们6.3节中展示的那样,但它在不同深度的作用适应于网络的需求。

SE块在网络不同部分的作用有所不同:

  1. 在前面的层中,它学习以类不可知的方式激发信息特征,增强共享的较低层表示的质量。
  2. 在后面的层中,SE块越来越专业化,并以高度类特定的方式响应不同的输入。

因此,SE块进行特征重新校准的好处可以通过整个网络进行累积。

1.3.1 注意力和门机制

从广义上讲,可以将注意力视为一种工具,将可用处理资源的分配偏向于输入信号的信息最丰富的组成部分。这种机制的发展和理解一直是神经科学社区的一个长期研究领域,并且近年来作为一个强大补充,已经引起了深度神经网络的极大兴趣。注意力已经被证明可以改善一系列任务的性能,从图像的定位和理解到基于序列的模型。它通常结合门函数(例如softmax或sigmoid)和序列技术来实现。(Highway Networks)高速网络[36]采用门机制来调节快捷连接,使得可以学习非常深的架构。王等人[42]受到语义分割成功的启发,引入了一个使用沙漏模块[27]的强大的trunk-and-mask注意力机制。这个高容量的单元被插入到中间阶段之间的深度残差网络中。

相比之下,作者提出的SE块是一个轻量级的门机制,专门用于以计算有效的方式对通道关系进行建模,并设计用于增强整个网络中模块的表示能力。

1.3.2 SE块具体运行过程

Squeeze-and-Excitation块是一个计算单元,可以为任何给定的变换构建(就是给某个变换结束了,对它产生的结果进行一个处理)。

为了简化说明,在接下来的表示中,我们将Ftr看作一个标准的卷积算子。V=[v1,v2,…,vC]表示学习到的一组滤波器核,vc指的是第c个滤波器的参数。然后我们可以将Ftr的输出写作U=[u1,u2,…,uC],其中
在这里插入图片描述
这里∗表示卷积,vc=[v1c,v2c,…,vC′c],X=[x1,x2,…,xC′](为了简洁表示,忽略偏置项)。这里vsc是2D空间核,因此表示vc的一个单通道,作用于对应的通道X。Uc表示输出的第C个通道的Fm,Vc代表在输入的第C个通道上使用的卷积核,Vsc代表该卷积核对应输入的某个通道的2D空间核。

从上式不难知道输出的某个Fm是通过所有通道的和来产生的,所以通道依赖性(这里指的通道依赖性指的是上一批通道,也就是输入信号的那批通道,后面我们处理的是后面一批通道)被隐式地嵌入到vc中,而vc是滤波器(卷积核),它的作用是捕获图片像素点的空间相关性,所以我们说通道间的依赖性与滤波器捕获的空间相关性是纠缠在一起的。

1.3.3 通道间依赖关系的提取

输出特征中每个通道的信号:要找通道间信号的关系,先把他们输出。

问题:

每个通道在这里是指刚刚输出的每张Fm,所以,输出每个通道信息就是说输出每张Fm,而Fm上有很多像素点,这些像素点都是由上一步的局部感受野处理得到的,没有哪个像素点可以代表整个通道(Fm):

每个学习到的滤波器都对局部感受野进行操作,因此变换输出U的每个单元(每张Fm)都无法利用该区域之外的上下文信息。在网络较低的层次上其感受野尺寸很小,这个问题变得更严重。

解决方法:

使用全局平均池化将整个通道压缩成一个通道描述符。第c个通道(第c个Fm)表示如下:
在这里插入图片描述
上一步的转换输出U可以被解释为局部描述子的集合,这些描述子的统计信息对于整个图像来说是有表现力的。特征工程工作中普遍使用这些信息。作者选择最简单的全局平均池化,同时也可以采用更复杂的汇聚策略。

1.3.4 自适应重新校正(Excitation)

通过一定方式提取完了通道信息,我们就要开始利用这些通道信息了,利用他们来全面捕获通道依赖性。

能捕获通道间依赖关系的机制必须要满足下面两个条件:

  1. 它必须是灵活的(特别是它必须能够学习通道之间的非线性交互)
  2. 它必须学习一个非互斥的关系(non-mutually-exclusive relationship ),因为允许多个通道被强调, 相对于独热激活。(这里感觉第一条灵活的非线性交互互其实包含了第二条,第二条只是为了强调下非互斥关系)

解决方案:

为了满足这些标准,我们选择采用一个简单的门机制,并使用sigmoid激活(这里得到的标量S就相当于一会要加在输出信息U的某个Fm上的权重了):
在这里插入图片描述
δ是指Relu激活函數,W1和W2是用于降维和升维的两个全连接层的权重,目的是为了(1)限制模型复杂度(2)辅助模型泛化。

通过在非线性周围形成两个全连接(FC)层的瓶颈来参数化门机制,即降维层参数为W1,降维比例为r。一个ReLU,然后是一个参数为W2的升维层。

块的最终输出通过重新调节变换输出U得到:

在这里插入图片描述
其中X˜=[x˜1,x˜2,…,x˜C]和Fscale(uc,sc)指的是特征映射uc∈RW×H和标量sc之间的对应通道乘积。激活作为适应特定输入描述符z的通道权重。在这方面,SE块本质上引入了以输入为条件的动态特性,有助于提高特征辨别力。

1.4 SE结合先进架构的灵活应用

SE块的灵活性意味着它可以直接应用于标准卷积之外的变换。为了说明这一点,我们通过将SE块集成到两个流行的网络架构系列Inception和ResNet中来开发SENets。前面之所以用一个看似加一个无关的Ftr其实是现在用将它们替换为Inception和Residual模块了。

1. SE-Inception模块:

通过对架构中的每个模块进行更改,我们构建了一个SE-Inception网络。如下图:
在这里插入图片描述
2. SE-ResNet模块:

在这里,SE块变换Ftr被认为是残差模块的非恒等分支。压缩和激励都在恒等分支相加之前起作用。如下图:

在这里插入图片描述

1.5 实验

SENet通过堆叠一组SE块来构建。实际上,它是通过用原始块的SE对应部分(即SE残差块)替换每个原始块(即残差块)而产生的。我们在表1中描述了SE-ResNet-50和SE-ResNeXt-50的架构。fc后面的内括号表示SE模块中两个全连接层的输出维度。

在这里插入图片描述
在实践中提出的SE块是可行的,它必须提供可接受的模型复杂度和计算开销。每个SE块利用压缩阶段的全局平均池化操作和激励阶段中的两个小的全连接层,接下来是几乎算不上计算量的通道缩放操作。

为了说明模块的成本,作为例子我们比较了ResNet-50和SE-ResNet-50,其中SE-ResNet-50的精确度明显优于ResNet-50,接近更深的ResNet-101网络(如表2所示)。对于224×224像素的输入图像,ResNet-50单次前向传播需要∼ 3.86 GFLOP。总的来说,SE-ResNet-50需要∼ 3.87 GFLOP,相对于原始的ResNet-50只相对增加了0.26%。

下图是ImageNet验证集上的单裁剪图像错误率(%)和复杂度比较。original列是指原始论文中报告的结果。为了进行公平比较,我们重新训练了基准模型,并在re-implementation列中报告分数。SENet列是指已添加SE块后对应的架构。括号内的数字表示与重新实现的基准数据相比的性能改善。†表示该模型已经在验证集的非黑名单子集上进行了评估(在[38]中有更详细的讨论),这可能稍微改善结果。在实践中,训练的批数据大小为256张图像,ResNet-50的一次前向传播和反向传播花费190 ms,而SE-ResNet-50则花费209 ms(两个时间都在具有8个NVIDIA Titan X GPU的服务器上执行)。我们认为这是一个合理的开销,因为在现有的GPU库中,全局池化和小型内积操作(最后一步乘权重)的优化程度较低。此外,由于其对嵌入式设备应用的重要性,我们还对每个模型的CPU推断时间进行了基准测试:对于224×224像素的输入图像,ResNet-50花费了164ms,相比之下,SE-ResNet-50花费了167ms。SE块所需的小的额外计算开销对于其对模型性能的贡献来说是合理的。

在这里插入图片描述

对SE引入的附加参数的讨论:

SE的所有附加参数其实都在其中的两个全连接层了,他们构成了网络总容量的一小部分。增加的参数的计算方法如下:
在这里插入图片描述
单个SE块增加的参数为:c*c/r + (c/r)*c=(2c^2)/r . 其中r表示减少比率(我们在所有的实验中将r设置为16),S指的是阶段数量(每个阶段是指在共同的空间维度的特征映射上运行的块的集合),Cs表示阶段s的输出通道的维度,Ns表示重复的块编号。(一个网络S个阶段,每个阶段重复N个SE块)

1.6 模型的实现

训练过程

  1. 使用随机大小裁剪到224×224像素(299×299用于Inception-ResNet-v2[38]和SE-Inception-ResNet-v2)
  2. 随机的水平翻转
  3. 输入图像通过通道减去均值进行归一化
  4. 采用数据均衡策略进行小批量采样,以补偿类别的不均匀分布
  5. 网络在我们的分布式学习系统“ROCS”上进行训练
  6. 使用同步SGD进行优化,动量为0.9,小批量数据的大小为1024(在4个服务器的每个GPU上分成32张图像的子批次,每个服务器包含8个GPU)
  7. 初始学习率设为0.6
  8. 每30个迭代周期减少10倍
  9. 所有模型都从零开始训练100个迭代周期

imagenet测试
1.验证集上的处理过程:

在验证集上使用中心裁剪图像评估来报告top-1和top-5错误率,其中每张图像短边首先归一化为256,然后从每张图像中裁剪出224×224个像素,(对于Inception-ResNet-v2和SE-Inception-ResNet-v2,每幅图像的短边首先归一化到352,然后裁剪出299×299个像素)。

2.SE块对不同深度基础网络的影响(以ResNet为例):

我们首先将SE-ResNet与一系列标准ResNet架构进行比较。每个ResNet及其相应的SE-ResNet都使用相同的优化方案进行训练。

在这里插入图片描述
虽然应该注意SE块本身增加了深度,但是它们的计算效率极高,即使在扩展的基础架构的深度达到收益递减的点上也能产生良好的回报。而且,我们看到通过对各种不同深度的训练,性能改进是一致的,这表明SE块引起的改进可以与增加基础架构更多深度结合使用。

1.7 结论

在本文中,作者提出了 SE 块,这是一种新颖的架构单元,旨在通过使其能够执行动态通道特征重新校准来提高网络的表示能力。 大量的实验证明了 SENet 的有效性,它在多个数据集上实现了最先进的性能。

2. SE-Resnet50 代码实现

import torch.nn as nn
import torch.nn.functional as F
import math
from torchsummary import summary

class SElayer(nn.Module):
    def __init__(self,ratio,input_aisle):
        super(SElayer, self).__init__()
        self.pool=nn.AdaptiveAvgPool2d(1)
        self.fc=nn.Sequential(
            nn.Linear(input_aisle,input_aisle//ratio,bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(input_aisle//ratio,input_aisle,bias=False),
            nn.Sigmoid()
                             )
    def forward(self,x):
        a, b, _, _ = x.size()
        #读取批数据图片数量及通道数
        y = self.pool(x).view(a, b)
        #经池化后输出a*b的矩阵
        y = self.fc(y).view(a, b, 1, 1)
        #经全连接层输出【啊,吧,1,1】矩阵
        return x * y.expand_as(x)
        #输出权重乘以特征图
class SE_block(nn.Module):
    def __init__(self, outchannels, ratio=16, ):
        super(SE_block, self).__init__()
        self.backbone=nn.Sequential(nn.Conv2d(in_channels=outchannels, out_channels=outchannels // 4, kernel_size=1, stride=1),
                                    nn.BatchNorm2d(outchannels // 4),
                                    nn.ReLU(inplace=True),
                                    nn.Conv2d(in_channels=outchannels // 4, out_channels=outchannels // 4, kernel_size=3, stride=1, padding=1),
                                    nn.BatchNorm2d(outchannels // 4),
                                    nn.ReLU(inplace=True),
                                    nn.Conv2d(in_channels=outchannels // 4, out_channels=outchannels, kernel_size=1, stride=1),
                                    nn.BatchNorm2d(outchannels),
                                    nn.ReLU(inplace=True),
                                    )
        self.Selayer=SElayer(ratio, outchannels)
    def forward(self,x):
        residual=x
        x=self.backbone(x)
        x=self.Selayer(x)
        x=x+residual
        return x
class SE_Idenitity(nn.Module):
    def __init__(self, inchannel,outchannels, stride=2,ratio=16,):
        super(SE_Idenitity, self).__init__()
        self.backbone = nn.Sequential(
                                nn.Conv2d(in_channels=inchannel, out_channels=outchannels//4, kernel_size=1, stride=1),
                                nn.BatchNorm2d(outchannels//4),
                                nn.ReLU(inplace=True),
                                nn.Conv2d(in_channels=outchannels//4, out_channels=outchannels//4, kernel_size=3, stride=stride, padding=1),
                                nn.BatchNorm2d(outchannels//4),
                                nn.ReLU(inplace=True),
                                nn.Conv2d(in_channels=outchannels//4, out_channels=outchannels, kernel_size=1, stride=1),
                                nn.BatchNorm2d(outchannels),
                                nn.ReLU(inplace=True),
                                    )
        self.residual=nn.Conv2d(in_channels=inchannel, out_channels=outchannels, kernel_size=1, stride=stride)
        self.selayer = SElayer(ratio, outchannels)
    def forward(self,x):
        residual=self.residual(x)
        x=self.backbone(x)
        x=self.selayer(x)
        x=x+residual
        return x
class SE_Resnet(nn.Module):
    def __init__(self,layer_num,outchannel_num,num_class=10):
        super(SE_Resnet, self).__init__()
        self.initial=nn.Sequential(nn.Conv2d(in_channels=3,out_channels=64,kernel_size=7,padding=3,stride=2),
                                   nn.BatchNorm2d(64),
                                   nn.ReLU(inplace=True),
                                   nn.MaxPool2d(kernel_size=3,padding=1,stride=2))
        self.residual=self.make_layer(layer_num,outchannel_num)
        self.pool=nn.AdaptiveAvgPool2d(1)
        self.fc=nn.Linear(2048,num_class)
    def make_layer(self,number_layer,number_outchannel):
        layer_list=[]

        for i in range(len(number_layer)):
            if i==0:
                stride=1
            else:
                stride=2
            layer_list.append(SE_Idenitity(number_outchannel[i],number_outchannel[i+1],stride))
            for j in range(number_layer[i]-1):
                layer_list.append(SE_block(number_outchannel[i+1]))
        return nn.Sequential(*layer_list)
    def forward(self,x):
        x=self.initial(x)
        x=self.residual(x)
        x=self.pool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return F.softmax(x,dim=1)

def SE_Resnet50(num_class):
    model=SE_Resnet([3,4,6,3],[64,256,512,1024,2048],num_class)
    return model
def SE_Resnet101(num_class):
    model=SE_Resnet([3,4,23,3],[64,256,512,1024,2048],num_class)
    return model
def SE_Resnet151(num_class):
    model = SE_Resnet([3, 8, 36, 3], [64,256, 512, 1024, 2048], num_class)
    return model
device=torch.device("cuda:0")
Xception=SE_Resnet50(10).to(device)
summary(Xception,(3,224,224))

总结

本周学习了SENet这篇经典的通道注意力网络架构,同时也对其代码实现有了一定的了解,下周我将学习空间注意力模块。

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

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

相关文章

基于SSM+Jsp的列车票务信息管理系统

开发语言:Java框架:ssm技术:JSPJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包…

【Android】Android系统性学习——Android系统架构

前言 部分内容参考《Android进阶解密》 – 刘望舒 1. Android版本 官方链接:https://developer.android.com/studio/releases/platforms 里面有各个版本的官方文档,有些新功能的用法在这里面。 现在做安卓11,有时候需要向下兼容 2. AOSP …

目标检测算法SSD与FasterRCNN

目标检测算法SSD与FasterRCNN SSD:( Single Shot MultiBox Detector)特点是在不同特征尺度上预测不同尺度的目标。 SSD网络结构 首先对网络的特征进行说明:输入的图像是300x300的三通道彩色图像。 网络的第一个部分贯穿到Vgg16模型 Conv5的…

PAT B1026. 程序运行时间

题目描述 要获得一个C语言程序的运行时间,常用的方法是调用头文件time.h,其中提供了clock()函数,可以捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是clock tick,即“时钟打点”。同时还有一个常数CLK_TCK——给出了机器时钟每秒所走的时钟打点数…

【Android面试八股文】Java中有几种引用关系,它们的区别是什么?

在Java中,引用关系主要分为以下几种: 强引用(Strong Reference)软引用(Soft Reference)弱引用(Weak Reference)虚引用(Phantom Reference) 这些引用类型的区别在于它们对垃圾回收的影响程度。下面是对每种引用类型的详细解释及代码示例: 1. 强引用(Strong Referen…

继电器的保护二极管如何选择

继电器在实际应用中,通常都会使用三极管或MOS管控制,其最基本的应用电路如图: 那为什么要在继电器线圈上并联一个二极管呢?我们可以看看没有并联二极管时电路会出现什么情况,我们使用下图所示的电路参数仿真一下&#…

Java web应用性能分析之【prometheus+Grafana监控springboot服务和服务器监控】

Java web应用性能分析之【java进程问题分析概叙】-CSDN博客 Java web应用性能分析之【java进程问题分析工具】-CSDN博客 Java web应用性能分析之【jvisualvm远程连接云服务器】-CSDN博客 Java web应用性能分析之【java进程问题分析定位】-CSDN博客 Java web应用性能分析之【…

5.3.1_2 二叉树的层次遍历

👋 Hi, I’m Beast Cheng👀 I’m interested in photography, hiking, landscape…🌱 I’m currently learning python, javascript, kotlin…📫 How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以订…

PostgreSQL下载地址

下载地址:PostgreSQL: File Browser

Arduino入门2——常用函数及用法

Arduino入门2——串口驱动函数及用法 IO串口 上期,我们简单的认识了一下Arduino,浅浅的入了个门,这一期我们介绍以下Arduino串口常用的函数及用法 IO 常用串口库函数如下: 函数名用法及解析pinMode()用于IO口初始化digitalWrite…

【iOS】自定义cell及其复用机制

文章目录 cell的复用注册非注册两者的区别 自定义cell cell的复用 当用户滚动 UITableView 或 UICollectionView 时,只有少量可见的 cell 会被实际创建和显示。对于那些暂时不可见的 cell,系统会将它们缓存起来以备将来复用。这就是所谓的 cell 复用机制。 为什么需要cell的复…

【招联消费金融股份】有限公司2024年5月19日【算法开发岗暑期实习】二面试经验分享

招联消费金融股份有限公司2024年5月18日面试经验分享 面试流程:30分钟 面试流程:30分钟 先自我介绍3分钟然后介绍论文和实习,细细问。问对招联了解多少?对实习地点怎么样?反问,正常聊天。 创作不易&#x…

数字化转型中的数据资产运营:从数据资产的获取、存储、分析到应用的全流程管理策略

一、引言 随着信息技术的迅猛发展,数字化转型已成为企业提升竞争力、实现可持续发展的关键途径。数据资产作为数字化转型的核心要素,其运营与管理水平直接决定了企业能否在激烈的市场竞争中脱颖而出。本文将从数据资产的获取、存储、分析到应用的全流程…

vue关于:deep穿透样式的理解

情况一 子组件&#xff1a; <div class"child"><div class"test_class">test_class<div class"test1">test1<div class"test2">test2</div></div></div></div>父组件&#xff1a; …

Java爬虫——正则表达式应用

Pattern Matcher均属于regex下 步骤&#xff1a;pattern获取正则&#xff0c;matcher获取文本对象&#xff0c;find截取字符串&#xff08;返回true、false&#xff09;&#xff0c;group获得字符 例题&#xff1a;爬取指定文字 分析&#xff1a; 二次调用时&#xff1a; 循环…

【vue3中使用$refs】

在使用uniapp官网里的uni-popup弹出层组件时&#xff0c;要将vue2转换成vue3,&#xff0c;这里遇到了一个问题&#xff1a;vue2可以通过this访问到绑定的ref&#xff0c;但是vue3没有了this,应该怎么办呢&#xff1f; 解决方法&#xff1a; !

Cocos Creator,Youtube 小游戏!

YouTube 官方前段时间发布了一则重磅通知&#xff0c;宣布平台旗下小游戏功能 Youtube Playables 正式登录全平台&#xff08;安卓、iOS、网页&#xff09;&#xff0c;并内置了数十款精选小游戏。 Youtube Playables 入口&#xff1a; https://www.youtube.com/playables Coco…

Digital电路仿真软件的安装

文章目录 1. Java环境的安装 2. Digital安装 3. 软件配置 1. Java环境的安装 电路仿真软件Digital是一款用于设计和仿真数字逻辑电路的工具。它可以帮助用户创建、测试和调试各种数字电路&#xff0c;提供可视化的电路编辑环境&#xff0c;使得设计过程更加直观和便捷。 D…

Sigir2024 ranking相关论文速读

简单浏览一下Sigir2024中与ranking相关的论文。不得不说&#xff0c;自从LLM大热后&#xff0c;传统的LTR方向的论文是越来越少了&#xff0c;目前不少都是RAG或类似场景下的工作了&#xff0c;比如查询改写、rerank等。 文章目录 The Surprising Effectiveness of Rankers Tr…

centos环境上:k8s 简单安装教程

本次演示安装3节点k8s环境&#xff0c;无需多言&#xff0c;直接上操作步骤&#xff1a; 1、环境准备 k8s部署前&#xff0c;首先需要准备好环境&#xff0c;除了1.4 步骤&#xff0c;其他步骤在所有&#xff08;3个&#xff09;节点上都要执行&#xff1a; 1.1 关闭防火墙 s…