图片分类任务——卷积神经网络概念

分类任务基础概念

分类任务的输出

不同于回归任务,只输出一个值,分类任务的每一个样本都输出多维的预测值y^,即一个多维向量,代表着一组概率值,其和为1。

真实标签y,也同为一组概率向量,且用独热编码表示,即如果结果属于该类就取1,剩余类取0。

如下图,一共三类,如果有100个样本,5个特征,假如经过一层网络,即 Linear(5,3),100*5的样本输入,最终变成100*3的输出y^,其中每一个样本的输出都是三维的概率向量,分类任务的loss值会将y,y^经过交叉熵损失算得。(如果是回归任务则是 Linear(5,1),100*5的样本输入,最终变成100*1的输出y^)

图片的处理方法

一、拉直 Flatten

彩色图片通常可以表示为三个矩阵,分别对应于红色(Red)、绿色(Green)、蓝色(Blue)三个颜色通道,通常简称为RGB。每一个颜色都可以用一个矩阵来表示。如果这里rgb都采用的是224*224*224的矩阵,将所有元素拉成一维向量,则输入为224*224*3行的一维向量。

如果一共有1000类,则拉直后采用全连接网络, 全连接Linear(224*224*3, 1000),但是这样一来,参数量就过大,有224*224*3*1000 + 1000个参数,容易导致过拟合,故一般不直接采取拉直的方法,而是先经过卷积层和池化层降低特征图尺寸(减少参数量)后,再拉直进入全连接层。

二、卷积神经网络(Convolutional Neural Networks,简称CNN)

卷积 Convolution

有大小图(矩阵),小的为卷积核,大的为原始图(也是一种特征图),红色代表1,黑色代表-1,将卷积核依次与特征图的局部矩阵(同卷积核大小相同)对应点相乘,元素相同的位置相乘的结果就是1,不同的结果就是-1,然后将得到的元素值加起来得到新特征图的一个像素值(即将两个矩阵进行对应点相乘并求和)。例如特征图的前3行前3列和卷积核点积再相加得数值7,数值越大,说明该局部图越像小图,将所有对比结果又组成一个新的矩阵,即新的特征图,它可以继续被卷积。

例如,我们需要判断一张动物图片类别,我们只需将一个鸟嘴的卷积核去在特征图上卷积,直到匹配到最符合的鸟嘴,即可判断。

我们的目标就是如何将卷积核变得像我们想要的(通过模型去训练学习),最后得到一个有意义的特征图

不论是卷积核还是特征图都是彩色图片,也就是三个矩阵,这里卷积核的感受野(大小)是3*3,所以每一次卷积都一共进行了3*3*3=27次对应点相乘,27个值相加得到一个值,一共可以卷积16次,即最终得到一张4*4的新特征图。

可以有多个卷积核,例如鸟的嘴巴,眼睛都可以作为卷积核去卷积,不同的卷积核可以卷出不同的特征图

其实,卷积的本质也是全连接的过程,如下图,我们把特征图拉直成一维,其实每一次卷积都是相当于全连接的特征与权重相乘过程,卷积核元素就是权重,但是卷积的过程使用的参数是重复使用的,卷积的参数量少,所以卷积不容易过拟合

零填充 Zero padding——卷积完特征图尺寸不变 / 增大 的方法

Zero padding 是卷积神经网络(CNN)中的一种技术,用于在输入图像的边缘添加额外的像素。这些额外的像素通常被设置为零(0),因此得名“zero padding”。Zero padding 的主要目的是在进行卷积操作后保持输出图像(特征图)的尺寸不变/增大,或者在某些情况下调整输出图像的尺寸。

在没有 padding 的情况下,卷积操作会导致输出图像的尺寸小于输入图像。这是因为卷积核在图像上滑动时,每次只能覆盖图像的一部分,而且通常会在图像边缘留下一些未被覆盖的区域。随着卷积核的不断滑动,这些未覆盖区域会逐渐累积,导致输出图像的尺寸缩小。

卷积的层数与参数量(权重w)

如下图,假如原始图片是224*224*3的图片,有5个不同部位的卷积核都是3*3*3,即经过一层卷积,得到了5张224*224的特征图,将5张特征图叠起来,变成一张224*224*5的特征图,继续卷积,这样的一次卷积过程被称为一层卷积,第二层的卷积必须是深度为5的卷积核。

卷积核参数量 = 一套卷积核的像素点数量(权重w),例如这里第一层的参数量为3*3*3*5。本来每个卷积核还包括一个偏置b,但是一般卷积神经网络参数量忽略bias,因为它们对模型的学习能力和复杂度的影响相对较小。

卷积核深度 = 原始图片(特征图)深度

输出特征图的数量 = 卷积核数量

卷积特征图尺寸计算公式(基于扩大步长方法)

PS: /S时向下取整

特征图尺寸减小的方法

一、扩大步长stride

前面提到的卷积过程都是卷积核每次移动一格,可以通过每次移动多格使得特征图变小

常常在卷积层,stride和padding都是同时出现的两个重要参数,共同影响着特征图尺寸(见特征图尺寸公式)

二、池化pooling

池化(Pooling)是卷积神经网络(CNN)中的一个操作,它用于降低特征图(feature maps)的空间尺寸,同时保留重要的特征信息。池化层通常位于卷积层之后,可以降低数据的维度,这有助于减少后续层中的参数数量和计算量,提高计算效率,防止过拟合,并增强模型对输入图像中位置变化的鲁棒性。

池化操作的主要类型包括:

  1. 最大池化(Max Pooling)(最常用)

    • 最大池化是最常见的池化操作。它将输入特征图划分为不重叠的区域(通常是2x2或3x3的窗口),然后在每个区域内取最大值作为输出。这有助于捕捉最显著的特征。
  2. 平均池化(Average Pooling)

    • 平均池化与最大池化类似,但它计算的是每个区域内所有值的平均值。这种方法试图保留区域内的平均特征信息。

拉直后全连接

当特征图的尺寸变得很小时,可以采用之前的拉直flatten,将特征图拉成一维向量,之后进全连接网络(一开始不能直接拉直是因为参数量过大容易导致过拟合),得到一组向量,再通过softmax激活函数,从而得到最终的类别概率向量的形式

交叉熵损失 Cross-Entropy Loss

分类问题中,当经过全连接层,得到了一组输出的特征向量,但是并不是概率的形式,需要通过softmax激活函数,使向量变为概率的分布形式,即输出预测值y^,再和标签y计算出交叉熵损失。而预测的概率分布中,哪个下标对应的概率越高,就代表着预测的类别,最后再跟真实类别作比较看是否符合,遍历完一轮得出准确率。

交叉熵损失计算案例

图片经过卷积神经网络的特征提取器(卷积层和池化层)再拉直后,输出的是一个向量(特征),所以图片经过cnn的过程就是提取特征的过程,全连接层(分类头)通常用于在特征提取之后进行最终的分类或回归,因为不同的数据集有不同的种类数,种类数决定了最后一维向量的维度,再变成概率分布的形式。

基于CNN的神经网络

卷积神经网络(CNN)是一种深度学习架构,它在图像和视频识别、自然语言处理等领域取得了巨大成功。CNN专门设计用于处理具有网格结构的数据,如图像(2D网格)和时间序列数据(1D网格)。CNN的核心思想是利用卷积层自动从输入数据中学习空间层次结构的特征。

CNN的主要组成部分包括:

  1. 卷积层(Convolutional Layer)

    • 通过卷积操作提取输入数据的局部特征。
    • 使用一组可学习的卷积核(或滤波器)在输入数据上滑动,计算点积来产生特征图(feature maps)。
    • 卷积层有助于捕捉图像中的边缘、纹理等局部信息。
  2. 激活函数(Activation Function)

    • 引入非线性,使得网络能够学习复杂的特征表示。
    • 常用的激活函数包括ReLU(Rectified Linear Unit)、tanh和sigmoid。
  3. 池化层(Pooling Layer)

    • 降低特征图的空间尺寸,减少参数数量和计算量。
    • 提高特征的空间不变性,常用的池化操作包括最大池化和平均池化。
  4. 全连接层(Fully Connected Layer)

    • 将卷积层和池化层提取的特征映射到最终的输出,如分类标签。
    • 全连接层通常位于网络的末端,每个神经元与前一层的所有激活值相连。
  5. 损失函数(Loss Function)

    • 衡量模型预测与真实标签之间的差异。
    • 交叉熵损失是分类任务中常用的损失函数。

CNN的训练过程(同之前):

  • 前向传播:输入数据通过网络,通过卷积层、激活函数、池化层和全连接层,最终得到预测结果
  • 损失计算:根据损失函数计算预测结果与真实标签之间的差异。
  • 梯度回传(反向传播):通过梯度下降算法,计算损失函数关于网络权重的梯度,并更新权重以最小化损失。
  • 参数更新:使用优化算法(如SGD、Adam等)来调整网络参数。

CNN的优势在于其能够自动学习特征,无需手动特征工程,并且对图像的平移、缩放和旋转具有一定的不变性。此外,CNN的参数共享特性使得模型在处理图像时更加高效。随着深度学习的发展,CNN的结构也在不断演化,出现了如VGGNet、ResNet、Inception等多种先进的网络架构。

CNN的发展

AlexNet

AlexNet的主要特点包括:

  1. 架构

    • AlexNet包含8层,其中包括5个卷积层和3个全连接层,共6000多万个参数量
    • 使用了ReLU激活函数,这在当时是一个相对较新的选择,它有助于解决梯度消失问题并加速训练。
  2. 池化层

    • 使用了最大池化层来降低特征图的空间尺寸,同时保留了重要的特征。
    • 池化层有助于减少计算量并提高模型的泛化能力。
  3. 正则化

    • 为了减少过拟合,AlexNet使用了Dropout技术(也是一种正则化技术),随机丢弃(即暂时移除)网络中的一些神经元。
    • 此外,AlexNet还使用了L2正则化。
  4. 局部响应归一化(LRN)

    • 卷积层之后使用了局部响应归一化,这是一种归一化技术,有助于提高模型的训练速度。

AlexNet的成功不仅在于其在ImageNet上的优异表现,还在于它展示了深度学习在处理复杂视觉任务上的潜力,从而激发了后续一系列更深层次和更高性能的网络架构的发展,如VGGNet、GoogLeNet(Inception)、ResNet等。AlexNet成为了深度学习和计算机视觉领域的一个里程碑。

PS知识拓展

Dropout技术(一种正则化技术)

训练过程中,Dropout通过在每次迭代时随机“丢弃”(即暂时移除)网络中的一些神经元(包括它们的连接),来减少网络的复杂度,防止过拟合

归一化(Normalization)

数据预处理的一个重要步骤,它将数据按比例缩放,使之落入一个小的特定区间(正态分布的标准化就是一种归一化)。归一化的目的是改善不同特征量纲之间的可比性,确保模型训练的稳定性和效率。在深度学习中,归一化通常用于输入数据,以加速训练过程并提高模型的性能,确保模型的稳定性。

在深度学习中,归一化对于提高训练速度和模型收敛性非常重要。例如,对于卷积神经网络(CNN),通常需要将输入图像的像素值归一化到0到1之间,或者使用Z得分归一化。对于循环神经网络(RNN)处理的序列数据,归一化可以帮助稳定梯度和加速训练。

归一化的选择取决于数据的特性和模型的需求。在实际应用中,可能需要尝试不同的归一化方法,以找到最适合特定任务的那一种。

其中,批量归一化 BN(batch normalization)是指,不仅仅在数据预处理时对输入进行一次归一化,而是每经过一层网络后,都对数据进行一次归一化,使得输出的分布更加稳定(能解决梯度消失和梯度爆炸),从而加速训练过程并减少对初始化权重的敏感度。

梯度消失(Vanishing Gradients)和 梯度爆炸(Exploding Gradients)

梯度消失是深度神经网络训练中的一个问题,尤其是在训练具有大量层(深层网络)的模型时。这个问题指的是反向传播过程中,梯度值变得非常小,以至于它们对网络中较浅层的权重更新几乎没有影响。随着层数的增加,这种梯度值的指数衰减会导致网络的前面几层几乎不学习或学习得非常缓慢

梯度爆炸是指在深度神经网络中,梯度在反向传播过程中逐渐变得非常大,以至于超过了数值稳定的范围。当梯度非常大时,权重更新也会非常大,这可能导致网络权重的数值不稳定,甚至导致模型训练过程中的数值溢出

梯度消失和梯度爆炸的主要原因包括:

  1. 连乘效应:在反向传播过程中,梯度是通过网络的每一层从输出层向输入层逐层传递的。如果每层的激活函数导数都小于1(例如,Sigmoid或Tanh函数),那么随着层数的增加,梯度的连乘将导致最终的梯度值非常小,相反大于1则会爆炸

  2. 权重初始化:如果权重初始化不当,也可能导致梯度消失和梯度爆炸(初始化过大)。例如,如果所有权重都初始化为相同的值,那么在训练过程中,这些权重可能会更新得非常相似,导致梯度在反向传播时相互抵消。

  3. 网络结构过深:在深度神经网络中,由于连续的层级结构,梯度需要通过多层反向传播回到网络的输入层。如果网络层数过多,使用激活函数(如Sigmoid或Tanh)可能会导致梯度在反向传播过程中逐渐减小,最终接近于零,即梯度消失。

解决方法

  • 权重初始化策略:采用合适的权重初始化方法,比如Xavier初始化和He初始化,这些方法可以确保在网络初始化阶段,每一层输出的方差大致保持一致,从而防止梯度过于稀疏或密集。
  • 批量归一化:在每层神经网络中引入BN层,它能在训练过程中调整每层输入的均值和方差,有助于稳定训练过程,减少梯度消失和爆炸的风险。
  • 残差连接:如ResNet中提出的跳过连接机制,它允许信号直接从浅层传递到深层,而不必经过层层间的梯度累积,从而解决了深度网络中的梯度消失问题。
  • (解决梯度消失)使用ReLU及其变体:ReLU激活函数在正区间内具有恒定的导数(为1),这有助于缓解梯度消失问题。

AlexNet模型架构

Conv2d是卷积层,一共传入5个参数(左边),Pool最大池化层传入两个参数,第一个是局部取最大的尺寸是3*3,第二个参数是步长stride,最后他这个池化层会使得特征图的尺寸长度减半(元素数量为四分之一)

注意特征图尺寸的变化以及每一层的参数量

# Alexnet模型
class myAlexnet(nn.Module):
    def __init__(self):
        super(myAlexnet, self).__init__()

        self.conv1 = nn.Conv2d(3, 64, 11, 4, padding=2)  # 卷积层
        self.pool1 = nn.MaxPool2d(3,2)      # 最大池化层

        self.conv2 = nn.Conv2d(64, 192, 5, 1, padding=2)
        self.pool2 = nn.MaxPool2d(3,2)

        self.conv3 = nn.Conv2d(192, 384, 3, 1, 1)
        self.conv4 = nn.Conv2d(384, 256, 3, 1, 1)
        self.conv5 = nn.Conv2d(256, 256, 3, 1, 1)
        self.pool3 = nn.MaxPool2d(3, 2)
        self.pool4 = nn.AdaptiveAvgPool2d(6)    # 自适应平均池化层

        self.fc1 = nn.Linear(9216, 4096)    # 全连接层
        self.fc2 = nn.Linear(4096, 4096)
        self.fc3 = nn.Linear(4096, 1000)
    # 前向传播
    def forward(self, x):
        x = self.conv1(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = self.pool2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x = self.conv5(x)
        x = self.pool3(x)
        x = self.pool4(x)
        # x.size()[0]:获取张量的第一个维度的大小,这通常对应于批次大小(batch size),也就是样本数量。
        # -1:在.view()方法中使用-1告诉PyTorch自动计算这个维度的大小,以便保持张量中元素的总数不变
        x = x.view(x.size()[0], -1)
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)

        return x
# 实例化
mymodel = myAlexnet()

# 卷积神经网络的初始参数:batch(样本数),channel(深度), Height * Width
input = torch.ones((4, 3, 224, 224))

out = mymodel(input)

print(out.shape)

# 获取模型的参数量,Alexnet一共有6000多万个参数量
def get_parameter_number(model):
    total_num = sum(p.numel() for p in model.parameters())
    trainable_num = sum(p.numel() for p in model.parameters() if p.requires_grad)
    return {'Total': total_num, 'Trainable': trainable_num}

VggNet

vggnet主要特点(针对alexnet的改进)
  1. 更深的网络结构:VGGNet的主要贡献之一是展示了通过增加网络深度可以显著提高性能。这种深度的增加使得网络能够捕捉更复杂的特征,从而在图像识别任务中取得了更好的结果。共有1亿多的参数量

  2. 小卷积核的使用:VGGNet在整个网络中坚持使用3x3的小卷积核,这种设计选择使得网络能够通过堆叠多个小卷积层来模拟大卷积核的效果,同时减少了每一层的参数数量和计算复杂度。

vggnet 13架构

Resnet(残差网络)

如果只是简单地堆积卷积层和池化层,堆叠在20层的网络结构的时候,模型的训练错误在1%-2%左右,但是当训练的层数增加到56层(很深)的时候训练的错误在7%-8%。很明显通过卷积层和池化层的增加是不行的。

原因就是深层网络很容易引起梯度爆炸或者梯度消失的问题。但是我们发现,即使调整了初始化权重、使用了BN(batch normalization)以及relu等,缓解梯度爆炸和梯度消失后,网络能够收敛了,但是随着模型的加深,又出现了准确率下降(“退化”)问题。而如何解决在浅层网络不断加深网络的同时,既不会出现梯度爆炸与消失,也不会使得效果变差呢?resnet的残差模块能同时解决这些问题

残差连接与残差块

网络随着深度达到一定层,准确率会变差,那么如果只是在浅层的网络加上一层将输入直接输出,即恒等映射,这样最少不会使网络性能变得更差,基于此,有了残差块的概念

在ResNet中,每个残差块包含两条路径:一条是主路径,包含一系列的卷积层和其他神经网络层;另一条是“恒等映射”路径,它直接将输入x跳过这些层传递到下一阶段,这个连接即残差连接(跳过连接 Identity Shortcut)。这一整个小单元被称作“残差块”。如果主路径的输出是H(x),那么最后整个残差块的输出是 F(x) = H(x) + x

残差(Residual,指的是主路径的输出与输入的差值 H(x) - x,通过学习残差,即输出与输入的差异,而不是直接学习H(x),能通过残差连接来优化网络的输出(具体如何实现的不用管),这也是基于论文作者的一个假设:“对于深度神经网络来说,学习输出与输入之间的差异(即残差)可能比直接学习输出本身要容易得多。”,且事实也是如此,因为有了恒等连接,输出方能直接获得H(x)以及x,故能直接地获取它们的差值。

训练过程中,损失函数的梯度会通过整个网络进行反向传播对于残差块(Residual Blocks),梯度会流过残差块的每个层,包括跳过连接。如果残差块中的卷积层和其他层能够学习到有用的特征,那么它们将有助于减少损失函数的值,从而在反向传播过程中,这些层的权重将被更新以进一步减少损失。

然而,如果这些层没有带来任何正向的贡献(即没有使loss变得更小),网络可以“学习”通过调整权重,使主路径的输出接近于0(即H(x)≈0),从而使总输出F(x)接近于恒等路径的输出x,即跳过这些层,从而使网络的效果等同于没有这些层(即执行恒等映射)。这样,网络可以自适应地决定是否通过这些额外的层,或者是否直接使用跳过连接,从而最少保证了网络不会随着深度的加深准确率变差,即解决了“失真”的问题。

反向传播过程中,如果残差块中的某些层(如sigmoid函数)会导致梯度减少,恒等连接允许梯度绕过这些层,直接回传到较早的层。这样,即使某些层会导致梯度减少,整体梯度也不会受到影响,从而有助于防止梯度消失问题(也能防止梯度爆炸,具体原因不探讨)。(其实从求偏导的角度来看,残差层的输出F(x) = H(x) + x比正常多了一项,也能使得梯度不会变的太小,也能防止梯度消失

残差块的设计不会增加任何参数,增加网络复杂性,只是多了一个加法过程

F(x) = H(x) + x中,如果x和H(x)特征图尺寸和通道数(深度)不一致,则可以通过padding来使尺寸一致,通道数则可以通过使用1*1的卷积核对x卷积,来加深通道数(通道数等于卷积核数量,所以可以任意改变),如果一致则特征图对应相加即可

这就是一个resnet网络,虚线部分指的是上面提到的使用1*1卷积核改变尺寸

  • 18
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值