论文阅读:ECAPA-TDNN

news2024/11/25 12:32:16

1. 提出ECAPA-TDNN架构

TDNN本质上是1维卷积,而且常常是1维膨胀卷积,这样的一种结构非常注重context,也就是上下文信息,具体而言,是在frame-level的变换中,更多地利用相邻frame的信息,甚至跳过t − 1 , t + 1 的frame,而去对t − 2 , t + 2 的frame进行连接
在ECAPA-TDNN中,更是进一步利用了膨胀卷积,出现了 dilation=2,3,4的情况。此外,还引入了Res2Net,从而获得了多尺度的context,所谓多尺度,指的是各种大小的感受野
 

代码实现

网络结构如下

  1. 数据增强
  2. TDNN block
  3. 多层特征聚合
  4. 注意力统计池化
  5. FC+BN
  6. 输出
def forward(self, x, aug):
      #数据增强
	    with torch.no_grad():
	        x = self.torchfbank(x)+1e-6
	        x = x.log()   
	        x = x - torch.mean(x, dim=-1, keepdim=True)
	        if aug == True:
	            x = self.specaug(x)
	    
	    #相当于一个TDNN block
	    x = self.conv1(x)
	    x = self.relu(x)
	    x = self.bn1(x)
	    
	    #多层特征聚合
	    x1 = self.layer1(x)
	    x2 = self.layer2(x+x1)
	    x3 = self.layer3(x+x1+x2)
	
	    x = self.layer4(torch.cat((x1,x2,x3),dim=1))
	    x = self.relu(x)
	    
	    #注意力统计池化
	    t = x.size()[-1] 
	    global_x = torch.cat((x,torch.mean(x,dim=2,keepdim=True).repeat(1,1,t), torch.sqrt(torch.var(x,dim=2,keepdim=True).clamp(min=1e-4)).repeat(1,1,t)), dim=1)
	    w = self.attention(global_x)
	    mu = torch.sum(x * w, dim=2)
	    sg = torch.sqrt( ( torch.sum((x**2) * w, dim=2) - mu**2 ).clamp(min=1e-4) )
	    x = torch.cat((mu,sg),1)

	    x = self.bn5(x)
	    x = self.fc6(x)
	    x = self.bn6(x)
	
	    return x

SpecAugment算法

SpecAugment算法是一种添加掩码的数据增强算法,步骤如下:

  1. 预加重:PreEmphasis(torch.nn.Module)
  2. 提取梅尔 torchaudio.transforms.MelSpectrogram(sample_rate=16000, n_fft=512, win_length=400, hop_length=160, f_min = 20, f_max = 7600, window_fn=torch.hamming_window, n_mels=80)
  3. 将梅尔进行零均值归一化,可以直接将Mask位置设为0
  4. 时间维度掩码
  5. 频率维度掩码
 with torch.no_grad():
     #预加重和提取梅尔
	 x = self.torchfbank(x)+1e-6
	 #对数梅尔
	 x = x.log()   
	 x = x - torch.mean(x, dim=-1, keepdim=True)
	 if aug == True:
	     #添加掩码
	     x = self.specaug(x)

掩码部分主要代码:
1.获取梅尔的维度,分别赋值为batch, fea, time
batch为每批次输入梅尔的数量;
fea为每一个梅尔的特征维度,这里应该为80;
time为每一个梅尔的时间维度
2.掩码的长度:生成[batch, 1, 1]维数组
3.掩码的位置:生成[batch, 1 ,1]维数组,根据长度和梅尔的维度调整
4.生成一个D维张量,并将其增加维度至[1,1,D]
5.根据掩码长度和掩码位置得到掩码:[batch, 1 , D] ->[batch, D] ->[batch, 1 , D] or [batch, D, 1]
6.将梅尔掩码的地方赋值为0
 

def mask_along_axis(self, x, dim):
    original_size = x.shape
    batch, fea, time = x.shape
    if dim == 1:
        D = fea
        width_range = self.freq_mask_width
    else:
        D = time
        width_range = self.time_mask_width

    mask_len = torch.randint(width_range[0], width_range[1], (batch, 1), device=x.device).unsqueeze(2)
    mask_pos = torch.randint(0, max(1, D - mask_len.max()), (batch, 1), device=x.device).unsqueeze(2)
    arange = torch.arange(D, device=x.device).view(1, 1, -1)
    mask = (mask_pos <= arange) * (arange < (mask_pos + mask_len))
    mask = mask.any(dim=1)

    if dim == 1:
        mask = mask.unsqueeze(2)
    else:
        mask = mask.unsqueeze(1)
    #用0填充张量x中对应mask位置处为True的元素
    x = x.masked_fill_(mask, 0.0)
    return x.view(*original_size)

2. Channel- and context-dependent statistics pooling

多头注意力机制的成功展示了确定说话人的属性可以在不同的帧集上被提取出来,将时间注意力机制进一步扩展到通道维度是有益的。这使得网络能够更多的关注说话人的特征,而不是激活相同或者相似的时间实例,例如,说话人特有的元音属性与说话人特有的辅音属性。

我们将注意力机制调整为通道的:

ht - 时间步长t时的最后一帧层的激活。

W和b - 自注意力的信息投影到一个更小的R维度表示中,该表示在所有C通道中共享,以减少参数计数和过拟合风险。

在非线性层f(.)之后,这个信息通过权重vc和偏差kc的线性层转化为依赖通道的自注意力分数。

然后再所有帧上通过再信道上应用softmax函数将标量分数et,c归一化。

自注意力分数αt,c表示给定通道下每帧的重要性,用于计算通道c的加权统计量。对于每一个话语,加权平均向量μ的信道分量μc和加权标准差向量σ的通道分量σc估计为:

池化层的最终输出由加权平均μ和加权标准差σ的向量串联得到。

另外,通过允许自注意力观察话语的全局属性,我们扩展了池化层的时间上下文。我们将(1)中的局部输入ht与ht在时域的全局非加权平均值和标准偏差连接起来。这个上下文向量应该允许注意力机制适应话语的全局属性,如噪音或录音条件。

对比Statistic Pooling 和 Attentive Statistic Pooling如下图:

 Statistic Pooling

Attentive Statistics Pooling

ECAPA-TDNN中对ASP进行了改进,首先将之前3个SE-Res2Block的输出,按照特征维度进行串联,假设frame-level变换中的特征维度是512,由于3个SE-Res2Block的输出维度都是 (bs,512,T),所以串联之后是(bs,512*3,T),之后经过一个CRB结构,输出维度固定为(bs,1536,T),即便frame-level的特征维度是1024,该CRB的输出维度也不变。如下图所示

对特征图(bs,1536,T),记为h,按照T维度计算每个特征维度的均值和标准差,从而T维度消失,得到的均值和标准差维度均为(bs,1536)

之后的操作很神奇,将均值在T维度重复堆叠T次,维度恢复为 (bs,1536,T),对标准差也是堆叠,维度恢复为(bs,1536,T),接着将特征图、均值和标准差在特征维度进行串联,得到的特征图维度为(bs,1536∗3,T),记为H

对H进行1维卷积,等价于上图的W × H + b ,目的是将每个frame的特征从1536*3维降维映射到F维,F可取128,然后经过tanh激活函数,得到特征图a,维度为(bs , F , T ) 

对a进行1维卷积,等价于上图的V × a + k,目的是将每个frame的特征从F维恢复映射到与h相同的维度,即1536,然后在T维度,进行softmax激活,得到特征图a,维度为(bs,1536,T)
此时的特征图a的每一行特征,在T维度上求和,都等于1,这是softmax激活的效果,又因为与h的维度相同,所以可以将a视为一种Attention分数,利用上图的ASTP公式,对h求基于Attention的均值和标准差,关于Attention分数,可以参考深入理解Self-attention(自注意力机制)
基于Attention的均值和标准差,维度都为(bs,1536),再将它们按照特征维度进行串联,得到ASP最终的输出,维度为 (bs,1536*2),在ECAPA-TDNN中,ASP之后还会接一个BN

torch.nn.BatchNorm1d(num-features,eps=1e−05,momentum=0.1,affine=True,track-running-stats=True,device=None,dtype=None)

BN中的num-features是理解BN的关键,对于图像任务,num-features要等于输入特征图的通道数,而对于音频任务,num-features要等于 (bs,F,T)中的F
也就是说,BN必然是作用于图像的特征图通道,或者音频中frame的每个特征的,num-features是告诉BN,均值和标准差,这两个向量的长度
BN计算均值和标准差的操作,与上述ASP的第一步,计算h_mean和h_std是类似的,不过计算的范围是在一个batch中

得到一个batch的统计量后,BN的输出也就确定了,不过需要先将μB 和σ^2B 重复堆叠成(bs,F,T)的大小,与输入BN的特征图H的维度相同,才能让其与H进行运算。在训练时,BN的输出

其中

此外,BN内部还有两个用于估计全局统计量的均值和标准差向量,在训练时,这两个向量根据每个batch的统计量进行更新,在测试时,BN会采用全局统计量对特征图进行规范化

其中
下标running表示采用移动平均(running average)的方法对全局统计量进行估计
系数momentum是对当前batch的统计量的权重,可取0.1
 

实现代码如下:

# 得到时间帧
t = x.size()[-1]
# 获取时间帧维度的均值和标准差,然后串联原始数据
mean = torch.mean(x,dim=2,keepdim=True).repeat(1,1,t)
standrad = torch.sqrt(torch.var(x,dim=2,keepdim=True).clamp(min=1e-4)).repeat(1,1,t))
global_x = torch.cat((x, mean, standrad), dim=1)
#通过注意力网络得到注意力矩阵w
w = self.attention(global_x)
self.attention = nn.Sequential(
            nn.Conv1d(4608, 256, kernel_size=1),
            nn.ReLU(),
            nn.BatchNorm1d(256),
            nn.Tanh(), # I add this layer
            nn.Conv1d(256, 1536, kernel_size=1),
            nn.Softmax(dim=2),
            )

mu = torch.sum(x * w, dim=2)
sg = torch.sqrt( ( torch.sum((x**2) * w, dim=2) - mu**2 ).clamp(min=1e-4) )
x = torch.cat((mu,sg),1)

3. 1-Dimensional Squeeze-Excitation Res2Blocks

Res2Net

  1. 经典的ResNet结构如下左图所示,先用kernel-size=1×1的卷积运算,相当于只针对每个像素点的特征通道进行变换,而不关注该像素点的任何邻近像素,并且是降低特征通道的,所以也被叫做Bottleneck,就好像将可乐从瓶口倒出来,如果是增加特征通道,那么就叫Inverted Bottleneck
  2. 1×1卷积后,会经过3 × 3 卷积,通常不改变特征通道,如果不需要在最后加上残差连接,那么stride=2,特征图的分辨率会被下采样,如果需要在最后加上残差连接,那么 stride=1,保持特征图分辨率不变。
  3. 最后还会有一个1 × 1卷积,目的是复原每个像素点的特征通道,使其等于输入时的特征通道,从而能够进行残差连接。整个Bottleneck block形似一个沙漏,中间是窄的(特征通道少),两边是宽的(特征通道多)
     

  1. 而Res2Net则是在中间的3 × 3 卷积进行的微创新,首先将1 × 1 卷积后的特征图,按照特征通道数进行平分,得到s c a l e 个相同的特征图(这里的scale是“尺度”的意思,Res2Net的作用就是多尺度特征,一语双关)
  2. 第一个特征图保留,不进行变换,这是对前一层特征的复用,同时也降低了参数量和计算量。从第二个特征图开始,都进行3 × 3 卷积,并且当前特征图的卷积结果,会与后一个特征图进行残差连接(逐元素相加),然后,后一个特征图再进行3 × 3 卷积
  3. 卷积中有一个概念叫感受野,是指当前特征图上的像素点,由之前某一个特征图在多大的分辨率下进行卷积得到的。如下图所示,dilation=1的3 × 3卷积,其输出特征图的每一个像素点的感受野都是3 × 3 ,再进行dilation=1的3 × 3卷积,其输出特征图的每一个像素点的感受野都是5 × 5 

  • 因此Res2Net中,第二个特征图的感受野为3 × 3 ,第三个特征图的感受野为5 × 5 + 3 × 3 ,第四个特征图的感受野为7 × 7 + 5 × 5 + 3 × 3 ,以此类推,从而得到多尺度特征
  • 所有的卷积结果都会按照特征通道进行串联(concatenate),由于第一个特征图保留,不进行变换,所以后续的特征图维度必须与第一个特征图相同,因此3 × 3 卷积不改变特征通道和分辨率
  • 最后的1 × 1 卷积,目的是复原每个像素点的特征通道,使其等于输入时的特征通道,从而能够进行残差连接
  • Res2Net可以作为一个即插即用的结构,插入到现有的其他神经网络中,还可以与其他即插即用的结构一起工作,比如SENet和ResNeXt
     

SENet

SENet(Squeeze-and-Excitation Networks)是现代卷积神经网络所必备的结构,性能提升明显,计算量不大。基本思路是将一个特征图的每个特征通道,都映射成一个值(常用全局平均池化,即取该特征通道的均值,代表该通道),从而特征图会映射为一个向量,长度与特征通道数一致

之后,对向量进行FC(用1维卷积也行,等价的),输出长度为特征通道数的1/r,然后经过激活函数ReLU,这个过程称为Squeeze(挤压);再进行FC,输出长度与特征通道数一致,然后经过激活函数Sigmoid,这个过程称为Excitation(激励);此时输出向量的每一个值,范围都是( 0 , 1 ) (0,1)(0,1),最后用输出向量的每一个值,对输入特征图的对应通道进行加权,这个过程称为Scale(伸缩)

SENet的结构相当于对特征图的特征通道进行加权,因为每个特征通道的重要性是不一样的,所以让神经网络自行学习每个特征通道的权重,因此是一种Attention机制。并且输入特征图和输出特征图的维度完全一致,从而可以作为一个即插即用的结构,下面是Res2Net与SENet结合得到的结构,被称为SE-Res2Net。

在ECAPA-TDNN中所用的Res2Net,是上述结构中的2维卷积全部换成1维卷积,采用的中间k = 3 卷积(1维卷积,不能用3 × 3 表示,以下都用k = 3 代替)为膨胀卷积,并且随着网络深度增加,dilation分别为2 , 3 , 4 。ECAPA-TDNN的结构图如下,SE-Res2Block后面括号内的参数,指的是Res2Block的中间k = 3卷积的参数。
 

SE block的第一个组成部分是压缩(squeeze)操作,为每一个通道生成一个描述符。压缩操作包括计算时间域的帧级特征的均值向量z

在激励操作中使用z中的描述符来计算每个通道的权重,我们定义后续的激励操作为

该操作作为bottleneck layer,C为输入通道数,R为降维数。得到的向量s包含介于0和1之间的权值sc,这些权值通过通道乘法作用于原始输入:

一维的SE-block可以以各种方式集成到x-vector中,在每次扩张卷积后使用它们是最直接的方法。但是,我们希望它们与残差连接的优点结合起来。


图1所示的SE-Res2Block包含了上面提到的需求。我们包含空洞卷积与前后密集层与上下文的一帧。第一个密集层用于降低特征维度,第二个密集层用于将特征数量恢复到原始维度。接下来是一个SE-block来缩放每一个通道,整个单元由一个跳跃连接覆盖。

代码实现

一维SE blocks,重新缩放帧级特征,得到通道的重要性。
过程为:
1.特征通过全局平均池化进行压缩
2.用两个全连接层,主要是为了应用relu和sigmoid(将输出映射至0和1)。第一个全连接层降低维度,第二个全连接层恢复维度。
3.输出为输入乘以权重矩阵。

 def __init__(self, channels, bottleneck=128):
    super(SEModule, self).__init__()
    self.se = nn.Sequential(
        #全局平均池化压缩为1个数
        nn.AdaptiveAvgPool1d(1),
        nn.Conv1d(channels, bottleneck, kernel_size=1, padding=0),
        nn.ReLU(),
        nn.Conv1d(bottleneck, channels, kernel_size=1, padding=0),
        nn.Sigmoid(),
        )

def forward(self, input):
    #获得权重矩阵
    x = self.se(input)
    return input * x

res2net主要是利用细粒度的多尺度信息,产生多个感受野的组合。下面左图是res2net多尺度的具体做法,右图是本论文res2net模块的网络结构。

由左图可得,res2net将传统resnet中的3*3卷积进行了多尺度的解耦,在1 * 1卷积之后对通道进行分组,尺度越大计算开销越大。
由右图可知,包含了扩展卷积和前后密集层,第一个密集层用于降低维度,第二个密集层用于恢复维度,最后由SE模块缩放每一个通道。

本文所用的res2net采用了8尺度,在代码中x1是作为最后一个直接送到。

def forward(self, x):
     residual = x
     #############################
     out = self.conv1(x)
     out = self.relu(out)
     out = self.bn1(out)
     #############################
     #############################
     #这里是res2net的核心
     spx = torch.split(out, self.width, 1)
     #分块卷积计算
     for i in range(self.nums):
       if i==0:
         sp = spx[i]
       else:
         sp = sp + spx[i]
       sp = self.convs[i](sp)
       sp = self.relu(sp)
       sp = self.bns[i](sp)
       if i==0:
         out = sp
       else:
         out = torch.cat((out, sp), 1)
     #cat x1的块
     out = torch.cat((out, spx[self.nums]),1)
     ###############################
     ###############################
     out = self.conv3(out)
     out = self.relu(out)
     out = self.bn3(out)
     ###############################
     out = self.se(out)
     out += residual
     return out 


4. Multi-layer feature aggregation and summation

原始的x-vector系统只使用最后一帧层的特征图来计算合并的统计量。鉴于TDNN的层次性质,这些更深层次的特征是最复杂的,应该与说话人的身份密切相关。然而,由于[17,18]中的证据,我们认为,更浅的特征图也可以有助于更稳健的说话人嵌入码。对于每一帧,我们提出的系统将所有SE-Res2Blocks的输出特征映射连接起来。在多层特征聚合(MFA)之后,密集层处理连接的信息,生成关注统计池的特征。
另一种利用多层信息的互补方法是使用前面所有SE-Res2Blocks的输出和初始卷积层作为每个帧层块的输入。我们通过将每个SE-Res2Block中的剩余连接定义为前面所有块输出的和来实现这一点。我们选择特征映射的总和而不是连接来限制模型参数计数。没有累加剩余连接的最终架构如图2所示。

MFA是多层特征聚合,将SE Res2Blocks输出特征映射连接起来

整体代码

x1 = self.layer1(x)
x2 = self.layer2(x+x1)
x3 = self.layer3(x+x1+x2)
x = self.layer4(torch.cat((x1,x2,x3),dim=1))
x = self.relu(x)

5. 损失函数(AAMsoftmax(loss.py))

原理:最大化类间间距,最小化类内间距。
softmax loss在决策边界产生明显的模糊性,但是AAMsoftmax通过添加加性角度边距可以扩大类间的间隙。

1. 归一化输入特征和FC层权重。令所得归一化特征x_{i} 与第j类别的FC层权重点乘得到FC层的第j个输出cosθ_{j} ,将特征x_{i}  预测为第j类的预测值。

cosine = F.linear(F.normalize(x), F.normalize(self.weight))

2. 根据正余弦公式计算sinθ_{j}

sine = torch.sqrt((1.0 - torch.mul(cosine, cosine)).clamp(0, 1))

3. 根据当前夹角的正余弦,计算添加了加性角度边距m的cos(θ+m)

phi = cosine * self.cos_m - sine * self.sin_m

4. 松弛约束

phi = torch.where((cosine - self.th) > 0, phi, cosine - self.mm)

5. 生成矩阵标签

one_hot = torch.zeros_like(cosine) #全0矩阵
one_hot.scatter_(1, label.view(-1, 1), 1) #在label索引上用1替换0

6. 当输入特征x对应真实类别,采用新 Target Logit cos(θ_yi + m), 其余并不对应输入特征x的真实类别的类,保持原有的logit

output = (one_hot * phi) + ((1.0 - one_hot) * cosine)

7. 使用scale缩放新的logit

output = output * self.s

8.计算损失

loss = self.ce(output, label)
self.ce = nn.CrossEntropyLoss()

6. 模型评估


原文链接:https://blog.csdn.net/qq_32766309/article/details/121359110

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

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

相关文章

用于医学图像分割的分段任意模型 (SAM)

一、说明 在不断发展的人工智能 (AI) 领域&#xff0c;医学成像是一个正在经历深刻变革的领域。乘着这一变革浪潮&#xff0c;Facebook 的&#xff08;现为 Meta&#xff09;研究小组开发了一种突破性的模型架构&#xff0c;称为 SegmentAnything (SAM)。SAM 的卓越之处在于它能…

队列:如何在线程池等有限资源池中的应用?

文章来源于极客时间前google工程师−王争专栏。 我们知道&#xff0c;CPU 资源是有限的&#xff0c;任务的处理速度与线程个数并不是线性正相关。相反&#xff0c;过多的线程反而会导致CPU频繁切换&#xff0c;处理性能下降。所以&#xff0c;线程池的大小一般都是综合考虑要处…

MTK6877/MT6877天玑900安卓5G核心板_安卓开发板主板定制开发

2021年5月13日&#xff0c;MediaTek 宣布发布旗下的天玑900系列芯片&#xff0c;又名MT6877。天玑900基于6nm先进工艺制造&#xff0c;搭载硬件级4K HDR视频录制引擎&#xff0c;支持1.08亿像素摄像头、5G双全网通和Wi-Fi 6连接、旗舰级存储规格和120Hz的FHD超高清分辨率显示&a…

GD32F10x系列单片机下载方式

GD32F10x系列单片机下载方式 简介烧录接口KEIL在线烧录选择下载器ST-link接线 DAP、JLINK等 烧录软件烧录STlink接线操作 ISP烧录接线 总结 简介 GD32F10x系列的单片机是兆易创新推出对标意法半导体STM32F10x系列的国产单片机。本文将以GD32F103C8T6展开&#xff0c;GD32F103C8…

持续提升信息安全运维保障服务能力,天玑科技助力企业快速实现数字化转型

近年来&#xff0c;以互联网、云计算、大数据、物联网为代表的新一代信息技术快速发展。给人们的生产生活方式带来方便的同时&#xff0c;也给信息系统的安全带来了严峻的挑战。我国信息化和信息安全保障工作的不断深入推进&#xff0c;以应急处理、风险评估、灾难恢复、系统测…

电动车租赁小程序开发方案详解php

电动车租赁小程序开发功能有哪些&#xff1f; 1.地图找车 进入小程序后&#xff0c;在地图上显示门店位置&#xff0c;点击位置可查看门店信息。进入门店后可以看到车辆列表&#xff0c;车辆里详细的介绍的车辆名称、图片、车辆介绍、租赁价格、押金等信息。 2.租赁/购车 电…

【LeetCode:1488. 避免洪水泛滥 | 有序表 哈希表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

十五、【历史记录画笔工具组】

文章目录 历史记录画笔工具历史记录艺术画笔工具 历史记录画笔工具 历史记录画笔工具很简单&#xff0c;就是将画笔工具嗯&#xff0c;涂抹过的修改过的地方&#xff0c;然后用历史记录画笔工具重新修改回来&#xff0c;比如我们将三叠美元中的一叠用画笔工具先涂抹掉&#xf…

CSS 边框

CSS 边框属性 CSS边框属性允许你指定一个元素边框的样式和颜色。 在四边都有边框 红色底部边框 圆角边框 左侧边框带宽度&#xff0c;颜色为蓝色 边框样式 边框样式属性指定要显示什么样的边界。 border-style属性用来定义边框的样式 border-style 值: none: 默认无边框…

防爆对讲机在消防救援工作中的重要性

据相关报道2022年国内因易燃易爆造成的事故825起&#xff0c;死亡1人以上的事故有103起&#xff0c;共造成234人死亡;火灾爆炸事故306起&#xff0c;占事故总数的37%&#xff0c;造成93人死亡&#xff0c;占死亡总人数的40%。 消防救援队伍在实施灭火作战、应急救援工作面对复杂…

新版Android Studio搜索不到Lombok以及无法安装Lombok插件的问题

前言 在最近新版本的Android Studio中&#xff0c;使用插件时&#xff0c;在插件市场无法找到Lombox Plugin&#xff0c;具体表现如下图所示&#xff1a; 1、操作步骤&#xff1a; &#xff08;1&#xff09;打开Android Studio->Settings->Plugins&#xff0c;搜索Lom…

Notepad++使用技巧

显示远程连接的文件目录 自动完成&#xff1a;函数自动提示 自动输入&#xff1a;输入一半括号自动补全另一半 自动关联 .pc文件识别为C 列模式 按住Alt不松手&#xff0c;可以直接范围选择&#xff0c;便于编辑选择的区域 关键行筛选 1.进入搜索页面的标记 2.选中标…

【C++】继承 ③ ( 继承的一些重要特性 | 子类拥有父类的所有成员 | 多态性 | 子类可以拥有父类没有的成员 | 代码示例 )

文章目录 一、继承的一些重要特性1、子类拥有父类的所有成员2、子类可以拥有父类没有的成员3、多态性 二、代码示例 一、继承的一些重要特性 1、子类拥有父类的所有成员 子类 继承 父类 , 则 子类 拥有 父类的 所有 成员变量 和 成员函数 ; 这里要注意 : 子类 拥有 父类的 私有…

海外代理高性价比推荐——精选list

做跨境电商的都明白&#xff0c;无论运营店铺还是社媒账号&#xff0c;都需要海外代理&#xff0c;而在市场上海外的代理很多&#xff0c;到底什么才是适合自己呢&#xff1f;下面我进行测评后整理列出了一份稳定&#xff0c;高性价比好用的几款海外代理。 1、IPFoxy全球代理I…

NeurIPS 2023 | MQ-Det: 首个支持多模态查询的开放世界目标检测大模型

目前的开放世界目标检测模型大多遵循文本查询的模式&#xff0c;即利用类别文本描述在目标图像中查询潜在目标。然而&#xff0c;这种方式往往会面临“广而不精”的问题。一图胜千言&#xff0c;为此&#xff0c;作者提出了基于多模态查询的目标检测&#xff08;MQ-Det&#xf…

postman接口测试

HTTP的接口测试工具有很多&#xff0c;可以进行http请求的方式也有很多&#xff0c;但是可以直接拿来就用&#xff0c;而且功能还支持的不错的&#xff0c;我使用过的来讲&#xff0c;还是postman比较上手。 优点&#xff1a; 1、支持用例管理 2、支持get、post、文件上传、响…

解决modprobe加载驱动问题

一、insmod与modprobe 在Linux中&#xff0c;linux设备驱动有两种加载方式insmod和modprobe。 insmod insmod是一个加载模块的命令&#xff0c;但和modprobe不同的是&#xff0c;insmod不会自动加载依赖的模块。如果你需要加载的模块有依赖关系&#xff0c;那么你需要手动一个…

linux进阶-ipc信号(软中断信号)

信号 信号&#xff08;软中断信号&#xff09;&#xff0c;用于通知进程发生了异步事件&#xff08;它是Linux系统响应某些条件而产生的一个事件&#xff0c;它是在软件层次上对中断机制的一种模拟&#xff0c;是一种异步通信的方式&#xff0c;在原理上&#xff0c;一个进程收…

基于springboot实现外卖点餐平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现外卖点餐平台系统演示 摘要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜…

(Vue3)大事记管理系统 首页 文章分类页

首页 先搭架子-用element-ui中的组件&#xff1a;container组件、layout组件 不知道的属性学会看文档&#xff01; :default-active"$route.path" 配默认高亮菜单项 $route.path 字符串&#xff0c;等于当前路由对象的路径&#xff0c;如“/home/news $route…