基础知识

简单说明下机器学习和深度学习的主要区别:

  • 模型结构:一般深度学习基于深度神经网络架构较为复杂化
  • 自动提取特征:传统机器学习需要人工构造特征但深度学习基于神经网络自动提取特征
  • 数据量:深度学习需要大量的数据集来训练多层神经网络

反向传播算法

反向传播(Backpropagation)算法是一种用于计算神经网络中各个参数梯度的方法,它基于链式法则梯度下降算法,下面是反向传播算法的基本步骤:

  1. 前向传播(Forward Propagation):
    • 输入一个样本,通过神经网络的前向传播计算得到预测输出
    • 逐层计算每个神经元的输出值,直至输出层
    • 在前向传播过程中,将每一层的输入、权重和激活函数的结果保存下来,用于后续的反向传播计算
  2. 计算损失函数(Loss Calculation):
    • 根据预测输出和真实标签计算损失函数的值
    • 常见的损失函数包括均方误差(Mean Squared Error)、交叉熵损失(Cross-Entropy Loss)等
  3. 反向传播计算梯度(Backward Propagation):
    • 从输出层开始,根据链式法则计算每个参数的梯度
    • 逐层向后传播,通过链式法则将上一层的梯度乘以当前层的局部梯度,得到当前层的梯度
    • 根据梯度下降算法更新网络参数
  4. 参数更新(Parameter Update):
    • 根据计算得到的梯度值,使用梯度下降算法或其变种方法来更新网络的参数
    • 常见的梯度下降算法包括随机梯度下降(Stochastic Gradient Descent,SGD)、动量法(Momentum)、Adam等
  5. 重复以上步骤
    • 对于每个训练样本,重复执行前向传播、损失计算、反向传播和参数更新的步骤
    • 迭代训练过程直到达到预设的停止条件,如达到最大迭代次数或损失函数收敛

注意,反向传播算法会重复利用前向传播中存储的中间值,以避免重复计算,因此,需要保留前向传播的中间结果,这也会导致模型训练比单纯的预测需要更多的内存(显存)

同时这些中间结果占用内存(显存)大小与网络层的数量和批量(batch_size)大小成正比

因此使用大batch_size训练更深层次的网络更容易导致内存不足(out of memory)的错误

反向传播算法通过有效地计算每个参数的梯度,使得神经网络可以通过梯度下降等优化方法来不断更新参数以最小化损失函数

这样,神经网络可以逐步优化自身的权重和偏置,从而提高模型的性能和准确度

深度学习优化存在许多挑战,其中一些最令人烦恼的是局部最小值、鞍点和梯度消失

  • 局部最小值(local minimum): 对于任何目标函数,如果在处对应的值小于在附近任何其他点的值,那么可能是局部最小值

    如果处的值是整个域上目标函数的最小值,那么是全局最小值

  • 鞍点(saddle point): 指函数的所有梯度都消失但既不是全局最小值也不是局部最小值的任何位置

  • 梯度消失(vanishing gradient): 因为某些原因导致目标函数的梯度接近零(即梯度消失问题),是在引入ReLU激活函数和ResNet之前训练深度学习模型相当棘手的原因之一

在深度学习中,大多数目标函数都很复杂,没有解析解,因此,我们需使用数值优化算法

梯度消失和爆炸

梯度不稳定的原因:核心在于链式法则前面层上的梯度是来自后面层上梯度乘积。当存在过多的层时,就会出现梯度不稳定场景,比如梯度消失梯度爆炸

梯度爆炸

在反向传播过程中需要对激活函数进行求导,如果导数大于1,那么随着网络层数的增加梯度更新将会朝着指数爆炸的方式增加这就是梯度爆炸

梯度消失

同样如果导数小于1,那么随着网络层数的增加梯度更新信息会朝着指数衰减的方式减少这就是梯度消失

根本原因

梯度消失和梯度爆炸,其根本原因在于反向传播训练法则,属于先天不足

计算权值更新信息的时候需要计算前层偏导信息,因此如果激活函数选择不合适

比如使用sigmoid,梯度消失就会很明显了,如果使用sigmoid作为损失函数,其梯度是不可能超过0.25,这样经过链式求导之后,很容易发生梯度消失

解决方案

梯度消失梯度爆炸是在神经网络训练过程中常见的问题,可能导致模型收敛困难无法有效更新权重。下面是梯度消失和梯度爆炸的产生原因和解决方法:

梯度消失(Gradient Vanishing)

原因:在深层神经网络中,梯度通过多个层传递时可能会逐渐衰减。特别是使用具有小梯度的激活函数(如Sigmoid、Tanh)时,梯度消失问题更为严重

解决方法:

  • 大梯度的激活函数:选择具有较大梯度的激活函数,如ReLU、Leaky ReLU等
  • 参数初始化:合理初始化权重,避免初始梯度过小或过大
  • 批归一化(Batch Normalization):通过对每一层的输入进行归一化,可以使得激活函数输入值的分布更稳定,有助于缓解梯度消失问题
  • 残差连接(Residual Connections):引入跨层的直接连接,使得梯度可以更容易地通过网络传播,例如ResNet中的残差连接结构

梯度爆炸(Gradient Explosion)

原因:在某些情况下,梯度可能会指数级增长,导致数值溢出

解决方法:

  • 梯度裁剪(Gradient Clipping):限制梯度的范围,通过设置阈值或缩放梯度来防止梯度爆炸
  • 参数初始化:合理初始化权重,避免初始梯度过大
  • 使用稀疏连接:减少网络中的连接数量,可以降低梯度爆炸的风险
  • 更小的学习率:降低学习率,使得梯度更新更加稳定

正则化方法可以在一定程度上缓解梯度爆炸和梯度消失的问题

总的来说,解决梯度消失和梯度爆炸问题的方法包括选择合适的激活函数、参数初始化策略、批归一化、残差连接、梯度裁剪等

需要根据具体情况综合考虑并适当调整这些方法以提高训练的稳定性和效果

泛化问题

过拟合(Over fitting)欠拟合(Under fitting)是指机器学习模型在训练过程中对训练数据的拟合程度不合适的问题

过拟合和欠拟合

过拟合

现象

过拟合指的是模型过于复杂,过度适应了训练数据的特征,导致在新的未见过的数据上表现不佳

过拟合的表现是在训练数据上表现出较好的拟合效果,但在测试数据上的表现较差

过拟合的原因可能是模型过于复杂,参数过多,导致模型具有很强的记忆能力而忽略了数据的真实规律

产生原因

  1. 模型太复杂: 训练集的数量级和模型的复杂度不匹配,训练集的数量级要小于模型的复杂度
  2. 特征分布不一致: 训练集和测试集特征分布不一致
  3. 学习到噪音: 样本里的噪音数据干扰过大,大到模型过分的记住了噪音特征,而忽略了真实的输入输出间的关系
  4. 迭代过多: 权值学习迭代次数足够多(Over training),拟合了训练数据中的噪声和训练样例中没有代表性的特征

解决方案

  1. 简化模型: 使其适合自己训练集的数量级(缩小宽度和减小深度),使模型更好地学习数据的真实分布
  2. 数据增强: 训练集越多,过拟合的概率越小。在计算机视觉领域中,增广的方式是对图像旋转,缩放,剪切,添加噪声等
  3. 正则化: 指通过引入额外新信息来解决过拟合问题的一种,这种额外信息通常的形式是模型复杂性带来的惩罚度。正则化可以保持模型简单
  4. dropout: 在训练的时候让神经元以一定概率不工作
  5. Early stopping: 迭代次数截断的方法来防止过拟合的,即在模型对训练数据集迭代收敛之前停止迭代来防止过拟合

欠拟合

现象

欠拟合指的是模型过于简单,不能很好地拟合训练数据的特征,导致在训练数据和测试数据上的表现都不佳

欠拟合的表现是模型无法捕捉到数据中的复杂关系或规律,无法很好地拟合训练数据

欠拟合的原因可能是模型过于简单,参数过少,无法充分学习数据的特征

产生原因

  1. 模型复杂度不足:模型的复杂度不足以捕捉数据中的复杂关系。例如,线性模型无法很好地拟合非线性数据,导致欠拟合
  2. 特征提取不足:特征提取不足意味着模型无法从原始数据中提取出有用的特征。如果特征不具备较强的区分性,模型就无法很好地进行拟合
  3. 数据量不足:当训练数据较少时,模型难以学习数据的真实分布和规律。有限的数据样本可能无法提供足够的信息来训练一个复杂的模型
  4. 过度正则化:过度正则化可以导致模型过于简单,无法很好地拟合训练数据。例如,强制施加较强的正则化项或使用较高的正则化系数会限制模型的灵活性
  5. 数据噪声:当训练数据中存在噪声或错误标签时,模型可能会过于关注这些异常样本,从而导致欠拟合

解决方案

  1. 特征工程: 欠拟合是由于学习不足,可以考虑添加特征,从数据中挖掘更多的特征,有时候还需要对特征进行变换,使用组合特征和高次特征
  2. 更强的模型: 模型简单也会导致欠拟合,如线性模型只能拟合一次函数的数据,尝试使用更高级的模型有助于解决欠拟合
  3. 调整超参数: 调整模型的超参数,如学习率、正则化系数等,以获得更好的模型拟合效果

核心网络层

全连接层

等待…

Conv卷积操作

一文详解各种卷积操作

pytorch中卷积网络的几种卷积和池化

pytorch官网关于cnn的说明

卷积操作是神经网络中常用的操作之一,特别是在图像处理和计算机视觉任务中

卷积操作通过将输入数据与卷积核(也称为滤波器)进行逐元素相乘,并将结果进行求和,从而产生输出特征图

在卷积神经网络(Convolutional Neural Network,CNN)中,卷积操作用于提取输入数据中的局部特征,它利用了特征的局部相关性平移不变性

  • 局部相关性: 局部相关性指的是每个神经元只与输入数据的一小块区域连接,可以捕捉到输入数据的局部特征,减少了参数数量,降低了计算复杂度
  • 平移不变性: 平移不变性指的是它对输入数据的平移具有不变性,卷积层可以通过共享权重和局部连接的方式来提取特征,从而使得对于不同位置的物体能够产生相似的特征表示

卷积输出大小计算公式

其中表示输入的特征大小,是填充,是卷积核大小,是步长

一维卷积在线可视化

二维卷积在线可视化

卷积之间的关系脉络.

普通卷积

深度学习中卷积的概念与信号处理领域的卷积相似(只是深度学习的卷积在运算过程中的滤波器不经过翻转),卷积核以一定的步长在输入图片上滑动,每一步都将对应元素相乘后求和的过程,如下图所示

基本一维卷积示例

卷积核大小(kernel_size)

卷积核大小定义了卷积的视图,根据卷积核的大小,常见的卷积尺寸有1×1卷积、3×3 卷积、5×5卷积、7×7卷积等

  • 卷积:通常用于输出维度的升维或降维。若特征图是尺寸是,卷积核尺寸是,输出通道尺寸是。当我们将卷积结果连接在一起时,可以得到的输出,从而实现升维或降维的功能
  • 卷积:由于大尺寸的卷积核的参数量较大,研究人员发现两个卷积的堆叠,感受野等同于一个卷积,但是参数量却减少了,所以从VGG的时代开始,基本后面的网络都离不开它的身影
  • 卷积:卷积核越大,感受野越大,看到的图片信息越多,所获得的全局特征越好。但是这样参数很多,会导致计算量暴增,层次少不利于模型深度的增加,表达能力弱。所以我们会看到在早期的网络会出现大卷积核的堆叠,或者当下研究人员一般将大尺寸卷积放在对输入图片的初始操作处(同理)

步长(stride)

核的步长定义了卷积核在图像中移动的每一步的大小,代表提取的精度,通常为1,也可以用大于等于2的步长,对图像进行下采样,替代池化操作

填充(padding)

卷积核与输入图像的尺寸不匹配,这时就需要填充图像,例如输入图片尺寸为,卷积核的大小为

如果不进行填充,步长为1的话,当卷积核沿着图片滑动后只能滑动出一个的图片出来,卷积后的图片越变越小,且输入图片边缘像素只被计算过一次

而中间像素会被卷积计算多次,意味着丢失图像角落信息,所以为了避免这种情况,需要先对原始图片做边界填充处理

3D卷积

3D卷积的卷积核可以在输入图像的3个方向,即图像的高度,宽度,深度上移动。并与二维卷积类似,在每个位置各元素先相乘再相加,最后输出一个3D数据

基本3D卷积示例

卷积特性:相比于普通的二维卷积,多了一个维度(深度),可以把这个深度当作视频中的连续帧,或者是立体图像中的不同的切片。但是其参数量较大,会延缓网络的推理速度

应用场景:3D卷积常应用在视频分类、医学影像、点云处理等领域。比如经典的VoxelNet网络就采用3D CNN提取点云的体素特征做目标检测任务

扩张卷积(膨胀、空洞)

扩张卷积(Dilated Convolution),也称为空洞卷积(Atrous Convolution),最早是由DeepLab团队提出的

DeepLab是由Google Brain开发的一种用于图像语义分割的深度学习架构,随后,扩张卷积被广泛应用于其他计算机视觉任务,如图像超分辨率目标检测图像生成图像修复

扩张卷积的主要目的是增加卷积操作的感受野,从而捕捉更大范围的上下文信息

传统的卷积操作具有固定的卷积核尺寸和步幅,限制了感受野的大小。而扩张卷积通过在卷积核的元素之间引入固定的间隔(扩张率或空洞率),使得卷积核在输入特征图上的采样间隔扩大,从而实现感受野的扩大

扩张卷积最初用于图像语义分割任务,旨在提高分割结果的精度。语义分割需要将图像中的每个像素分类到不同的语义类别中,因此需要充分考虑像素周围的上下文信息

通过使用扩张卷积,DeepLab团队可以更好地捕捉像素之间的长距离依赖关系,提高分割模型对细粒度边界和小尺寸物体的感知能力

它在这些任务中的应用主要是为了增加感受野、提高分辨率和实现多尺度特征融合,以增强模型的感知能力和表达能力

基本空洞卷积示例

扩张的好处:使得在相同的计算成本下,避免因池化损失信息而增大了感受野

膨胀卷积使用的方法

  1. 连续使用多个膨胀卷积时应该如何设计它的膨胀系数
  2. 将膨胀系数设置为锯齿形状,例如[1,2,3,1,2,3]
  3. 公约数不能大于1,比如可以是[1,2,3],而不是[2,4,8]

分组卷积

分组卷积(Group Convolution)

Depthwise卷积与Pointwise卷积

分组卷积最开始被使用在经典入门卷积神经网络AlexNet上,用于解决显存不足的问题。在现在被广泛用于各种轻量化模型中,用于减少运算量和参数量,其中应用最广的就是深度可分离卷积(Depthwise Separable Convolution)

Depthwise卷积(深度卷积)和Pointwise卷积(逐点卷积)

Depthwise卷积(深度卷积)和Pointwise卷积(逐点卷积)是MobileNet等轻量级神经网络中常用的卷积操作卷积,合起来被称作Depthwise Separable Convolution(参见Google的Xception),该结构和常规卷积操作类似,可用来提取特征,但相比于常规卷积操作,其参数量和运算成本较低。所以在一些轻量级网络中会碰到这种结构如MobileNet

可以将深度卷积和逐点卷积结合使用,作为分组卷积的一种实现方式,以提高模型的计算效率和参数效率

深度卷积用于捕捉空间上的相关信息,逐点卷积用于整合和转换通道间的特征关系。这样的组合可以在一定程度上减少计算量,并保持模型的表达能力

传统和分组卷积的比较

  • 在传统的卷积操作中,输入特征图的每个通道都与卷积核的每个通道进行卷积运算,输出的特征图是所有通道的叠加
  • 在分组卷积中,将输入特征图和卷积核分成多个组,每个组中的通道进行独立的卷积运算,最后将各组的输出特征图进行连接,得到最终的输出结果

普通卷积和分组卷积比较

左图是普通的卷积,右图是分组卷积

  • 对于尺寸为的输入矩阵,当标准卷积核的尺寸为,共有个标准卷积核时,标准卷积会对完整的输入数据进行运算,最终得到的输出矩阵尺寸为 。这里我们假设卷积运算前后的特征图尺寸保持不变,则上述过程可以展示为左图

  • 分组卷积中,通过指定组数来确定分组数量,将输入数据分成组。需要注意的是,这里的分组指的是在深度上进行分组,输入的宽和高保持不变,即将每个通道的数据分为一组。因为输入数据发生了改变,相应的卷积核也需要进行对应的变化,即每个卷积核的输入通道数也就变为了,而卷积核的大小是不需要改变的

    同时,每组的卷积核个数也由原来的变为。对于每个组内的卷积运算,同样采用标准卷积运算的计算方式,这样就可以得到组尺寸为的输出矩阵,最终将这组输出矩阵进行拼接就可以得到最终的结果。这样拼接完成后,最终的输出尺寸就可以保持不变,仍然是。分组卷积的运算过程如右图所示

分组卷积的主要优点是减少了计算量和参数数量,因为每个组内的卷积操作是独立进行的,相当于将整个卷积操作拆分成了多个较小的卷积操作

这在一些计算资源有限的情况下,如移动设备或嵌入式系统中,可以显著减少计算成本,提高模型的速度和效率

需要注意的是,分组卷积的使用需要在考虑计算效率的同时权衡模型性能。分组卷积可能会损失一定的表示能力,特别是对于那些具有跨通道相关性的特征

因此,在设计网络结构时,需要根据任务的需求和资源的限制来选择合适的分组数和组内通道数,以在效率和准确性之间找到平衡点

反卷积(转置)

UNet Architecture Breakdown

Pytorch 转置卷积

转置卷积(Transposed Convolution),也称为反卷积(Deconvolution),是卷积神经网络中常用的一种操作

它与标准卷积操作相反,用于将低维特征映射扩展为高维特征映射

在传统的卷积操作中,输入特征图通过卷积核进行卷积运算,得到输出特征图。而转置卷积则是通过对输出特征图应用反向卷积操作,以重建高维特征映射

转置卷积常用于以下几个任务和应用中:

  1. 图像生成:转置卷积被广泛应用于图像生成任务,如图像生成、图像修复等。通过将低维特征映射转换为高维特征映射,可以生成具有更高分辨率和更多细节的图像
  2. 图像分割:在图像分割任务中,转置卷积常用于将低分辨率的语义特征映射恢复到与输入图像相同的尺寸,以获得像素级别的分割结果
  3. 目标检测:转置卷积在目标检测任务中被用于生成高分辨率的特征映射,以便更准确地定位和识别目标

需要注意的是,转置卷积的名称可能会引起一些误解,因为它实际上并不是真正的卷积操作的逆运算。转置卷积的名称起源于其与卷积操作的相似性,但其计算过程与卷积并不完全相同

在神经网络中,我们经常需要上采样来提高低分辨率图片的分辨率。而转置卷积就可以作为一种通过卷积学习参数,从而获得最优上采样的方法

trans_conv_stride2

可视化解释

下图是一个的输入矩阵,用的卷积核进行没有填充,步长为1的卷积操作,结果是一个的矩阵

转置卷积示例步骤_1

我们将的卷积核重排为的形式(下图第一项),同时将的输入矩阵展开为的列向量的形式(下图第二项)。通过矩阵乘法得到一个的列向量,可以看出这个列向量正是由上图的卷积输出矩阵展开得到的,也就是说,我们可以将卷积操作写成矩阵乘法运算

转置卷积示例步骤_2

通过这样的操作,可以把16(的矩阵)个值映射为4(的矩阵)个值,那么将这个操作反过来,我们就可以把4(的矩阵)个值映射为16(的矩阵)

转置卷积示例步骤_3

最后将输出矩阵可以reshape为的形式

卷积特征:虽然转置卷积能够通过学习参数进行最优的上采样,但是实际应用中,研究人员往往更加倾向于使用线性插值的方式做上采样,效率更高

可分离卷积

空间可分离卷积

空间可分离卷积主要处理图像和卷积核的空间维度:宽度和高度

将一个卷积核划分为两个较小的卷积核,如将的卷积核分为的卷积核,再依次进行卷积

如此,则可以将一次卷积的9次乘法减少为两次卷积共6次乘法,减少计算量,从而加快网络运行速度

深度可分离卷积

深度可分离卷积不仅涉及空间维度,还对深度维度进行处理。它主要分为两个过程,分别为逐通道卷积逐点卷积

  1. 逐通道卷积: 逐通道卷积的卷积核与通道是一一对应的,所以输出的特征图片的深度和输入的深度完全一样

    逐通道卷积

  2. 逐点卷积: 逐点卷积的运算与常规卷积运算相似,它的卷积核的尺寸为为上一层的深度。它是将上一步的特征图在深度方向上进行加权相加,生成新的特征图,有几个卷积核就有几层新的特征图输出

    逐点卷积

卷积特性:深度可分离卷积的优势在于需要提取的属性越多,就能够节省越多的参数,减少计算量。最早出现在mobilenet中,也是用于轻量化网络的特征提取部分,使嵌入式部署的神经网络推理更快速

相较于传统的标准卷积,它只需要对每个通道进行卷积操作,而不是对每个通道和每个位置都进行卷积操作。因此,它能够在保持模型性能的同时,显著减少计算开销,特别适用于轻量级模型和计算资源受限的场景

可分离卷积常用于移动设备、嵌入式设备和计算资源有限的环境中,如移动端的图像分类、目标检测、语义分割等任务

通过采用可分离卷积,可以实现轻量级的模型结构,提高模型的计算效率和速度,同时降低模型的存储空间和内存消耗

可变形卷积

Deformable Convolutional Networks 2017

可变形卷积(Deformable Convolution)是一种具有自适应感受野的卷积操作,能够更好地捕捉图像中非刚性形变的特征。与传统的卷积操作相比,可变形卷积引入了可学习的偏移参数,用于调整卷积核在输入特征图上的采样位置

在传统的卷积操作中,卷积核的采样位置是固定的,对输入特征图的不同区域应用相同的采样模式。而可变形卷积通过在每个位置引入偏移参数,使得卷积核可以自适应地调整采样位置,从而适应不同区域的非刚性形变

思路

可变形卷积是一种卷积核内部点按不规则的方式组合,如下图所示

不规则卷积

(a)普通卷积采样的9个点(绿点);(b)(c)(d)都为可变形卷积,在普通卷积采样坐标上加上一个位移量(蓝色箭头),得到变形的采样位置(深蓝点)

对于输入的一张特征图,把普通卷积的过程分成两路,先通过上面一路学习得到offset;下面的可变形卷积是基于上面生成的offset,我们的卷积窗口将由规整的绿色窗口变成蓝色部分,然后再执行普通的卷积,这种实现方式相当于于比正常的卷积操作多学习了卷积核的偏移offset

可变性卷积

如下图所示,左边普通卷积方法没有提取到完整绵羊的特征,而右边的可变形卷积方法提取到了完整的绵羊的特征

可变性卷积和传统卷积比较

实现DCN中的两个问题QA

QA1: 如何将可变形卷积变成单独的一个层,而不影响别的层

在实际操作时,并不是真正地把卷积核进行扩展,而是对卷积前图片的像素重新整合,变相地实现卷积核的扩张。也就是说,实际上变的是每次进行卷积后得到的带偏移值的坐标值,根据这些坐标取像素点,然后双线性差值,得到新feature map,然后作为输出并成为下一层的新输入

QA2: 在前向传播实现可变性卷积中,如何能有效地进行反向传播

在图片像素整合时,需要对像素进行偏移操作,偏移量的生成会产生浮点数类型,而偏移量又必须转换为整形,直接对偏移量取整的话无法进行反向传播,这时采用双线性差值的方式来得到对应的像素

可变形卷积的使用程度取决于具体的应用场景和任务要求

  1. 目标检测:可变形卷积在目标检测任务中被广泛使用。由于目标在图像中可能存在尺度变化、形变等非刚性变化,传统的固定感受野的卷积核难以准确捕捉目标的细节和形状信息。可变形卷积通过引入可学习的偏移参数,能够自适应地调整感受野,从而提高目标检测的精度和鲁棒性
  2. 语义分割:对于语义分割任务,可变形卷积也被广泛使用。语义分割需要对图像中的每个像素进行分类,因此准确地捕捉像素周围的上下文信息至关重要。可变形卷积能够通过自适应调整采样位置来更好地捕捉非刚性形变的目标边界和细节,提高语义分割的精度和细节保留能力
  3. 人体姿态估计:在人体姿态估计任务中,可变形卷积也被广泛应用。人体姿态具有复杂的非刚性形变,传统的卷积操作往往无法准确地捕捉到人体关节的位置和姿态信息。通过引入可变形卷积,可以更好地建模人体的非刚性形变,提高姿态估计的准确性和鲁棒性

需要注意的是,可变形卷积的计算量较大,可能会增加模型的复杂性训练的难度

因此,它通常在需要对非刚性形变建模的任务中使用,并且在设计模型时需要根据具体情况进行权衡和选择

池化操作

卷积神经网络池化方法综述

那些鬼斧神工的池化操作,看完我炸裂!

池化的作用

  1. 抑制噪声,降低信息冗余
  2. 提升模型的尺度不变性旋转不变性
  3. 降低模型计算量
  4. 防止过拟合

池化回传梯度的原则是保证传递的loss(或者说梯度)总和不变

  1. 最大池化: 取每个块的最大值作为下一层的一个元素值,因此下一个元素的Loss只来源于这个最大值,因此梯度更新也只更新这个最大值,其他值梯度为0
  2. 平均池化: 将输入区域内的梯度均匀地分配给该区域中的每个位置。反向传播过程中,将梯度均匀分配给输入区域内的所有位置

池化输出大小计算公式

池化之间的关系脉络.

最大最小池化

定义

最大池化(Max Pooling): 选择输入区域中的最大值作为输出,忽略其他值

最小池化(Min Pooling): 选择输入区域中的最小值作为输出,忽略其他值

下图是最大池化的示例图

最大池化

重叠池化和非重叠池化

池化又分为重叠池化非重叠池化

  • 非重叠池化: stride=kernel size的情况
  • 重叠池化: stride<kernel size的情况

重叠池化相比于非重叠池化不仅可以提升预测精度,同时在一定程度上可以缓解过拟合

平均池化

平均池化(Average Pooling): 计算输入区域内的平均值作为输出,将输入区域的值平均分配

最大池化和均值池化的弊端如下所示

最大池化与均值池化的弊端

随机池化

Stochastic Pooling for Regularization of Deep Convolutional Neural Networks 2013

Stochastic pooling是论文《Stochastic Pooling for Regularization of Deep Convolutional Neural Networks》中提到的一种池化策略,大意是只需对特征区域元素按照其概率值大小随机选择,元素值大的被选中的概率也大

随机池化

下表是随机池化在CIFAR-10上的表现,可以看出,使用随机池化效果和采用dropout的结果接近,证明了其有一定防止过拟合的作用

随机池化_cifar数据集

Lp池化

Lp池化(Lp Pooling)是通过调整参数p的值来实现不同的池化方式,当p=1时,为平均池化,当p趋近于无穷大时,为最大池化

Lp池化的好处是可以在一定程度上保留更多的信息。平均池化会平均化局部区域的特征,可能丢失一些细节信息;而最大池化只保留局部区域的最大值,可能丢失其他重要的信息

Lp池化通过调整参数p的值,可以在特征汇聚时平衡信息的丰富性和抗噪性能

LP池化

池化具体操作如下公式所描述

当p=1时,使用局部求和,而p为无穷大时,对应max-pooling

在Lp池化中,p的选择需要根据具体任务和数据集进行调整

  • 较小的p值可以更加注重细节信息,适用于需要保留细粒度特征的任务
  • 较大的p值可以更加注重全局信息,适用于更加整体化的任务

通常情况下,p取2时能够获得较好的性能

组合池化

组合池化则是同时利用最大值池化与均值池化两种的优势而引申的一种池化策略,常见组合策略有Cat和Add这两种

常常被当做分类任务的一个trick,其作用就是丰富特征层,maxpool更关注重要的局部特征,而average pooling更关注全局特征

1
2
3
4
5
6
7
8
9
def add_avgmax_pool2d(x, output_size=1):
x_avg = F.adaptive_avg_pool2d(x, output_size)
x_max = F.adaptive_max_pool2d(x, output_size)
return 0.5 * (x_avg + x_max)

def cat_avgmax_pool2d(x, output_size=1):
x_avg = F.adaptive_avg_pool2d(x, output_size)
x_max = F.adaptive_max_pool2d(x, output_size)
return torch.cat([x_avg, x_max], 1)

SPP池化

Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition 2015

SPP(空间金字塔池化)是在SPPNet中提出的,SPPNet提出比较早,在RCNN之后提出的,用于解决重复卷积计算固定输出的两个问题,具体方法如下图所示

空间金字塔池化的基本思想是将输入特征图分割成多个不同大小的子区域,并对每个子区域进行池化操作。这些子区域的大小和数量构成了一个金字塔形状的层次结构

然后,对每个子区域进行池化操作(通常是最大池化),生成固定大小的特征向量。最后,将所有尺度上得到的特征向量拼接在一起,形成最终的特征表示

SPP池化

通过空间金字塔池化,模型能够在不同尺度上捕捉到更加丰富的局部特征,从而增强了模型对尺度变化和物体大小变化的鲁棒性

这对于处理不同尺度的物体检测、图像分类和语义分割等任务非常有用

ROI池化

ROI池化(Region of Interest Pooling)是在目标检测任务中广泛使用的操作。它对于来自输入列表的每个感兴趣区域,它采用与其对应的输入特征图的一部分并将其缩放到某个预定义的大小。这可以显着加快训练和测试时间,它允许重新使用卷积网络中的特征映射,同时也允许以端到端的方式训练物体检测系统

ROI池化

ROI Pooling与SPP池化的区别

通过上面的介绍,可以看到两者起到的作用是相同的,把不同尺寸的特征输入转化为相同尺寸的特征输出

SPP针对同一个输入使用了多个不同尺寸的池化操作,把不同尺度的结果拼接作为输出;而ROI Pooling可看作单尺度的SPP,对于一个输入只进行一次池化操作

反池化

[CNN] 卷积、反卷积、池化、反池化

反池化(Unpooling)与池化操作相反,用于恢复特征图的尺寸,常见的方法包括最大反池化平均反池化

在传统的池化操作中,通过将特征图的大小减小,以实现特征的降维和减少计算量。然而,这也导致了信息的损失和空间分辨率的降低

为了补偿这种信息损失,反池化和Unpooling操作用于还原特征图的空间分辨率,使其与输入特征图具有相同的尺寸

反池化通常是通过转置卷积(Transpose Convolution)来实现的。转置卷积通过在特征图之间插入空白像素或零填充,并使用适当的卷积核对这些空白像素进行卷积运算,以恢复特征图的尺寸

Unpooling则是在反池化操作中与转置卷积结合使用的一种方式。在池化操作中,通常会记录池化操作时的最大值或平均值的位置。在Unpooling中,根据这些位置信息,将反池化操作的输出值放置回原始特征图的对应位置。这样可以在恢复空间分辨率的同时保留一定的位置信息

反池化

反池化和Unpooling在卷积神经网络中起着重要的作用,特别是在语义分割和图像重建等任务中。它们帮助网络恢复输入图像的详细结构和空间信息,从而提高模型的精度和质量

其他池化

  1. LIP池化: LIP: Local Importance-based Pooling
  2. 自适应池化(Adaptive Pooling): 根据输入的尺寸自动调整池化窗口的大小,适应不同大小的输入

归一化

BatchNormalization、LayerNormalization、InstanceNorm、GroupNorm简介

神经网络中有各种归一化算法,从公式看它们都差不多:无非是减去均值,除以标准差,再施以线性映射

归一化算法的主要区别在于操作的feature map维度不同

下图来自何凯明的Group Normalization 2018

归一化层之间的比较

可以看出

  • BN: 针对整个batch不同通道,具体来说,就是把第1个样本的第1个通道,加上第2个样本第1个通道…加上第N个样本第1个通道,求平均,得到通道1的均值

  • LN:针对每个样本,对每个样本的C、H、W维度上的数据求均值和标准差,保留N维度

  • IN:针对每个样本下的每个通道,对每个样本的H、W维度的数据求均值和标准差,保留N 、C维度,也就是说,它只在channel内部求均值和标准差

  • GN:针对每个样本下的多个通道,计算均值和标准差时,把每一个样本feature map的channel分成G组,每组将有C/G个channel,然后将这些channel中的元素求均值和标准差。各组channel用其对应的归一化参数独立地归一化

批归一化

背景

机器学习领域有个很重要的假设:IID 独立同分布假设,就是假设训练数据和测试数据是满足相同分布的,这是通过训练数据获得的模型能够在测试集获得好的效果的一个基本保障

在把数据喂给机器学习模型之前,白化(whitening)是一个重要的数据预处理步骤

  1. 独立: 去除特征之间的相关性
  2. 同分布: 使得所有特征具有相同的均值和方差

每批训练数据的分布各不相同,那么网络需要在每次迭代中去学习适应不同的分布,这样将会大大降低网络的训练速度。对于深度网络的训练是一个非常复杂的过程,只要网络的前面几层发生微小的改变,那么这些微小的改变在后面的层就会被累积放大下去

一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度

一文搞懂BN的原理及其实现过程(Batch Normalization)

深入理解NLP中LayerNorm的原理以及LN的代码详解

引入批归一化Batch Normalization的原因:在图像预处理过程中通常会对图像进行标准化处理,也就是image normalization,使得每张输入图片的数据分布能够统均值为,方差为的分布。这样能够加速网络的收敛。但是当一张图片输入到神经网络经过卷积计算之后,这个分布就不会满足刚才经过image normalization操作之后的分布了,可能适应了新的数据分布规律,这个时候将数据接入激活函数中,很可能一些新的数据会落入激活函数的饱和区,导致神经网络训练的梯度消失

这个时候我们引入Batch Normalization的目的就是使我们卷积以后的feature map满足均值为0,方差为1的分布规律,再接入激活函数就不会发生这样的情况

数据归一化都是在数据输入时做的,但是实际上在任何位置都是可以进行数据归一化,在神经网络里上一层网络的输出正好就是下一层网络的输入

优点

  1. 加速收敛:归一化操作可以减少网络中不稳定的因素,有助于梯度的传播和收敛。它使得网络在训练过程中更容易优化,加速了训练的速度
  2. 减少梯度弥散问题:神经网络在深层时容易出现梯度消失或梯度爆炸的问题。Batch Normalization通过将数据归一化到一个合适的范围,使得激活函数的输入更加稳定,减少了梯度消失的风险
  3. 提高泛化能力:Batch Normalization作为一种正则化方法,有助于减少过拟合的风险。通过在训练过程中引入一些噪声,它可以提高模型的泛化能力,并使得网络对输入数据的变化更加鲁棒

Batch Normalization在每个小批量训练样本中对输入进行标准化,使其具有零均值和单位方差

btach Normalization可视化

图像下的BN示例

下图展示了一个batch size为2(两张图片,每张图片有3个通道,其中颜色红,绿,蓝分别代表r,g,b通道)的Batch Normalization的原理,首先会统计每个通道数目所有点的像素值,求得均值和方差,然后在每个通道上分别用该点的像素值减均值除方差得到该点的像素值,此过程就是BN。最后将其接入到激活函数中

btach Normalization神经网络示例

如下图所示,其中红,绿,蓝分别代表图像不同的通道,假设假设feature map1、feature map2分别是由image1、image2经过一系列卷积池化后得到的特征矩阵

其中每个网格的值代表该点的像素值,分别统计feature map1和feature map2每个通道的像素值,得到一个矩阵,在使用BN的计算公式计算经过BN以后每个通道每个像素点的像素值

btach Normalization示例

定义为以下矩阵

可以计算得到

即得到均值和方差为

这有助于解决训练过程中的内部协变量偏移(Internal Covariate Shift)问题,即网络在训练过程中的每一层的输入分布发生变化,导致网络的训练变得困难

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import torch.nn as nn
import torch

data = [[[1, 2, 5], [2, 5, 8.5], [3, 3, 3]],
[[2, 8, 4], [1, 3, 9], [2, 6, 4]],
[[1, 1, 1], [1, 3, 5], [0.5, 6, 0.2]]]
data = torch.tensor(data)
data_bn = nn.BatchNorm1d(3)(data)
data_ln = nn.LayerNorm(3)(data)
mean = torch.sum(data_bn)
mu = torch.sum(th.pow(data_bn - mean, 2) / 27)
print(data_bn)
print(mean)
print(mu)

>>>
tensor([[[-0.7734, -0.3384, 0.9667],
[-0.7714, 0.2967, 1.5428],
[-0.0400, -0.0400, -0.0400]],
[[-0.3384, 2.2718, 0.5317],
[-1.1274, -0.4154, 1.7208],
[-0.5542, 1.5027, 0.4742]],
[[-0.7734, -0.7734, -0.7734],
[-1.1274, -0.4154, 0.2967],
[-1.3256, 1.5027, -1.4798]]], grad_fn=<NativeBatchNormBackward0>)
tensor(-5.9605e-07, grad_fn=<SumBackward0>) # 约等于0
tensor(1.0000, grad_fn=<SumBackward0>)

层归一化

深度学习基础之BatchNorm和LayerNorm

为什么Transformer使用LayerNorm ,而不使用BatchNorm

BN的特点是强行拉平数据之间的分布,使得模型收敛速度更快,并且起到了正则化的作用,使模型效果更佳。但是,BatchNorm对Batch Size大小很敏感,并且在LSTM网络上效果极差。

LayerNorm是横向归一化,不受Batch Size大小的影响,并且可以很好地应用在时序数据中,而且不需要额外的储存空间。

《Rethinking Batch Normalization in Transformers》一文对比了LayerNorm和BatchNorm对于Transformer的作用,并且提出了一种新的归一化方式

批归一化和层归一化比较

  • 适用场景

    • batch norm: 适用于CV,因为计算机视觉喂入的数据都是像素点,可以说数据点与点之间是可以比较的,所以使用batch norm可以有比较好的效果,

    • layer norm: NLP里,每个词的词向量是一组向量表示一个词,一个词向量割裂开来看是没有意义的,因此不同词向量里的数据点是不能混为一谈的

      所以batch norm之后可能会使得词损失语义,效果就可能不好了,但是使用layer norm只是让各个词向量进行标准化,就能够有比较理想的效果了

  • 归一化维度

    • batch norm: 以CV为例,归一化的是相同通道,均值和方差计算是每个通道的值
    • layer norm: 以NLP为例,归一化的每个词向量,一个词向量自己做归一化

实例归一化

等待…

组归一化

1
2
3
4
5
6
7
8
9
10
def GroupNorm(x, gamma, beta, G, eps=1e-5):
# x: input features with shape [N,C,H,W]
# gamma, beta: scale and offset, with shape [1,C,1,1]
# G: number of groups for GN
N, C, H, W = x.shape
x = tf.reshape(x, [N, G, C // G, H, W])
mean, var = tf.nn.moments(x, [2, 3, 4], keepdims=True)
x = (x - mean) / tf.sqrt(var + eps)
x = tf.reshape(x, [N, C, H, W])
return x * gamma + beta

Embedding层

等待…

Dropout层

等待…

指标

等待…