您的位置:首页 > 文旅 > 美景 > 深度学习--机器学习相关(3)

深度学习--机器学习相关(3)

2024/12/23 9:12:22 来源:https://blog.csdn.net/m0_63860007/article/details/141896077  浏览:    关键词:深度学习--机器学习相关(3)
1.K-近邻算法

        KNN 听起来像是某种神经网络的名字,如RNN、CNN  等,其实不然,这是一种经典、简单的分类算法K- 近邻算法(K-Nearest  Neighbor,KNN)。与无监督学习讲解的聚类算法不同,KNN 是一个有监督算法。

        有监督学习是一种学习算法,它从标记的训练数据学习,每个训练示例都包括输入和相应的输出标签。有监督学习的目标是学习出一个映射规则,使得模型能够对新的、未见过的数据做出准确的预测或决策。

        无监督学习涉及无标签数据,模型必须自行发现输入数据中的结构。无监督学习的目标是探索数据的内在性质和分布,以便进行聚类、密度估计、降维等任务。

开始KNN 算法的流程:

(1)计算出这个测试数据与所有训练集中的样本的距离;

(2)对这个距离进行排序,然后选取距离测试数据最近的k 个样本;

(3)对这被选取的k 个样本的标签进行统计,k 个样本中哪一种标签的数量最多,这个 测试数据就属于哪个类别。

整个流程非常的简单,而且模型的准确度也比较高,但是计算量大,尤其是当训练集的数据量是千万级别的时候。

2.模拟退火算法

        模拟退火算法(Simulatied   Annealing,SA)是一种避免局部最优的方法。

3.流形学习

        流形学习是一种对于数据特征本质学习的过程。在特征工程中,有很多高维度的数据,如果在高维度空间直接衡量他们的距离,也可以,但是需要找到一个适合高维度空间的、适合数据特征的距离函数。否则,可以把高维 的特征映射到低维上,然后用低维的距离来表示样本的距离。自编码器(Auto   Encoder)就是一个降维的操作。可以把一个图片的高维数据降维成低维数据。当然流形学习还有一个观点:生成。高维数据冗杂很多,所以通过降维操作来提取数据特征的本质,过滤冗余。高维数据冗杂太多,高维空间中并不是每一个点都是有意义的。 假设要生成手写数字,高维空间中并不是每一个点都对应一张图片,因为有冗杂。所以把高 维数据映射到低维空间中,这样低维空间中的数据较少冗杂,更能体现数据本质,从而低维 空间中的每一个点都是有效的、可以生成图片的。再把低维数据映射回高维中,就可以产生 有意义的图片了。

总之流形学习的思想有:

(1)高维数据之间的距离衡量函数比较困难,不妨映射到低维中用欧氏距离。

(2)高维空间并不是每一个点都有意义,用更能表示本质特征的低维空间来生成有意 义的样本。

(3)降维降低的是冗杂信息,希望保留的是本质特征,所以自编码器的使用其实非常

广泛。

4.端侧神经网络GhostNet(2019)

        GhostNet  基于 Ghost 模块,其特点是不改变卷积的输出特征图的尺寸和通道大小,但是可以让整个计算量和参数数量大幅度降低。简单来说,GhostNet 的主要贡献就是减低计算量、提高运行速度的同时,精准度降低的更少了,而且这种改变,适用于任意的卷积网络, 因为它不改变输出特征图的尺寸。GhostNet 的想法就是,既然有这么多的特征图都 是相似的,那么生成相似的特征图的那部分计算量就是多余的,可以节省。其中,相似的特征图,称为Ghost

        从GhostNet   中可以学到怎么用GhostNet  的基  本思想来降低模型的计算量。下面的内容就会围绕着GhostNet   Ghost-Blockneck  展开。 Ghost-Blockneck  是基于Ghost    Module组件,还有SE   Module Depthwise  卷积。

 Ghost Module是 GhostNet 的主要贡献

class GhostModule(nn.Module):#定义了一个名为 GhostModule 的类,它继承自 PyTorch 的 nn.Moduledef __init__(self,inp,oup,kernel_size=1,ratio=2,dw_size=3,Stride=1,relu=True):#定义了类的初始化函数,接受以下参数#inp:输入通道数,oup:输出通道数,kernel_size:主要卷积层的卷积核大小。#ratio:廉价操作扩展比例,dw_size:廉价操作中深度可分离卷积的卷积核大小。super(GhostModule,self).__init__()self.oup=oup#将输出通道数保存为类的成员变量。init_channels=math.ceil(oup/ratio)#计算初始通道数,这是通过将输出通道数除以比例并向上取整得到的。new_channels=init_channels*(ratio-1)#计算通过廉价操作扩展后的新通道数。#定义了一个序列模块,包含一个卷积层、一个批量归一化层和一个可选的ReLU激活函数。这个序列作为主要卷积操作。self.primary_conv=nn.Sequential(nn.Conv2d(inp,init_channels,kernel_size,Stride,padding=kernel_size//2,bias=False),nn.BatchNorm2d(init_channels),nn.ReLU(inplace=True) if relu else nn.Sequential(),)self.cheap_operation=nn.Sequential(nn.Conv2d(init_channels,new_channels,dw_size,Stride=1,padding=dw_size//2,groups=init_channels,bias=False),nn.BatchNorm2d(new_channels),nn.ReLU(inplace=True) if relu else nn.Sequential(),)def forward(self,x):#定义了前向传播函数。x1=self.primary_conv(x)#将输入 x 通过主要卷积操作x2=self.cheap_operation(x1)#将 x1 的输出通过廉价操作out=torch.cat([x1,x2],dim=1)#将 x1 和 x2 在通道维度上进行拼接,dim 参数指定了要进行操作的维度return out[:,:self.oup,:,:]#返回输出,只保留前 oup 个通道,以确保输出通道数与预期一致

        这里的参数 ratio 是一个重点,体现了特征图中有多少的特征图不是Ghost的比例。例如,生成16个特征图,如果ratio=2,就说明有8个特征图不是Ghost

 5.分 组 卷 

        如果分的组数等于输入特征图的通道数,那么就是Depthwise了,如果分 的组没有那么多,就是一般的分组卷积(Group Convolution)。

        "Depthwise",它指的是深度可分离卷积,这是一种卷积操作,可以分解为两个较小的操作:深度卷积和逐点卷积,从而减少模型的计算复杂度和参数数量。

深度卷积(Depthwise Convolution):在深度卷积中,每个输入通道独立地应用一个卷积核。如果输入有 D 个通道,则有 D 个卷积核。

通道分组:在分组卷积中,输入和输出通道被分成多个组。每个组内的通道只能与该组内的卷积核进行卷积操作。

这是一个二维卷积层

self.cheap_operation=nn.Sequential(nn.Conv2d(init_channels,new_channels,dw_size,Stride=1,#这是一个二维卷积层,init_channels:输入通道数,new_channels:输出通道数,这里通过深度可分离卷积扩展的通道数#dw_size:卷积核的大小,用于深度可分离卷积,卷积的步长设置为1,意味着卷积核每次移动一个像素padding=dw_size//2,groups=init_channels,bias=False),#边缘填充的大小,通常设置为卷积核大小的一半,以保持输出特征图的空间尺寸不变。nn.BatchNorm2d(new_channels),#groups=init_channels:将输入通道分组,每组包含一个通道,并为每组应用一个卷积核。当 groups 等于输入通道数时,这实现了深度可分离卷积nn.ReLU(inplace=True) if relu else nn.Sequential(),
)
#bias=False:不使用偏置项,在神经网络的卷积层中,bias=False 参数指定了在该层中不使用偏置项
# 偏置项是卷积操作中的一个额外参数,它的作用是在应用激活函数之前为每个输出单元添加一个常数,以帮助网络更好地拟合数据。
#这是一个批量归一化层,用于归一化深度可分离卷积的输出,以提高训练的稳定性和速度。它作用于 new_channels 个通道。
#inplace=True 表示在原地进行计算,可以减少内存使用

        参数 groups 就是要分的组数,如果groups  的数值等于输入通道数,那么就是Depthwise的方法。

6.SE Module

SE(Squeeze-and   Excitation)Module SENet 网络提出的 Module,SENet 现在有点过时了,但SENet 的核心 SE Module保留了下来,代码如下:

class SELayer(nn.Module):def __init__(self,channel,reduction=4):#reduction:降维比例,默认为4,用于在全连接层中减少参数数量super(SELayer,self).__init__()self.avg_pool=nn.AdaptiveAvgPlool2d(1)#创建一个自适应平均池化层,它将对每个通道的特征图进行平均,输出一个包含全局空间信息的特征图。self.fc=nn.Sequential(nn.Linear(channel,channel//reduction),nn.ReLU(inplace=True),#nn.ReLU(inplace=True) 是一个激活函数,用于增加非线性nn.Linear(channel//reduction,channel),)def forward(self,x):b,c,_,=x.size()#获取输入特征图 x 的尺寸,其中 b 是批次大小,c 是通道数y=self.avg_pool(x).view(b,c)#通过自适应平均池化层处理输入特征图 x,然后将其重新形状为 (b, c)y=self.fc(y).view(b,c,1,1)#将处理后的特征图 y 通过定义的全连接层序列,然后重新形状为 (b, c, 1, 1),使其可以与原始输入特征图 x 进行逐元素乘法y=torch.clamp(y,0,1)#使用 torch.clamp 函数将 y 的值限制在 [0, 1] 范围内,这通常是为了确保权重在合理的范围内return x*y#将输入特征图 x 与重新校准后的权重 y 进行逐元素乘法,实现通道注意力机制,然后返回结果#SELayer 通过对特征图的全局平均池化和全连接层的处理,学习到每个通道的重要性权重,然后将这些权重应用于原始特征图,以此来增强模型对重要特征的感知能力。# 这种注意力机制在许多现代卷积神经网络架构中被广泛使用

        x×y  就是SE  Module的最终返回值。自适应池化层,可以随便设置池化之后的尺寸,都可以适应。这段代码相当于SE  Module对通道进行了一个权重的评估。有的通道可能重 要,有的通道可能不重要,所以经过这个过程让特征图的每一个通道得到了一个权重值。 如何体现权重值的?就是让通道的每一个值都乘上这个权重值,虽操作简单但是是有效果 SE Module中使用到了全连接层,如果每一层都是用SE   Module的话,可能增加10%  左右的计算量。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com