卷积神经网络超详细介绍

2023-11-13

文章目录


本博客还有多个超详细综述,感兴趣的朋友可以移步:

卷积神经网络:卷积神经网络超详细介绍

目标检测:目标检测超详细介绍

语义分割:语义分割超详细介绍用 mmsegmentation 训练自己的分割数据集

NMS:让你一文看懂且看全 NMS 及其变体

数据增强:一文看懂计算机视觉中的数据增强

损失函数:分类检测分割中的损失函数和评价指标

Transformer:A Survey of Visual Transformers

机器学习实战系列:决策树

YOLO 系列:v1v2v3v4scaled-v4v5v6v7yolofyoloxyolosyolop


1、卷积神经网络的概念

计算机视觉和 CNN 发展十一座里程碑

上世纪 60 年代,Hubel 等人通过对猫视觉皮层细胞的研究,提出了感受野这个概念,到 80 年代,Fukushima 在感受野概念的基础之上提出了神经认知机的概念,可以看作是卷积神经网络的第一个实现的网络,神经认知机将一个视觉模式分解成许多子模式(特征),然后进入分层递阶式相连的特征平面进行处理,它试图将视觉系统模型化,使其能够在即使物体有位移或轻微变形的时候,也能完成识别。

卷积神经网络是多层感知机(MLP)的变种,由生物学家休博尔和维瑟尔在早期关于猫视觉皮层的研究发展而来,视觉皮层的细胞存在一个复杂的构造,这些细胞对视觉输入空间的子区域非常敏感,称之为感受野。

卷积神经网络,也叫 CNN,由纽约大学的 Yann Lecun 于 1998 年提出,其本质是一个多层感知机,成功的原因在于其所采用的局部连接和权值共享的方式:

  • 一方面减少了权值的数量使得网络易于优化

  • 另一方面降低了模型的复杂度,也就是减小了过拟合的风险

该优点在网络的输入是图像时表现的更为明显,使得图像可以直接作为网络的输入,避免了传统识别算法中复杂的特征提取和数据重建的过程,在二维图像的处理过程中有很大的优势,如网络能够自行抽取图像的特征包括颜色、纹理、形状及图像的拓扑结构,在处理二维图像的问题上,特别是识别位移、缩放及其他形式扭曲不变性的应用上具有良好的鲁棒性和运算效率等。

名称 特点
LeNet5 没啥特点-不过是第一个CNN应该要知道
AlexNet 引入了 ReLU 和 dropout,引入数据增强、池化相互之间有覆盖,三个卷积一个最大池化+三个全连接层
VGGNet 采用 1x1 和 3x3 的卷积核以及 2x2 的最大池化使得层数变得更深。常用 VGGNet-16 和 VGGNet19
Google Inception Net 这个在控制了计算量和参数量的同时,获得了比较好的分类性能,和上面相比有几个大的改进:1、去除了最后的全连接层,而是用一个全局的平均池化来取代它; 2、引入 Inception Module,这是一个4个分支结合的结构。所有的分支都用到了 1x1 的卷积,这是因为 1x1 性价比很高,可以用很少的参数达到非线性和特征变换。3、Inception V2第二版将所有的 5x5 变成 2 个 3x3,而且提出来著名的 Batch Normalization;4、Inception V3 第三版就更变态了,把较大的二维卷积拆成了两个较小的一维卷积,加速运算、减少过拟合,同时还更改了 Inception Module 的结构。
微软ResNet残差神经网络(Residual Neural Network) 1、引入高速公路结构,可以让神经网络变得非常深 2、ResNet第二个版本将ReLU激活函数变成y=x的线性函数

2、 发展过程

1986 年 Rumelhart 等人提出了人工神经网络的反向传播算法,掀起了神经网络在机器学习中的热潮,神经网络中存在大量的参数,存在容易发生过拟合、训练时间长的缺点,但是对比 Boosting、Logistic 回归、SVM 等基于统计学习理论的方法(也可以看做具有一层隐层节点或不含隐层节点的学习模型,被称为浅层模型)来说,具有较大的优越性。

浅层模型为什么效果没有深层模型好?

浅层学习模型通常要由人工的方法来获得好的样本特性,在此基础上进行识别和预测,因此方法的有效性在很大程度上受到特征提取的制约。

深度学习的提出:

2006年,Hinton提出了深度学习,两个主要的观点是:

  • 多隐层的人工神经网络具有优异的特征学习能力,学习到的数据更能反映数据的本质特征有利于可视化或分类

  • 深度神经网络在训练上的难度,可以通过逐层无监督训练有效克服,

深度学习取得成功的原因:

  • 大规模数据(例如ImageNet):为深度学习提供了好的训练资源

  • 计算机硬件的飞速发展:特别是GPU的出现,使得训练大规模上网络成为可能

深度学习的思想:

深度神经网络的基本思想是通过构建多层网络,对目标进行多层表示,以期通过多层的高层次特征来表示数据的抽象语义信息,获得更好的特征鲁棒性。

什么是卷积神经网络:

卷积神经网络是一种带有卷积结构的深度神经网络,卷积结构可以减少深层网络占用的内存量,其三个关键的操作,其一是局部感受野,其二是权值共享,其三是 pooling 层,有效的减少了网络的参数个数,缓解了模型的过拟合问题。

1)网络结构

卷积神经网络整体架构:

  • 卷积神经网络是一种多层的监督学习神经网络,隐含层的卷积层和池采样层是实现卷积神经网络特征提取功能的核心模块。该网络模型通过采用梯度下降法最小化损失函数对网络中的权重参数逐层反向调节,通过频繁的迭代训练提高网络的精度。
  • 卷积神经网络的低隐层是由卷积层和最大池采样层交替组成,高层是全连接层对应传统多层感知器的隐含层和逻辑回归分类器。
  • 第一个全连接层的输入是由卷积层和子采样层进行特征提取得到的特征图像。
  • 最后一层输出层是一个分类器,可以采用逻辑回归,Softmax 回归甚至是支持向量机对输入图像进行分类。

卷积神经网络结构包括:

  • 卷积层,降采样层,全连接层
  • 每一层有多个特征图,每个特征图通过一种卷积滤波器提取输入的一种特征,每个特征图有多个神经元。

输入图像统计和滤波器进行卷积之后,提取该局部特征,一旦该局部特征被提取出来之后,它与其他特征的位置关系也随之确定下来了,每个神经元的输入和前一层的局部感受野相连,每个特征提取层都紧跟一个用来求局部平均与二次提取的计算层,也叫特征映射层,网络的每个计算层由多个特征映射平面组成,平面上所有的神经元的权重相等。

通常将输入层到隐藏层的映射称为一个特征映射,也就是通过卷积层得到特征提取层,经过 pooling 之后得到特征映射层。

2)局部感受野与权值共享

卷积神经网络的核心思想就是局部感受野、是权值共享和pooling层,以此来达到简化网络参数并使得网络具有一定程度的位移、尺度、缩放、非线性形变稳定性。

  • 局部感受野:由于图像的空间联系是局部的,每个神经元不需要对全部的图像做感受,只需要感受局部特征即可,然后在更高层将这些感受得到的不同的局部神经元综合起来就可以得到全局的信息了,这样可以减少连接的数目。

  • 权值共享:不同神经元之间的参数共享可以减少需要求解的参数,使用多种滤波器去卷积图像就会得到多种特征映射。权值共享其实就是对图像用同样的卷积核进行卷积操作,也就意味着第一个隐藏层的所有神经元所能检测到处于图像不同位置的完全相同的特征。其主要的能力就能检测到不同位置的同一类型特征,也就是卷积网络能很好的适应图像的小范围的平移性,即有较好的平移不变性(比如将输入图像的猫的位置移动之后,同样能够检测到猫的图像)

3)卷积层、下采样层、全连接层

卷积层:因为通过卷积运算我们可以提取出图像的特征,通过卷积运算可以使得原始信号的某些特征增强,并且降低噪声。

  • 用一个可训练的滤波器fx去卷积一个输入的图像(第一阶段是输入的图像,后面的阶段就是卷积特征map了),然后加一个偏置 bx,得到卷积层 Cx。

下采样层:因为对图像进行下采样,可以减少数据处理量同时保留有用信息,采样可以混淆特征的具体位置,因为某个特征找出来之后,它的位置已经不重要了,我们只需要这个特征和其他特征的相对位置,可以应对形变和扭曲带来的同类物体的变化。

  • 每邻域四个像素求和变为一个像素,然后通过标量 Wx+1 加权,再增加偏置 bx+1,然后通过一个sigmoid激活函数,产生一个大概缩小四倍的特征映射图 Sx+1。

全连接层:采用 softmax 全连接,得到的激活值即卷积神经网络提取到的图片特征。

卷积神经网络相比一般神经网络在图像理解中的优点:

  • 网络结构能够较好的适应图像的结构
  • 同时进行特征提取和分类,使得特征提取有助于特征分类
  • 权值共享可以减少网络的训练参数,使得神经网络结构变得简单,适应性更强

3、如何利用CNN实现图像识别的任务

  • 输入层读入经过规则化(统一大小)的图像,每一层的每个神经元将前一层的一组小的局部近邻的单元作为输入,也就是局部感受野和权值共享,神经元抽取一些基本的视觉特征,比如边缘、角点等,这些特征之后会被更高层的神经元所使用。
  • 卷积神经网络通过卷积操作获得特征图,每个位置,来自不同特征图的单元得到各自不同类型的特征。一个卷积层中通常包含多个具有不同权值向量的特征图,使得能够保留图像更丰富的特征。
  • 卷积层后边会连接池化层进行降采样操作,一方面可以降低图像的分辨率,减少参数量,另一方面可以获得平移和形变的鲁棒性。卷积层和池化层的交替分布,使得特征图的数目逐步增多,而且分辨率逐渐降低,是一个双金字塔结构。

4、CNN的特征

1)具有一些传统技术所没有的优点:良好的容错能力、并行处理能力和自学习能力,可处理环境信息复杂,背景知识不清楚,推理规则不明确情况下的问题,允许样品有较大的缺损、畸变,运行速度快,自适应性能好,具有较高的分辨率。它是通过结构重组和减少权值将特征抽取功能融合进多层感知器,省略识别前复杂的图像特征抽取过程。

2)泛化能力要显著优于其它方法,卷积神经网络已被应用于模式分类,物体检测和物体识别等方面。利用卷积神经网络建立模式分类器,将卷积神经网络作为通用的模式分类器,直接用于灰度图像。

3)是一个前溃式神经网络,能从一个二维图像中提取其拓扑结构,采用反向传播算法来优化网络结构,求解网络中的未知参数。

4)一类特别设计用来处理二维数据的多层神经网络。CNN 被认为是第一个真正成功的采用多层层次结构网络的具有鲁棒性的深度学习方法。CNN 通过挖掘数据中的空间上的相关性,来减少网络中的可训练参数的数量,达到改进前向传播网络的反向传播算法效率,因为 CNN 需要非常少的数据预处理工作,所以也被认为是一种深度学习的方法。在 CNN 中,图像中的小块区域(也叫做“局部感知区域”)被当做层次结构中的底层的输入数据,信息通过前向传播经过网络中的各个层,在每一层中都由过滤器构成,以便能够获得观测数据的一些显著特征。因为局部感知区域能够获得一些基础的特征,比如图像中的边界和角落等,这种方法能够提供一定程度对位移、拉伸和旋转的相对不变性。

5)CNN 中层次之间的紧密联系和空间信息使得其特别适用于图像的处理和理解,并且能够自动的从图像抽取出丰富的相关特性。

6)CNN 通过结合局部感知区域、共享权重、空间或者时间上的降采样来充分利用数据本身包含的局部性等特征,优化网络结构,并且保证一定程度上的位移和变形的不变性。

7)CNN 是一种深度的监督学习下的机器学习模型,具有极强的适应性,善于挖掘数据局部特征,提取全局训练特征和分类,它的权值共享结构网络使之更类似于生物神经网络,在模式识别各个领域都取得了很好的成果。

8) CNN 可以用来识别位移、缩放及其它形式扭曲不变性的二维或三维图像。CNN 的特征提取层参数是通过训练数据学习得到的,所以其避免了人工特征提取,而是从训练数据中进行学习;其次同一特征图的神经元共享权值,减少了网络参数,这也是卷积网络相对于全连接网络的一大优势。共享局部权值这一特殊结构更接近于真实的生物神经网络使 CNN 在图像处理、语音识别领域有着独特的优越性,另一方面权值共享同时降低了网络的复杂性,且多维输入信号(语音、图像)可以直接输入网络的特点避免了特征提取和分类过程中数据重排的过程。

9)CNN 的分类模型与传统模型的不同点在于其可以直接将一幅二维图像输入模型中,接着在输出端即给出分类结果。其优势在于不需复杂的预处理,将特征抽取,模式分类完全放入一个黑匣子中,通过不断的优化来获得网络所需参数,在输出层给出所需分类,网络核心就是网络的结构设计与网络的求解。这种求解结构比以往多种算法性能更高。

10)隐层的参数个数和隐层的神经元个数无关,只和滤波器的大小和滤波器种类的多少有关。隐层的神经元个数,它和原图像,也就是输入的大小(神经元个数)、滤波器的大小和滤波器在图像中的滑动步长都有关。

5、CNN的求解

CNN 在本质上是一种输入到输出的映射,它能够学习大量的输入与输出之间的映射关系,而不需要任何输入和输出之间的精确的数学表达式,只要用已知的模式对卷积网络加以训练,网络就具有输入输出对之间的映射能力。

卷积网络执行的是监督训练,所以其样本集是由形如:(输入向量,理想输出向量)的向量对构成的。所有这些向量对,都应该是来源于网络即将模拟系统的实际“运行”结构,它们可以是从实际运行系统中采集来。

1)参数初始化:

在开始训练前,所有的权都应该用一些不同的随机数进行初始化。

  • “小随机数”用来保证网络不会因权值过大而进入饱和状态,从而导致训练失败;
  • “不同”用来保证网络可以正常地学习。实际上,如果用相同的数去初始化权矩阵,则网络无学习能力。

2)训练过程包括四步

① 第一阶段:前向传播阶段

  • 从样本集中取一个样本,输入网络

  • 计算相应的实际输出;在此阶段信息从输入层经过逐级的变换,传送到输出层,这个过程也是网络在完成训练之后正常执行时执行的过程

② 第二阶段:后向传播阶段

  • 计算实际输出与相应的理想输出的差

  • 按照极小化误差的方法调整权值矩阵

    网络的训练过程如下:

  1. 选定训练组,从样本集中分别随机地寻求 N 个样本作为训练组;

  2. 将各权值、阈值,置成小的接近于 0 的随机值,并初始化精度控制参数和学习率;

  3. 从训练组中取一个输入模式加到网络,并给出它的目标输出向量;

  4. 计算出中间层输出向量,计算出网络的实际输出向量;

  5. 将输出向量中的元素与目标向量中的元素进行比较,计算出输出误差;对于中间层的隐单元也需要计算出误差;

  6. 依次计算出各权值的调整量和阈值的调整量;

  7. 调整权值和调整阈值;

  8. 当经历 M 后,判断指标是否满足精度要求,如果不满足,则返回 (3),继续迭代;如果满足就进入下一步;

  9. 训练结束,将权值和阈值保存在文件中。这时可以认为各个权值已经达到稳定,分类器已经形成。再一次进行训练,直接从文件导出权值和阈值进行训练,不需要进行初始化。

6、卷积神经网络注意事项

1)数据集的大小和分块

数据驱动的模型一般依赖于数据集的大小,CNN 和其他经验模型一样,能够适用于任意大小的数据集,但用于训练的数据集应该足够大, 能够覆盖问题域中所有已知可能出现的问题,

设计 CNN 的时候,数据集应该包含三个子集:训练集、测试集、验证集

训练集:包含问题域中的所有数据,并在训练阶段用来调整网络的权重

测试集:在训练的过程中用于测试网络对训练集中未出现的数据的分类性能,根据网络在测试集上的性能情况,网络的结构可能需要作出调整,或者增加训练循环次数。

验证集:验证集中的数据统一应该包含在测试集和训练集中没有出现过的数据,用于在网络确定之后能够更好的测试和衡量网络的性能

Looney 等人建议,数据集中 65% 的用于训练,25% 的用于测试,10% 用于验证

2)数据预处理

为了加速训练算法的收敛速度,一般都会采用一些数据预处理技术,其中包括:去除噪声、输入数据降维、删除无关数据等。

数据的平衡化在分类问题中异常重要,一般认为训练集中的数据应该相对于标签类别近似于平均分布,也就是每一个类别标签所对应的数据集在训练集中是基本相等的,以避免网络过于倾向于表现某些分类的特点。

为了平衡数据集,应该移除一些过度富余的分类中的数据,并相应补充一些相对样例稀少的分类中的数据。

还有一个方法就是复制一部分这些样例稀少分类中的数据,并在这些数据中加入随机噪声。

3)数据规则化

将数据规则化到统一的区间(如 [0,1])中具有很重要的优点:防止数据中存在较大数值的数据造成数值较小的数据对于训练效果减弱甚至无效化,一个常用的方法是将输入和输出数据按比例调整到一个和激活函数相对应的区间。

4)网络权值初始化

CNN 的初始化主要是初始化卷积层和输出层的卷积核(权值)和偏置

网络权值初始化就是将网络中的所有连接权重赋予一个初始值,如果初始权重向量处在误差曲面的一个相对平缓的区域的时候,网络训练的收敛速度可能会很缓慢,一般情况下网络的连接权重和阈值被初始化在一个具有0均值的相对小的区间内均匀分布。

5)BP 算法的学习速率

如果学习速率选取的较大,则会在训练过程中较大幅度的调整权值 w,从而加快网络的训练速度,但是这和造成网络在误差曲面上搜索过程中频繁抖动,且有可能使得训练过程不能收敛。

如果学习速率选取的较小,能够稳定的使得网络逼近于全局最优点,但也可能陷入一些局部最优,并且参数更新速度较慢。

自适应学习率设定有较好的效果。

6)收敛条件

有几个条件可以作为停止训练的判定条件,训练误差、误差梯度、交叉验证等。一般来说,训练集的误差会随着网络训练的进行而逐步降低。

7)训练方式

训练样例可以有两种基本的方式提供给网络训练使用,也可以是两者的结合:逐个样例训练(EET)、批量样例训练(BT)。

在 EET 中,先将第一个样例提供给网络,然后开始应用 BP 算法训练网络,直到训练误差降低到一个可以接受的范围,或者进行了指定步骤的训练次数。然后再将第二个样例提供给网络训练。

EET 的优点是相对于BT只需要很少的存储空间,并且有更好的随机搜索能力,防止训练过程陷入局部最小区域。

EET的缺点是如果网络接收到的第一个样例就是劣质(有可能是噪音数据或者特征不明显)的数据,可能使得网络训练过程朝着全局误差最小化的反方向进行搜索。

相对的,BT 方法是在所有训练样例都经过网络传播后才更新一次权值,因此每一次学习周期就包含了所有的训练样例数据。

BT方法的缺点也很明显,需要大量的存储空间,而且相比EET更容易陷入局部最小区域。

而随机训练(ST)则是相对于EET和BT一种折衷的方法,ST 和 EET 一样也是一次只接受一个训练样例,但只进行一次 BP 算法并更新权值,然后接受下一个样例重复同样的步骤计算并更新权值,并且在接受训练集最后一个样例后,重新回到第一个样例进行计算。

ST 和 EET 相比,保留了随机搜索的能力,同时又避免了训练样例中最开始几个样例如果出现劣质数据对训练过程的过度不良影响。

7、CNN发展综合介绍

CNN的开山之作是 LeCun 提出的 LeNet-5,而其真正的爆发阶段是 2012 年 AlexNet 取得 ImageNet 比赛的分类任务的冠军,并且分类准确率远远超过利用传统方法实现的分类结果,该模型能够取得成功的原因主要有三个:

  • 海量的有标记的训练数据,也就是李飞飞团队提供的大规模有标记的数据集 ImageNet
  • 计算机硬件的支持,尤其是 GPU 的出现,为复杂的计算提供了强大的支持
  • 算法的改进,包括网络结构加深、数据增强(数据扩充)、ReLU、Dropout等

AlexNet 之后,深度学习便一发不可收拾,分类准确率每年都被刷榜,下图展示了模型的变化情况,随着模型的变深,Top-5 的错误率也越来越低,目前已经降低到了 3.5% 左右,同样的 ImageNet 数据集,人眼的辨识错误率大概为 5.1%,也就是深度学习的识别能力已经超过了人类。

这里写图片描述

这里写图片描述

8、LeNet-5结构分析

这里写图片描述

LeNet-5 共包含 8 层

  • C1 层是一个卷积层,由 6 个特征图 Feature Map 构成。特征图中每个神经元与输入为5x5 的邻域相连。特征图的大小为 28x28,这样能防止输入的连接掉到边界之外(32-5+1=28)。C1 有 156 个可训练参数(每个滤波器 5x5=25 个 bunit 参数和一个 bias 参数,一共 6 个滤波器,共(5x5+1)x6=156个参数),共 156x(28x28)=122,304个连接。

  • S2层是一个下采样层,有 6 个 14x14 的特征图。特征图中的每个单元与 C1 中相对应特征图的 2x2 邻域相连接。S2层每个单元的 4 个输入相加,乘以一个可训练参数,再加上一个可训练偏置。每个单元的 2x2 感受野并不重叠,因此 S2 中每个特征图的大小是 C1 中特征图大小的 1/4(行和列各 1/2)。S2 层有 12(6x(1+1)=12)个可训练参数和 5880(14x14 (2 2+1) 6=5880)个连接。

  • C3 层也是一个卷积层,它同样通过5x5的卷积核去卷积层 S2,然后得到的特征 map 就只有 10x10 个神经元,但是它有 16 种不同的卷积核,所以就存在 16 个特征 map 了。 C3 中每个特征图由 S2 中所有 6 个或者几个特征 map 组合而成。为什么不把 S2 中的每个特征图连接到每个 C3 的特征图呢?原因有 2 点:① 不完全的连接机制将连接的数量保持在合理的范围内。② 也是最重要的,其破坏了网络的对称性。由于不同的特征图有不同的输入,所以迫使他们抽取不同的特征(希望是互补的)。

    例如,存在的一个方式是:C3 的前 6 个特征图以 S2 中 3 个相邻的特征图子集为输入。接下来 6 个特征图以 S2 中 4 个相邻特征图子集为输入。然后的 3 个以不相邻的 4 个特征图子集为输入。最后一个将 S2 中所有特征图为输入。这样 C3 层有 1516(6x(3x25+1)+6x(4x25+1)+3x(4x25+1)+(25x6+1)=1516)个可训练参数和151600(10x10x1516=151600)个连接。

  • S4 层是一个下采样层,由 16 个 5x5 大小的特征图构成。特征图中的每个单元与 C3 中相应特征图的 2x2 邻域相连接,跟 C1 和 S2 之间的连接一样。S4 层有 32 个可训练参数(每个特征图1个因子和一个偏置16x(1+1)=32)和 2000(16 (2 2+1)x5 x5=2000)个连接。

  • C5 层是一个卷积层,有 120 个特征图。每个单元与 S4 层的全部 16个 单元的 5x5 邻域相连。由于 S4 层特征图的大小也为 5x5 (同滤波器一样),故 C5 特征图的大小为 1x1(5-5+1=1),这构成了 S4 和 C5 之间的全连接。之所以仍将 C5 标示为卷积层而非全相联层,是因为如果 LeNet-5 的输入变大,而其他的保持不变,那么此时特征图的维数就会比 1x1 大。C5 层有48120(120x(16x5x5+1)=48120 由于与全部 16 个单元相连,故只加一个偏置可训练连接。

  • F6 层有 84 个单元(之所以选这个数字的原因来自于输出层的设计),与 C5 层全相连。有 10164(84x(120x(1x1)+1)=10164)个可训练参数。如同经典神经网络,F6 层计算输入向量和权重向量之间的点积,再加上一个偏置。然后将其传递给 sigmoid 函数产生单元i的一个状态。

  • 最后,输出层由欧式径向基函数(Euclidean Radial Basis Function)单元组成,每类一个单元,每个有 84 个输入。

1、输入层:N 个 32x32 的训练样本

输入图像大小为 32x32,比 MNIST 数据库中的字母大,这样做的原因是希望潜在的明显特征,如笔画断点或角点能够出现在最高层特征监测子感受野的中心。

2、C1 层

  • 输入图像大小:32x32
  • 卷积核大小:5x5
  • 卷积核个数:6
  • 输出特征图数量:6
  • 输出特征图大小:28x28(32-5+1)
  • 神经元数量:4707(28x28x6)
  • 连接数:122304((28x28x5x5x6)+(28x28x6))
  • 可训练参数:156(5x5x6+6,权值+偏置)

3、S2 层

  • 输入图像大小:(28x28x6)
  • 卷积核大小:2x2
  • 卷积核个数:6
  • 输出特征图数量:6
  • 输出特征图大小:14x14(28/2,28/2)
  • 神经元数量:1176(14x14x6)
  • 连接数:5880((2x2x14x14x6)+(14x14x6))
  • 可训练参数:12(1x6+6,权值+偏置)

备注:S2层每个单元的4个输入相加,乘以一个可训练参数,再加上一个可训练偏置。结果通过sigmoid函数计算。可训练系数和偏置控制着sigmoid函数的非线性程度。

如果系数比较小,那么运算近似于线性运算,下采样相当于模糊图像。

如果系数比较大,根据偏置的大小下采样可以被看成是有噪声的“或”运算或者有噪声的“与”运算。

每个单元的 2x2 感受野并不重叠,因此 S2 中每个特征图的大小是 C1 中特征图大小的 1/4(行和列各 1/2)。

4、C3 层

  • 输入图像大小:(14x14x6)
  • 卷积核大小:5x5
  • 卷积核个数:16
  • 输出特征图数量:16
  • 输出特征图大小:10x10(14-5+1)
  • 神经元数量:1600(10x10x16)
  • 连接数:151600(1516x10x10)
  • 可训练参数:1516

备注:C3 层也是一个卷积层,通过 5x5 的卷积核去卷积 S2 层,然后得到的特征图 map 就有 10x10 个神经元,但是有 16 种不同的卷积核,就存在 16 个不同的特征 map。

C3 中每个特征图由 S2 中的所有 6 个或几个特征图组合而成,为什么不把 S2 中的所有特征图都连接到 C3 的特征图呢:

  • 第一,不完全的连接机制将连接的数量保持在合理的范围内
  • 第二,也是最重要的,这样一来就可以破坏网络的对称性,由于不同的特征图有不同的输入,所以迫使他们抽取不同的特征。

5、S4 层

  • 输入图像大小:(10x10x16)
  • 卷积核大小:2x2
  • 卷积核个数:16
  • 输出特征图数量:16
  • 输出特征图大小:5x5x16
  • 神经元数量:400(5x5x16)
  • 连接数:2000((2x2x5x5x16)+(5x5x16))
  • 可训练参数:32((1+1)x16)

备注:S4 是一个下采样层,由 16 个 5x5 大小的特征图构成,特征图的每个单元与 C3 中相应的特征图的 2x2 邻域相连,S4 层有 32 个可训练参数(每个特征图 1 个因子和一个偏置)和 2000 个连接。

6、C5 层

  • 输入图像大小:5x5x16
  • 卷积核大小:5x5
  • 卷积核个数:120
  • 输出特征图数量:120
  • 输出特征图大小:1X1(5-5+1)
  • 神经元数量:120(1x120)
  • 连接数:48120(5x5x16x120x1+120x1)
  • 可训练参数:48120(5x5x16x120+120)

备注:C5 层是一个卷积层,有 120 个特征图,每个单元与 S4 层的全部 16 个单元的 5x5 邻域相连,构成了 S4 和 C5 的全连接,之所以仍将 C5 标识为卷积层而非全连接层是因为如果 LeNet-5 的输入变大,而其他的保持不变,那么此时特征图的维数就会比 1x1 大。

7、F6 层

  • 输入图像大小:(1x1x120)
  • 卷积核大小:1x1
  • 卷积核个数:84
  • 输出特征图数量:1
  • 输出特征图大小:84
  • 神经元数量:84
  • 连接数:10164(120x84+84)
  • 可训练参数:10164(120x84+84)

备注:F6 有 84 个单元(之所以选择 84 是源于输出层的设计),与 C5 层相连,有 10164 个可训练参数,类似经典的全连接神经网络,F6 层计算输入向量和权重向量之间的点积,再加上一个偏置,之后将其传递给 sigmoid 函数产生一个单元i的状态。

8、output 层

  • 输入图像大小:1x84
  • 输出特征图数量:1x10

9、AlexNet

超详细介绍AlexNet

这篇论文,题目叫做 “ImageNet Classification with Deep Convolutional Networks”,迄今被引用 6184 次,被业内普遍视为行业最重要的论文之一。Alex Krizhevsky、Ilya Sutskever 和 Geoffrey Hinton 创造了一个“大型的深度卷积神经网络”,赢得了 2012 ILSVRC(2012年ImageNet 大规模视觉识别挑战赛)。稍微介绍一下,这个比赛被誉为计算机视觉的年度奥林匹克竞赛,全世界的团队相聚一堂,看看是哪家的视觉模型表现最为出色。2012 年是 CNN 首次实现 Top 5 误差率 15.4% 的一年 (Top 5 误差率是指给定一张图像,其标签不在模型认为最有可能的 5 个结果中的几率),当时的次优项误差率为 26.2%。这个表现不用说震惊了整个计算机视觉界。可以说,是自那时起,CNN 才成了家喻户晓的名字。

ImageNet 2012 比赛分类任务的冠军,将分类错误率降低到了 15.315%,使用传统计算机视觉的第二名小组的分类错误率为 26.172%。

这里写图片描述

上图所示是 caffe 中 alexnet 的网络结构,上图采用是两台 GPU 服务器,所有会看到两个流程图。下边把 AlexNet 的网络结构示意一下:

这里写图片描述

简化的结构:

这里写图片描述

架构:

因为使用了两台 GPU 训练,因而有两股 “流”。使用两台 GPU 训练的原因是计算量太大,只能拆开来。

要点:

数据集:ImageNet 数据集,含 1500 多万个带标记的图像,超过 2.2 万个类别
激活函数:ReLU(训练速度快,一定程度上减小了梯度消失的问题)
数据增强:平移、镜像、缩放等
过拟合:dropout
如何训练:批处理梯度下降训练模型,注明了动量衰减值和权值衰减值
训练时间:使用两台 GTX 580 GPU,训练了 5 到 6 天

这里写图片描述

这里写图片描述

这里写图片描述

Alex Krizhevsky 等人于 2012 年的 ImageNet 比赛中提出了新型卷积神经网络 AlexNet,并获得了图像分类问题的最好成绩(Top-5 错误率为 15.3%)。

网络结构:

其实 AlexNet 的结构很简单,只是 LeNet 的放大版,输入是一个 224x224 的图像,经过 5 个卷积层,3 个全连接层(包含一个分类层),达到了最后的标签空间。

AlexNet学习出来的特征是什么样子的?

  • 第一层:都是一些填充的块状物和边界等特征
  • 中间层:学习一些纹理特征
  • 更高层:接近于分类器的层级,可以明显的看到物体的形状特征
  • 最后一层:分类层,完全是物体的不同的姿态,根据不同的物体展现出不同姿态的特征了。

即无论对什么物体,学习过程都是:边缘 → \to 部分 → \to 整体

该方法训练了一个端到端的卷积神经网络实现对图像特征提取和分类,网络结构共7层,包含5层卷积层和2层全连接层。

AlexNet 包含了 6 亿三千万个连接,6000 万个参数和 65 万个神经元,拥有 5 个卷积层,其中 3 个卷积层后面连接了最大池化层,最后还有 3 个全连接层。

AlexNet 可以说是神经网络在低谷期后的第一次发声,确立了深度学习(深度卷积神经网络)在计算机界的统治地位,同时也推动了深度学习在语音识别、自然语言处理、强化学习等方面的拓展。

训练技巧:dropout 防止过拟合,提高泛化能力

训练阶段使用了 Dropout 技巧随机忽略一部分神经元,缓解了神经网络的过拟合现象,和防止对网络参数优化时陷入局部最优的问题,Dropout 虽有单独的论文论述,但是 AlexNet 将其实用化,通过实践证实了它的效果。在 AlexNet 中主要是最后几个全连接层使用了 Dropout。

该网络是利用 Dropout 在训练过程中将输入层和中间层的一些神经元随机置零,使得训练过程收敛的更慢,但得到的网络模型更加具有鲁棒性。

数据扩充 / 数据增强:防止过拟合

通过图像平移、水平翻转、调整图像灰度等方法扩充样本训练集,扩充样本训练集,使得训练得到的网络对局部平移、旋转、光照变化具有一定的不变性,数据经过扩充以后可以达到减轻过拟合并提升泛化能力。进行预测时,则是取图像的四个角加上中间共 5 个位置,并进行左右翻转,一共获得 10 张图像,对它们进行预测并对 10 次结果求均值。

  • 水平翻转:
    这里写图片描述

  • 随机裁剪、平移旋转:
    这里写图片描述

  • 颜色变换:
    这里写图片描述

池化方式:

AlexNet 全部使用最大池化的方式,避免了平均池化所带来的模糊化的效果,并且步长 < 池化核的大小,这样一来池化层的输出之间会有重叠和覆盖,提升了特征的丰富性。

此前的 CNN 一直使用平均池化的操作。

激活函数:ReLU

Relu函数:f(x)=max(0,x)

采用非饱和线性单元——ReLU 代替传统的经常使用的 tanh 和 sigmoid 函数,加速了网络训练的速度,降低了计算的复杂度,对各种干扰更加具有鲁棒性,并且在一定程度上避免了梯度消失问题。
这里写图片描述

优势:

  1. ReLU 本质上是分段线性模型,前向计算非常简单,无需指数之类操作;
  2. ReLU 的偏导也很简单,反向传播梯度,无需指数或者除法之类操作;
  3. ReLU 不容易发生梯度发散问题,Tanh 和Logistic 激活函数在两端的时候导数容易趋近于零,多级连乘后梯度更加约等于 0;
  4. ReLU 关闭了右边,从而会使得很多的隐层输出为 0,即网络变得稀疏,起到了类似 L1 的正则化作用,可以在一定程度上缓解过拟合。

缺点:

当然,ReLU 也是有缺点的,比如左边全部关了很容易导致某些隐藏节点永无翻身之日,所以后来又出现 pReLU、random ReLU等改进,而且 ReLU 会很容易改变数据的分布,因此 ReLU 后加 Batch Normalization 也是常用的改进的方法。

提出了LRN层(Local Response Normalization):

LRN 即 Local Response Normalization,局部响应归一化处理,实际就是利用临近的数据做归一化,该策略贡献了 1.2% 的准确率,该技术是深度学习训练时的一种提高准确度的技术方法,LRN 一般是在激活、池化后进行的一种处理方法。

LRN 是对局部神经元的活动创建竞争机制,使得其中响应较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。

为什么输入数据需要归一化(Normalized Data)?

归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。

对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。

分布式计算:

AlexNet 使用 CUDA 加速深度卷积网络的训练,利用 GPU 强大的并行计算能力,处理神经网络训练时大量的矩阵运算,AlexNet 使用两个 GTX580 的 GPU 进行训练,单个 GTX580 只有 3GB 的显存,限制了可训练网络的最大规模,因此将其分布在两个 GPU 上,在每个 GPU 的显存中储存一般的神经元参数。

有多少层需要训练

整个 AlexNet 有 8 个需要训练参数的层,不包括池化层和 LRN 层,前 5 层为卷积层,后 3 层为全连接层,AlexNet 的最后一层是由 1000 类输出的 Softmax 层用作分类,LRN 层出现在第一个和第二个卷积层之后,最大池化层出现在两个 LRN 之后和最后一个卷积层之后。

每层的超参数、参数量、计算量:

这里写图片描述

虽然前几个卷积层的计算量很大,但是参数量都很小,在 1M 左右甚至更小。只占 AlexNet 总参数量的很小一部分,这就是卷积层的作用,可以通过较小的参数量有效的提取特征。

为什么使用多层全连接:

  • 全连接层在 CNN 中起到分类器的作用,前面的卷积层、池化层和激活函数层等操作是将原始数据映射到隐层特征空间,全连接层是将学到的特征映射映射到样本标记空间,就是矩阵乘法,再加上激活函数的非线性映射,多层全连接层理论上可以模拟任何非线性变换。但缺点也很明显: 无法保持空间结构。

  • 由于全连接网络的冗余(占整个我拿过来参数的 80%),近期一些好的网络模型使用全局平均池化(GAP)取代 FC 来融合学到的深度特征,最后使用 softmax 等损失函数作为网络目标函数来指导学习过程,用 GAP 替代 FC 的网络通常有较好的预测性能。

  • 全连接的一个作用是维度变换,尤其是可以把高维变到低维,同时把有用的信息保留下来。全连接另一个作用是隐含语义的表达 (embedding),把原始特征映射到各个隐语义节点 (hidden node)。对于最后一层全连接而言,就是分类的显示表达。不同 channel 同一位置上的全连接等价与 1x1 的卷积。N 个节点的全连接可近似为 N 个模板卷积后的均值池化 (GAP)。

GAP:假如最后一层的数据是 10 个 6x6 的特征图,global average pooling 是将每个特征图计算所有像素点的均值,输出一个数据值,10 个特征图就会输出 10 个值,组成一个 1x10 的特征向量。

  • 用特征图直接表示属于某类的置信率,比如有 10 个输出,就在最后输出 10 个特征图,每个特征图的值加起来求均值,然后将均值作为其属于某类的置信值,再输入 softmax 中,效果较好。

  • 因为 FC 的参数众多,这么做就减少了参数的数量(在最近比较火的模型压缩中,这个优势可以很好的压缩模型的大小)。

  • 因为减少了参数的数量,可以很好的减轻过拟合的发生。

这里写图片描述

为什么过了 20年才卷土重来:

1. 大规模有标记数据集的出现,防止以前不可避免的过拟合现象

2. 计算机硬件的突飞猛进,卷积神经网络对计算机的运算要求比较高,需要大量重复可并行化的计算,在当时CPU只有单核且运算能力比较低的情况下,不可能进行个很深的卷积神经网络的训练。随着GPU计算能力的增长,卷积神经网络结合大数据的训练才成为可能。

3. 卷积神经网络有一批一直在坚持的科学家(如Lecun)才没有被沉默,才没有被海量的浅层方法淹没。然后最后终于看到卷积神经网络占领主流的曙光。

10、ZFNet

和 AlexNet 很像,只是把参数优化了。

2012 年 AlexNet 出尽了风头,ILSVRC 2013 就有一大批 CNN 模型冒了出来。2013 年的冠军是纽约大学 Matthew Zeiler 和 Rob Fergus 设计的网络 ZF Net,错误率 11.2%。ZFNet 模型更像是 AlexNet 架构的微调优化版,但还是提出了有关优化性能的一些关键想法。还有一个原因,这篇论文写得非常好,论文作者花了大量时间阐释有关卷积神经网络的直观概念,展示了将滤波器和权重可视化的正确方法。

在这篇题为 “Visualizing and Understanding Convolutional Neural Networks” 的论文中,Zeiler 和 Fergus 从大数据和 GPU 计算力让人们重拾对 CNN 的兴趣讲起,讨论了研究人员对模型内在机制知之甚少,一针见血地指出 “发展更好的模型实际上是不断试错的过程”。虽然我们现在要比3年前知道得多一些了,但论文所提出的问题至今仍然存在!这篇论文的主要贡献在于提出了一个比AlexNet稍微好一些的模型并给出了细节,还提供了一些制作可视化特征图值得借鉴的方法。

10.1 意义

该论文是在 AlexNet 基础上进行了一些细节的改动,网络结构上并没有太大的突破。该论文最大的贡献在于通过使用可视化技术揭示了神经网络各层到底在干什么,起到了什么作用。

从科学的观点出发,如果不知道神经网络为什么取得了如此好的效果,那么只能靠不停的实验来寻找更好的模型。

使用一个多层的反卷积网络来可视化训练过程中特征的演化及发现潜在的问题;同时根据遮挡图像局部对分类结果的影响来探讨对分类任务而言到底那部分输入信息更重要。

10.2 实现方法

训练过程:

对前一层的输入进行卷积 → relu → max pooling(可选) → 局部对比操作(可选) → 全连接层 → softmax分类器。

输入是 (x,y),计算 y 与 y 的估计值之间的交叉熵损失,反向传播损失值的梯度,使用随机梯度下降算法来更新参数(w和b)以完成模型的训练。

反卷积可视化:

一个卷积层加一个对应的反卷积层;

输入是 feature map,输出是图像像素;

过程包括反池化操作、relu 和反卷积过程。

反池化:

严格意义上的反池化是无法实现的。作者采用近似的实现,在训练过程中记录每一个池化操作的一个 zxz 的区域内输入的最大值的位置,这样在反池化的时候,就将最大值返回到其应该在的位置,其他位置的值补 0。

relu:

卷积神经网络使用 relu 非线性函数来保证输出的 feature map总是为正数。在反卷积的时候,也需要保证每一层的 feature map 都是正值,所以这里还是使用 relu 作为非线性激活函数。

滤波:

使用原卷积核的转秩和 feature map 进行卷积。反卷积其实是一个误导,这里真正的名字就是转秩卷积操作。

这里写图片描述

上图左边是一个解卷积层,右边为一个卷积层,解卷积层将会重建一个来自下一层的卷积特征近似版本,图中使用 switch 来记录在卷积网中进行最大池化操作时每个池化区域的局部最大值的位置,经过非池化操作后,原来的非最大值的位置全都置为 0。

预处理:

网络对输入图片进行预处理,裁剪图片中间的 256x256 区域,并减去整个图像每个像素的均值,然后用 10 个不同的对 256x256 图像进行 224x224 的裁剪(中间区域加上四个角落,以及他们的水平翻转图像),对以 128 个图片分的块进行随机梯度下降法来更新参数。起始学习率为 1 0 − 2 10 ^{−2} 102 ,动量为 0.9,当验证集误差停滞时,手动调整学习率。在全连接网络中使用概率为 0.5 的 dropout,并且所有权值都初始化为 1 0 − 2 10 ^{−2} 102 ,偏置设为 0。

在训练时第一层的可视化揭露了一些占主导的因素,为了了解这些,我们采用重新归一化每个卷积层的滤波器,这些滤波器的均方根值超过了一个固定半径的 1 0 − 1 10 ^{−1} 101 。这是非常关键的,尤其是在模型中的第一层,因为输出图片大约在 [-128,128] 的范围内。

特征可视化:

每个特征单独投影到像素空间揭露了不同的结构能刺激不同的一个给定的特征图,因此展示了它对于变形的输入内在的不变性。下图即在一个已经训练好的网络中可视化后的图。

10.3 训练细节

网络结构类似于 AlexNet,有两点不同,一是将 3,4,5 层的变成了全连接,二是卷积核的大小减小。

图像预处理和训练过程中的参数设置也和 AlexNet 很像。

  • AlexNet 用了1500万张图像,ZFNet 用了 130 万张图像。

  • AlexNet 在第一层中使用了大小为 11×11 的滤波器,而ZF使用的滤波器大小为 7x7,整体处理速度也有所减慢。做此修改的原因是,对于输入数据来说,第一层卷积层有助于保留大量的原始象素信息。11×11 的滤波器漏掉了大量相关信息,特别是因为这是第一层卷积层。

  • 随着网络增大,使用的滤波器数量增多。

  • 利用 ReLU 的激活函数,将交叉熵代价函数作为误差函数,使用批处理随机梯度下降进行训练。

  • 使用一台 GTX 580 GPU 训练了 12 天。

  • 开发可视化技术 “解卷积网络”(Deconvolutional Network),有助于检查不同的特征激活和其对输入空间关系。名字之所以称为“deconvnet”,是因为它将特征映射到像素(与卷积层恰好相反)。

这里写图片描述

解卷积层 DeConvNet:

DeConvNet 工作的基本原理是,每层训练过的 CNN 后面都连一层 “deconvet”,它会提供一条返回图像像素的路径。输入图像进入 CNN 之后,每一层都计算激活。然而向前传递。

现在,假设我们想知道第4层卷积层某个特征的激活值,我们将保存这个特征图的激活值,并将这一层的其他激活值设为 0,再将这张特征图作为输入送入 deconvnet。Deconvnet 与原来的 CNN 拥有同样的滤波器。输入经过一系列 unpool (maxpooling 倒过来),修正,对前一层进行过滤操作,直到输入空间满。

这一过程背后的逻辑在于,我们想要知道是激活某个特征图的是什么结构。下面来看第一层和第二层的可视化。
这里写图片描述

ConvNet 的第一层永远是低层特征检测器,在这里就是对简单的边缘、颜色进行检测。第二层就有比较圆滑的特征了。再来看第三、第四和第五层。

这里写图片描述

  • 第二层应对角落和其他边缘或者颜色的结合

  • 第三层有更加复杂的不变性,捕捉到了相似的纹理

  • 第四层显示了特定类间显著的差异性

  • 第五层显示了有显著构成变化的整个物体。

这些层展示出了更多的高级特征,比如狗的脸和鲜花。值得一提的是,在第一层卷积层后面,我们通常会跟一个池化层将图像缩小 (比如将 32x32x32 变为 16x16x3)。这样做的效果是加宽了第二层看原始图像的视野。更详细的内容可以阅读论文。

训练时的特征演变过程:

外表突然的变化导致图像中的一个变换即产生了最强烈的激活。模型的底层在少数几个 epoches 就能收敛聚集,然而上层在一个相当多的 epoches(40-50) 之后才能有所变化,这显示了让模型完全训练到完全收敛的必要性。可以由下图看到颜色对比度都逐步增强。

这里写图片描述

特征不变性:

一般来说,小的变化对于模型的第一层都有非常大的影响,但对于最高层的影响却几乎没有。对于图像的平移、尺度、旋转的变化来说,网络的输出对于平移和尺度变化都是稳定的,但却不具有旋转不变性,除非目标图像时旋转对称的。下图为分别对平移,尺度,旋转做的分析图。

这里写图片描述

上图按行顺序分别为对5类图像进行不同程度的垂直方向上的平移、尺度变换、旋转对输出结果影响的分析图。按列顺序分别为原始变换图像,第一层中原始图片和变换后的图片的欧氏距离,第7层中原始图片和变换后的图片的欧氏距离,变换后图片被正确分类的概率图。

可视化不仅能够看到一个训练完的模型的内部操作,而且还能帮助选择好的网络结构。

ZF Net 为什么重要?

ZF Net 不仅是 2013 年比赛的冠军,还对 CNN 的运作机制提供了极好的直观信息,展示了更多提升性能的方法。论文所描述的可视化方法不仅有助于弄清 CNN 的内在机理,也为优化网络架构提供了有用的信息。Deconv 可视化方法和 occlusion 实验也让这篇论文成了我个人的最爱。

10.4 卷积网络可视化

特征可视化:

通过对各层卷积核学习到的特征进行可视化发现神经网络学习到的特征存在层级结构。第二层是学习到边缘和角点检测器,第三层学习到了一些纹理特征,第四层学习到了对于指定类别图像的一些不变性的特征,例如狗脸、鸟腿,第五层得到了目标更显著的特征并且获取了位置变化信息。

训练过程中的特征演化:

低层特征经过较少 epoch 的训练过程之后就学习的比较稳定了,层数越高越需要更多的 epoch 进行训练。因此需要足够多的epoch过程来保证顺利的模型收敛。

特征不变性:

卷积神经网络具有平移和缩放不变性,并且层数越高不变性越强。但是不具有旋转不变性。

特征结构选择:

作者通过可视化 AlexNet 第一层和第二层的特征,发现比较大的stride和卷积核提取的特征不理想,所以作者将第一层的卷积核从 11x11 减小到 7x7,将 stride 从 4 减小到 2,实验说明,这样有助于分类性能的提升。

遮挡实验:

遮挡实验说明图像的关键区域被遮挡之后对分类性能有很大的影响,说明分类过程中模型明确定位出了场景中的物体。

一致性分析:

不同图像的指定目标局部块之间是否存在一致性的关联,作者认为深度模型可能默认学习到了这种关联关系。作者通过对五张不同的狗的图像进行局部遮挡,然后分析原图和遮挡后的图像的特征之间的汉明距离的和值,值越小说明一致性越大。实验表明,对不同的狗的图像遮挡左眼、右眼和鼻子之后的汉明距离小于随机遮挡,证明存在一定的关联性。

10.6 总结

  • 提出了一种可视化方法;

  • 发现学习到的特征远不是无法解释的,而是特征间存在层次性,层数越深,特征不变性越强,类别的判别能力越强;

  • 通过可视化模型中间层,在 alexnet 基础上进一步提升了分类效果;

  • 遮挡实验表明分类时模型和局部块的特征高度相关;

  • 模型的深度很关键;

  • 预训练模型可以在其他数据集上fine-tuning得到很好的结果。

11、VGGNet

很适合做迁移学习,提到了一系列,VGG-16、VGG-19,不同层,参数也不同,最后选择了D的参数,结果最好。

传统的网络训练19层的网络很不容易,很厉害。

这里写图片描述

VGGNet 是牛津大学计算机视觉组和 Google DeepMind 公司的研究员一起研发的的深度卷积神经网络。

VGGNet 探索了卷积神经网络的深度与其性能之间的关系,通过反复堆叠 3x3 的小型卷积核和 2x2 的最大池化层,VGGNet 成功地构筑了 16~19 层深的卷积神经网络。VGGNet 相比之前 state-of-the-art 的网络结构,错误率大幅下降,并取得了 ILSVRC 2014 比赛分类项目的第 2 名和定位项目的第 1 名。

VGGNet 论文中全部使用了 3x3 的卷积核和 2x2 的池化核,通过不断加深网络结构来提升性能。下图所示为 VGGNet 各级别的网络结构图,和每一级别的参数量,从 11 层的网络一直到 19 层的网络都有详尽的性能测试。

这里写图片描述

A网络(11层)有 8 个卷积层和 3 个全连接层,E 网络(19层)有 16 个卷积层和 3 个全连接层,卷积层宽度(通道数)从 64 到 512,每经过一次池化操作,扩大一倍。

11.1 结构

  • 输入:训练时输入大小为 224x224 大小的 RGB 图像;

  • 预处理:在训练集中的每个像素减去 RGB 的均值

  • 卷积核:3x3 大小的卷积核,有的地方使用 1x1 的卷积,这种 1x1 的卷积可以被看做是对输入通道的线性变换。

  • 步长:步长 stride 为 1

  • 填充:填充 1 个像素

  • 池化:max-pooling,共有 5 层在一部分卷积层之后,连接的 max-pooling 的窗口是 2x2,步长为 2

  • 全连接层:前两个全连接层均有 4096 个通道,第三个全连接层由 1000 个通道,用来分类。所有网络的全连接层配置相同。

  • 激活函数:ReLU

  • 不使用 LRN,这种标准化并不能带来很大的提升,反而会导致更多的内存消耗和计算时间

这里写图片描述

相比 AlexNet 的变化:

  • LRN 层作用不大,还耗时,抛弃
  • 网络越深,效果越好
  • 卷积核使用更小的卷积核,比如 3x3

VGG 虽然比 AlexNet 模型层数多,且每轮训练时间会比 AlexNet 更长,但是因为更深的网络和更小的卷积核带来的隐式正则化结果,需要的收敛的迭代次数减小了许多。

要点:

这里使用 3x3 的滤波器和 AlexNet 在第一层使用 11x11 的滤波器和 ZF Net 7x7 的滤波器作用完全不同。

作者认为两个 3x3 的卷积层组合可以实现 5x5 的有效感受野。这就在保持滤波器尺寸较小的同时模拟了大型滤波器,减少了参数。此外,有两个卷积层就能够使用两层 ReLU。

  • 3 卷积层具有 7x7 的有效感受野。

  • 每个 maxpool 层后滤波器的数量增加一倍。进一步加强了缩小空间尺寸,但保持深度增长的想法。

  • 图像分类和定位任务都运作良好。

  • 使用 Caffe 工具包建模。

  • 训练中使用 scale jittering 的数据增强技术。

  • 每层卷积层后使用 ReLU 层和批处理梯度下降训练。

  • 使用 4 台英伟达 Titan Black GPU 训练了两到三周。

为什么重要?

VGG Net 是最重要的模型之一,因为它再次强调 CNN 必须够深,视觉数据的层次化表示才有用。深的同时结构简单。

11.2 网络特点:

  1. VGGNet 使用 3x3 的卷积

AlexNet 和 ZFNet 在第一个卷积层的卷积分别是 11x11 、步长为 4,7x7、步长为 2)

  1. 使用三个 3x3 的卷积,而不是一个 7x7 的卷积

两个连续的 3x3 的卷积相当于 5x5 的感受野,三个相当于 7x7 的感受野,优势在于:

  • ① 包含三个 ReLU 层而不是一个,使得决策函数更有判别性;
  • ② 减少了参数,比如输入输出都是c个通道,使用 3x3 的3个卷积层需要 3x(3x3xCxC)=27xCxC,使用7x7的1个卷积层需要7x7xCxC=49xCxC,这可以看做是为 7x7 的卷积施加一种正则化,使它分解为 3 个 3x3 的卷积。
  1. 使用 1x1 的卷积层,该层主要是为了增加决策函数的非线性,而不影响卷积层的感受野,虽然 1x1 的卷积操作是线性的,但是 ReLU 增加了非线性

11.3 分类框架:

a. 训练过程:

除了从多尺度的训练图像上采样输入图像外,VGGNet 和 AlexNet 类似

优化方法: 是含有动量的随机梯度下降 SGD+momentum(0.9)

批尺度: batch size = 256

正则化: 采用 L2 正则化,weight decay 是 5e-4,dropout 在前两个全连接层之后,p=0.5

为什么能在相比 AlexNet 网络更深,参数更多的情况下,VGGNet 能在更少的周期内收敛:

  • ① 更大的深度和更小的卷积核带来隐式正则化;
  • ② 一些层的预训练

参数初始化:

对于较浅的 A 网络,参数进行随机初始化,权值 w 从 N(0,0.01)中采样,偏差 bias 初始化为 0;对于较深的网络,先用 A 网络的参数初始化前四个卷积层和三个全连接层。

数据预处理:

为了获得 224x224 的输入图像,要在每个 SGD 迭代中对每张重新缩放的图像进行随机裁剪,为了增强数据集,裁剪的图像还要随机水平翻转和 RGB 色彩偏移。

b. 测试过程

  1. 对输入图像重新缩放到一个预定义的最小图像边的尺寸 Q
  2. 网络密集地应用在重缩放后的图像上,也就是说全连接层转化为卷积层(第一个全连接层转化为 7x7 的卷积层,后两个全连接层转化为 1x1 的卷积层),然后将转化后的全连接层应用在整张图中)
  3. 为了获得固定尺寸的类别分数向量,对分数图进行空间平均化处理。

c. 实现

基于 C++ Caffe,进行一些重要修改,在单系统多 GPU 上训练。
在装有 4 个 NVIDIA Titan Black GPUs 的电脑上,训练一个网络需要 2-3 周。

12、GoogLeNet

ImageNet 2014 比赛分类任务的冠军,将错误率降低到了 6.656%,突出的特点是大大增加了卷积神经网络的深度。

将最后的全连接层都换成了 1x1 的卷积层,大大加速了训练速率。

12.1 GoogLeNet Inception V1——22层

GoogLeNet Incepetion V1《Going deeper with convolutions》

之所以名为 “GoogLeNet” 而非 “GoogleNet”,文章说是为了向早期的 LeNet 致敬。

1)动机:

深度学习以及神经网络快速发展,人们不再只关注更给力的硬件、更大的数据集、更大的模型,而是更在意新的 idea、新的算法以及模型的改进。

一般来说,提升网络性能最直接的办法就是增加网络深度和宽度,这也就意味着巨量的参数。但是,巨量参数容易产生过拟合也会大大增加计算量。

文章认为解决上述两个缺点的根本方法是将全连接甚至一般的卷积都转化为稀疏连接。

  • 一方面现实生物神经系统的连接也是稀疏的
  • 另一方面有文献 1 表明:对于大规模稀疏的神经网络,可以通过分析激活值的统计特性和对高度相关的输出进行聚类来逐层构建出一个最优网络。这点表明臃肿的稀疏网络可能被不失性能地简化。 虽然数学证明有着严格的条件限制,但Hebbian准则有力地支持了这一点:fire together,wire together。

早些的时候,为了打破网络对称性和提高学习能力,传统的网络都使用了随机稀疏连接。但是,计算机软硬件对非均匀稀疏数据的计算效率很差,所以在 AlexNet 中又重新启用了全连接层,目的是为了更好地优化并行运算。

所以,现在的问题是有没有一种方法,既能保持网络结构的稀疏性,又能利用密集矩阵的高计算性能。大量的文献表明可以将稀疏矩阵聚类为较为密集的子矩阵来提高计算性能,据此论文提出了名为 Inception 的结构来实现此目的。

这里写图片描述

2012 年 AlexNet 做出历史突破以来,直到 GoogLeNet 出来之前,主流的网络结构突破大致是网络更深(层数),网络更宽(神经元数)。所以大家调侃深度学习为 “深度调参”,但是纯粹的增大网络的缺点:

  1. 参数太多,容易过拟合,若训练数据集有限;
  2. 网络越大计算复杂度越大,难以应用;
  3. 网络越深,梯度越往后穿越容易消失(梯度弥散),难以优化模型

那么解决上述问题的方法当然就是增加网络深度和宽度的同时减少参数,Inception 就是在这样的情况下应运而生。

2)网络结构

Inception 结构的主要思路是怎样用密集成分来近似最优的局部稀疏结构,基本结构如下:

这里写图片描述

上图说明:

  1. 采用不同大小的卷积核意味着不同大小的感受野,最后拼接意味着不同尺度特征的融合
  2. 之所以卷积核采用 1x1,3x3 和 5x5,主要是为了方便对齐,设定卷积步长 stride=1,只要分别设定 padding=0,1,2,那么卷积之后便可以得到相同维度的特征,然后将这些特征就可以直接拼接在一起了。
  3. 文章中说 pooling 被证明很有效,所以网络结构中也加入了
  4. 网络越到后面,特征越抽象,而且每个特征所涉及的感受野也变大了,因此随着层数的增加,3x3 和 5x5 的比例也要增加。

但是使用 5x5 的卷积核仍然会带来巨大的计算量,为此文章借鉴 NIN,采用 1x1 的卷积核来进行降维。

例如:上一层的输出为 100x100x128,经过具有 256 个输出的5x5卷积层之后 (stride=1,pad=2),输出数据为 100x100x256。其中,卷积层的参数为 128x5x5x256。假如上一层输出先经过具有 32 个输出的 1x1 卷积层,再经过具有 256 个输出的 5x5 卷积层,那么最终的输出数据仍为为 100x100x256,但卷积参数量已经减少为 128x1x1x32 + 32x5x5x256,大约减少了 4 倍。

卷积层参数数量计算:

输入通道数为 K,输出通道数为 L,那么卷积核个数为 KxL。因为高维卷积计算是多个通道与多个卷积核分别进行二维计算

所以 K 个通道会需要 K 个卷积核,计算之后,合并也就是相加得到一个通道,又因为输出通道为 L,所以需要 KxL 个卷积核。

然后就是如何求解参数数量?

其实很简单,就是卷积核个数乘以卷积核尺寸,para=IxJxKxL。

输入是 3 个 32x32, 共 3x1024=3072。每条边 padding 为 2,则内存里实际为 3 个 36x36.

卷积核个数是 3 维的 5x5 分别与 3 个输入进行卷积运算,得到 3 维的 32x32 的输出,这里将 3 维的 32x32 对应位相加得到一张 32x32 的 feature Map

如果有 64 个 3 维的 5x5 卷积核就有 64 张 feature Map

具体过程图示为:

这里写图片描述

卷积的权值存取方式为:

  • 第 1 个 5x5 作用于第一张输入全图,

  • 第 2 个 5x5 作用于第二张输入全图,

  • 第 3 个 5x5 作用于第三张输入全图,

  • 再把这三个对应位置相加,在加上 biases,得到第一张 feature map

  • 最后 64 个 5x5x3 重复上面的过程,得到 64 个 featuremap

  • 这里 weights 有 3x5x5x64 个, biases 有 64个.

  • 这里输入是 3 输出是 64,卷积核是 5x5 权值个数是 64x5x5x3

具体改进后的Inception Module如下:

这里写图片描述

GoogLeNet Incepetion V1 比 AlexNet 的 8 层或者 VGGNet 的 19 层还要更深。但其计算量只有 15 亿次浮点运算,同时只有 500 万的参数量,仅为 AlexNet 参数量(6000万)的 1/12,却可以达到远胜于 AlexNet 的准确率,可以说是非常优秀并且非常实用的模型。

Inception V1降低参数量的目的有两点:

  • 第一,参数越多模型越庞大,需要供模型学习的数据量就越大,而目前高质量的数据非常昂贵;

  • 第二,参数越多,耗费的计算资源也会更大。

Inception V1 参数少但效果好的原因除了模型层数更深、表达能力更强外,还有两点:

  • 其一,去除了最后的全连接层,用全局平均池化层(即将图片尺寸变为 1x1)来取代它。全连接层几乎占据了 AlexNet 或 VGGNet 中 90% 的参数量,而且会引起过拟合,去除全连接层后模型训练更快并且减轻了过拟合。

  • 其二,Inception V1 中精心设计的 Inception Module 提高了参数的利用效率,其结构如上图所示。这一部分也借鉴了 Network In Network 的思想,形象的解释就是 Inception Module 本身如同大网络中的一个小网络,其结构可以反复堆叠在一起形成大网络。

Inception Module的基本结构:

其中有 4 个分支:

  • 第一个分支对输入进行 1x1 的卷积,这其实也是 NIN 中提出的一个重要结构。1x1 的卷积是一个非常优秀的结构,它可以跨通道组织信息,提高网络的表达能力,同时可以对输出通道升维和降维。
    Inception Module的 4 个分支都用到了 1x1 的卷积,来进行低成本(计算量比 3x3 小很多)的跨通道的特征变换

  • 第二个分支,先使用了 1x1 卷积,然后连接 3x3 卷积,相当于进行了两次特征变换

  • 第三个分支,先使用 1x1 卷积,然后连接 5x5 卷积

  • 第四个分支,3x3 最大池化后直接使用 1x1 卷积

  • 四个分支在最后通过一个聚合操作合并,在输出通道这个维度上聚合。

我们立刻注意到,并不是所有的事情都是按照顺序进行的,这与此前看到的架构不一样。我们有一些网络,能同时并行发生反应,这个盒子被称为 Inception 模型。

12.2 GoogLeNet

这里写图片描述

先小心翼翼的训练得到一组权重参数(第一个出来的分支),再利用这些参数作为初始化参数,训练网络,之后再进行一次初始化,训练得到 22 层的网络。

上图说明:

  1. GoogLeNet 采用了模块化的几个,方便增添和修改
  2. 网络最后采用了平均池化来代替全连接层,想法来自 NIN,事实证明可以将 TOP accuracy 提高 0.6%,但是,实际在最后一层还是加了一个全连接层,主要为了方便之后的微调
  3. 虽然移除了全连接,但是网络中依然使用了 Dropout
  4. 为了避免梯度消失,网络额外增加了 2 个辅助的 softmax 用于前向传导梯度,文章中说着两个辅助分类器的 loss 应该加一个衰减系数,但是 caffe 中的模型没有加任何衰减,此外,实际测试的时候,这两个额外的 softmax 会被去掉。

比较清晰的结构图:

这里写图片描述

结论:

GoogLeNet 是谷歌团队为了参加 ILSVRC 2014 比赛而精心准备的,为了达到最佳的性能,除了使用上述的网络结构外,还做了大量的辅助工作:包括训练多个 model 求平均、裁剪不同尺度的图像做多次验证等等。详细的这些可以参看文章的实验部分。

本文的主要想法其实是想通过构建密集的块结构来近似最优的稀疏结构,从而达到提高性能而又不大量增加计算量的目的。GoogleNet 的 caffemodel 大小约 50M,但性能却很优异。

这里写图片描述

12.3 GoogleNet Inception V2

V2 和 V1 的最大的不同就是,V2 增加了 Batch Normalization。《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》

Inception V2 学习了 VGGNet,用两个 3x3 的卷积代替 5x5 的卷积,用以降低参数量并减轻过拟合,还提出了著名的Batch Normalization 方法,该方法是一个很有效的正则化的方法,可以让大型卷积网络的训练速度加快很多倍,同时收敛后的分类准确率也可以得到大幅度的提高。

BN 在用于神经网络某层时,会对每一个 mini-batch 数据的内部进行标准化(normalization)处理,使输出规范化到 N(0,1) 的正态分布,减少了 Internal Covariate Shift(内部神经元分布的改变)。

BN 的论文指出,传统的深度神经网络在训练时,每一层的输入的分布都在变化,导致训练变得困难,我们只能使用一个很小的学习速率解决这个问题。而对每一层使用 BN 之后,我们就可以有效地解决这个问题,学习速率可以增大很多倍,达到之前的准确率所需要的迭代次数只有 1/14,训练时间大大缩短。

而达到之前的准确率后,可以继续训练,并最终取得远超于 Inception V1 模型的性能——top-5 错误率 4.8%,已经优于人眼水平。因为 BN 某种意义上还起到了正则化的作用,所以可以减少或者取消 Dropout,简化网络结构。

12.3.1 动机:

文章作者认为,网络训练过程中参数不断改变导致后续每一层输入的分布也发生变化,而学习的过程又要使得每一层适应输入的分布,因此我们不得不降低学习率、小心的初始化,分布发生变化称为 internal covariate shift。

一般在训练网络时会对数据进行预处理,包括去掉均值、白化操作等,目的是为了加快训练:

去均值化:

首先,图像数据是高度相关的,假设其分布如下图 a 所示(简化为 2 维),由于初始化的时候,我们的参数一般都是 0 均值的,因此开始的拟合 y=Wx+b 基本过原点附近,如图 b 红色虚线,因此,网络需要经过多次学习才能逐步达到紫色实线的拟合,即收敛的比较慢。

如果对数据先去均值化,如图 c,显然可以加快学习,更进一步的,我们对数据在进行去相关操作,使得数据更加容易区分,这样又会加快训练,如图 d。

去均值是一种常用的数据处理方式,它是将各个特征值减去其均值,几何上的展现是可以将数据的中心移到坐标原点,python代码为 X=X-np.mean(X,axis=0) ,对于图像来说,就是对每个像素的值都要减去平均值。

这里写图片描述

PCA:

由于计算需要,需要实现进行前面所说的均值0化。
PCA要做的是将数据的主成分找出。流程如下:

  1. 计算协方差矩阵
  2. 求特征值和特征向量
  3. 坐标转换
  4. 选择主成分

首先我们需要求出数据各个特征之间的协方差矩阵,以得到他们之间的关联程度,Python 代码如下:

# Assume input data matrix X of size [N x D]
X -= np.mean(X, axis = 0) # zero-center the data (important)
cov = np.dot(X.T, X) / X.shape[0] # get the data covariance matrix,公式含义可按照协方差矩阵的定义得到

其中得到的矩阵中的第(i,j)个元素代表第i列和第j列的协方差,对角线代表方差。协方差矩阵是对称半正定矩阵可以进行 SVD 分解:

U,S,V = np.linalg.svd(cov)1

U 的列向量是特征向量, S 是对角阵其值为奇异值也是特征值的平方奇异值分解的直观展示:

这里写图片描述

详细介绍

我们可以用特征向量(正交且长度为1可以看做新坐标系的基)右乘X(相当于旋转坐标系)就可以得到新坐标下的无联系(正交)的特征成分:

Xrot = np.dot(X, U) # decorrelate the data1

注意上面使用的 np.linalg.svd()已经将特征值按照大小排序了,这里仅需要取前几列就是取前几个主要成分了(实际使用中我们一般按照百分比取),代码:

Xrot_reduced = np.dot(X, U[:,:100]) # Xrot_reduced becomes [N x 100]

白化:

白化的方式有很多种,常用的有 PCA 白化,就是对数据进行 PCA 操作之后,再进行方差归一化,这样数据基本满足 0 均值、单位方差、弱相关性。

作者首先尝试了对每一层数据都是用白化操作,但分析认为这是不可取的,因为白化需要计算协方差矩阵、求逆等操作,计算量很大,此外,反向传播时,白化操作不一定可导,于是使用了 Normalization 的操作。

# whiten the data:
# divide by the eigenvalues (which are square roots of the singular values)
Xwhite = Xrot / np.sqrt(S + 1e-5)

但是白化因为将数据都处理到同一个范围内了,所以如果原始数据有原本影响不大的噪声,它原本小幅的噪声也会被放大到与全局相同的范围内了。

另外我们防止出现除以 0 的情况,在分母处多加了 0.00001,如果增大它会使得噪声减小。

白化之后,得到的是一个多元高斯分布。

上面两种处理的结果如下:

这里写图片描述

可以看出,经过PCA的去相关操作,将原始数据的坐标轴旋转,并且可以看出x方向的信息量比较大,如果只选择一个特征,那么久选横轴方向的特征,经过白化之后数据进入了相同的范围。

下面以处理之前提到过的 CIFAR-10 为例,看 PCA 和 Whitening 的作用:

这里写图片描述

左边是原始图片,每张图片都是一个 3072 维的一行向量,经过 PCA 之后选取 144 维最重要的特征(左2),将特征转化到原来的坐标系 U.transpose()[:144,:] 得到了降维之后的图形(左3),图形变模糊了,说明我们的主要信息都是低频信息,关于高低频的含义在下一段展示一下,图片模糊了但是主要成分都还在,最后一个图是白化之后再转换坐标系之后的结果。

  • 1. CNN不用进行PCA和白化,只需要进行零均值化就好
  • 2. 注意进行所有的预处理时训练集、验证集、测试集都要使用相同的处理方法,比如减去相同的均值。

12.3.2 对小批量进行统计特性的标准化

标准化 Normalization:

标准化是将矩阵X中的Dimensions都保持在相似的范围内,有两种实现方式:

  1. 先使得均值为 0,然后除以标准差,X=X / np.std(X, axis=0)

  2. 在数据不在同一范围,而且各个维度在同一范围内对算法比较重要时,可以将其最大最小值分别缩放为 1 和 -1,对于图像处理而言,因为一般数据都在 0~255 之间,所以不用再进行这一步了。

这里写图片描述

数据归一化的方法很简单,就是让数据具有0均值和单位方差:

这里写图片描述

但是作者又说如果简单的这么干,会降低层的表达能力。比如下图,在使用 sigmoid 激活函数的时候,如果把数据限制到0均值单位方差,那么相当于只使用了激活函数中近似线性的部分,这显然会降低模型表达能力。

这里写图片描述

因此,作者又为 BN 增加了 2 个参数,用来保持模型的表达能力,于是最后的输出为:

这里写图片描述

上述公式中用到了均值E和方差Var,需要注意的是理想情况下 E 和 Var 应该是针对整个数据集的,但显然这是不现实的。因此,作者做了简化,用一个 Batch 的均值和方差作为对整个数据集均值和方差的估计。

BN算法实现如下:

这里写图片描述

输入:输入数据 x 1 . . . x m x_1...x_m x1...xm(这些数据是准备进入激活函数的数据)

计算过程:

  1. 求数据均值
  2. 求数据方差
  3. 数据进行标准化
  4. 训练参数 γ , β \gamma , \beta γ,β
  5. 输出y通过 γ \gamma γ β \beta β 的线性变换得到新的值
  • 正向传播的过程:通过可学习的 γ \gamma γ β \beta β 参数求出新的分布值

  • 反向传播的过程:通过链式求导方式,求出 γ , β \gamma,\beta γ,β 以及相关权值

这里写图片描述

12.3.3 BN 的意义:

解决的问题是梯度消失和梯度爆炸的问题

a. 关于梯度消失:

以 sigmoid 函数为例,sigmoid 函数使得输出在 [0,1] 之间:

这里写图片描述

事实上 x 到了一定大小,经过 sigmoid 函数的输出范围就很小了,如下图:

这里写图片描述

如果输入很大,其对应的斜率就很小,我们知道其斜率在反向传播中是权值学习速率,所以就会出现以下问题:

这里写图片描述

在深度网络中,如果网络的激活输出很大,那么其梯度就很小,学习速率就很慢,假设每层学习梯度都小于最大值 0.25,网络有 n 层,因为链式求导的原因,第一层的梯度小于 0.25 的 n 次方,所以学习速率就慢,对于最后一层只需对自身求导 1次,梯度就打,学习速率就快。

影响:在一个很大的深度网络中,浅层基本不学习,权值变化小,后面几层一直在学习,结果就是后面几层基本可以表示整个网络,失去了深度的意义。

b. 关于梯度爆炸:

根据链式求导法则:

第一层偏移量的梯度 = 激活层斜率1 x 权值1 x 激活层斜率2 x …激活层斜率(n-1) x 权值(n-1) x 激活层斜率n

假如激活层斜率均为最大值 0.25,所有层的权值为 100,这样梯度就会指数增加。

12.3.4 BN在CNN中的用法
这里写图片描述

首先解释对图像的卷积是如何使用BN层的,上图是CNN中的5x5的图像通过valid卷积得到的3x3的特征图,特征图里边的值作为 BN 的输入,也就是这 9 个数值通过 BN 计算并保存 γ , β \gamma,\beta γ,β,通过 γ , β \gamma,\beta γ,β 使得输出与输入不变。

假设输入的 batch_size=m,那就有 mx9 个数值,计算这 mx9 个数据的 γ , β \gamma,\beta γ,β 并保存,这就是正向传播的过程,反向传播就是根据求得的 γ , β \gamma,\beta γ,β 来计算梯度。

重要说明:

  1. 网络训练中以 batch_size 为最小单位不断迭代,很显然新的 batch_size 进入网络,就会有新的 γ , β \gamma,\beta γ,β,因此在 BN 层中,共有 总图像数 / batch_size γ , β \gamma,\beta γ,β 被保存下来。

  2. 图像卷积过程中,通常是使用多个卷积核,得到多张特征图,对于多个的卷积核需要保存多个 γ , β \gamma,\beta γ,β

这里写图片描述

输入:待进入激活函数的变量

输出:

  1. 对于 k 维的输入,假设每一维包含 m 个变量,所以需要 k 个循环,每个循环中按照上面所介绍的方法计算 γ , β \gamma,\beta γ,β,这里的k维,在卷积网络中可以看做卷积核个数,如网络中的第 n 层有 64 个卷积核,就需要计算 64 次。(注意:在正向传播时,会使用 γ , β \gamma,\beta γ,β 使得 BN 层输入与输出一样。)

  2. 在反向传播时利用 γ , β \gamma,\beta γ,β 求得梯度,从而改变训练权值(变量)

  3. 通过不断迭代直到结束,求得关于不同层的 γ , β \gamma,\beta γ,β,如果有 n 个 BN 层,每层根据 batch_size 决定有多少个变量,设定为 m,这里的 mini_batcher 指的是 特征图大小 乘以 batch_size,即 m = 特征图大小 x batch_size,因此对于 batch_size 为 1,这里的 m 就是每层特征图的大小。

  4. 不断遍历训练集中的图像,取出每个 batch_size 的 γ , β \gamma,\beta γ,β,最后统计每层BN的 γ , β \gamma,\beta γ,β 各自的和除以图像数量,得到平均值,并对其做无偏估计值作为每一层的E[x]与Var[x]。

  5. 在预测的正向传播时,对测试数据求取 γ , β \gamma,\beta γ,β,并使用该层的 E[x] 与 Var[x],通过图中所表示的公式计算 BN 层的输出。

12.3.5 BN应该放在激活层之前还是之后

作者在文章中说应该把 BN 放在激活函数之前,这是因为 Wx+b 具有更加一致和非稀疏的分布。但是也有人做实验表明放在激活函数后面效果更好。这是实验链接,里面有很多有意思的对比实验:
https://github.com/ducha-aiki/caffenet-benchmark

12.3.6 实验

作者在文章中也做了很多实验对比,我这里就简单说明 2 个。

下图 a 说明,BN 可以加速训练。图 b 和 c 则分别展示了训练过程中输入数据分布的变化情况。

这里写图片描述

下表是一个实验结果的对比,需要注意的是在使用 BN 的过程中,作者发现 Sigmoid 激活函数比 Relu 效果要好。

这里写图片描述

12.4 GoogLeNet Inception V3

GoogLeNet 凭借其优秀的表现,得到了很多研究人员的学习和使用,因此 Google 团队又对其进行了进一步发掘改进,产生了升级版本的 GoogLeNet。这一节介绍的版本记为 V3,文章为:《Rethinking the Inception Architecture for Computer Vision》。

12.4.1 简介

2014 年以来,构建更深网络的同时逐渐成为主流,但是模型的变大也使得计算效率越来越低,这里文章试图找到不同方法来扩大网络的同时又尽可能的发挥计算性能。

首先,GoogLeNet V1 出现的同期,性能与之接近的大概只有 VGGNet 了,并且二者在图像分类之外的很多领域都得到了成功的应用。但是相比之下,GoogLeNet 的计算效率明显高于 VGGNet,大约只有 500 万参数,只相当于 Alexnet 的1/12(GoogLeNet的 caffemodel 大约 50M,VGGNet 的 caffemodel 则要超过 600M)。

GoogLeNet 的表现很好,但是,如果想要通过简单地放大 Inception 结构来构建更大的网络,则会立即提高计算消耗。此外,在 V1 版本中,文章也没给出有关构建 Inception 结构注意事项的清晰描述。因此,在文章中作者首先给出了一些已经被证明有效的用于放大网络的通用准则和优化方法。这些准则和方法适用但不局限于 Inception 结构。

12.4.2 一般情况的设计准则

下面的准则来源于大量的实验,因此包含一定的推测,但实际证明基本都是有效的。

1)避免表达瓶颈,特别是在网络靠前的地方

信息流前向传播过程中显然不能经过高度压缩的层,即表达瓶颈。从 input 到 output,feature map 的宽和高基本都会逐渐变小,但是不能一下子就变得很小。比如你上来就来个 kernel = 7, stride = 5 ,这样显然不合适。

另外输出的维度 channel,一般来说会逐渐增多 (每层的num_output),否则网络会很难训练。(特征维度并不代表信息的多少,只是作为一种估计的手段)

这种情况一般发生在 pooling 层,字面意思是,pooling 后特征图变小了,但有用信息不能丢,不能因为网络的漏斗形结构而产生表达瓶颈,解决办法是作者提出了一种特征图缩小方法,更复杂的池化。

2)高维特征更容易处理

高维特征更加容易区分,会加快训练

3)可以在低维嵌入上进行空间汇聚而无需担心丢失很多信息

比如在进行3x3卷积之前,可以对输入先进行降维而不会产生严重的后果,假设信息可以被简单的压缩,那么训练就会加快。

4)平衡网络的深度和宽度

上述的这些并不能直接用来提高网络质量,而仅用来在大环境下作指导。

12.4.3 利用大尺度滤波器进行图像的卷积

大尺寸的卷积核可以带来更大的感受野,但也意味着更多的参数,比如 5x5 卷积核参数是 3x3 卷积核的 25/9=2.78 倍。为此,作者提出可以用 2 个连续的 3x3 卷积层 (stride=1) 组成的小网络来代替单个的5x5卷积层,(保持感受野范围的同时又减少了参数量)如下图:

这里写图片描述

问题:

  1. 这种代替会造成表达能力的下降吗?

实验证明该操作不会造成表达缺失

  1. 3x3 卷积之后还要再激活吗?

添加非线性激活之后会提高性能

从上面来看,大卷积核完全可以由一系列的 3x3 卷积核来替代,那能不能分解的更小一点呢。文章考虑了 nx1 卷积核。

如下图所示的取代 3x3 卷积:

这里写图片描述

于是,任意 nxn 的卷积都可以通过 1xn 卷积后接 nx1 卷积来替代。实际上,作者发现在网络的前期使用这种分解效果并不好,还有在中度大小的 feature map 上使用效果才会更好。(对于 mxm 大小的 feature map,建议 m 在 12 到 20 之间)。

总结如下图:

这里写图片描述

(1) 图 4 是 GoogLeNet V1中使用的 Inception 结构;

(2) 图 5 是用 3x3 卷积序列来代替大卷积核;

(3) 图 6 是用 nx1 卷积来代替大卷积核,这里设定 n=7 来应对 17x17 大小的 feature map。该结构被正式用在 GoogLeNet V2 中。即非对称个卷积核,其实类似于卷积运算中,二维分解为 1 维计算,提高了计算速度。

13、ResNet

ResNet 在 2015 年被提出,在 ImageNet 比赛 classification 任务上获得第一名,因为它“简单与实用”并存,之后很多方法都建立在 ResNet50 或者 ResNet101 的基础上完成的,检测,分割,识别等领域都纷纷使用 ResNet,Alpha zero 也使用了 ResNet,所以可见 ResNet 确实很好用。

训练神经网络的反向传播,导致很容易出现梯度消失。

对常规的网络(plain network,也称平原网络)直接堆叠很多层次,经对图像识别结果进行检验,训练集、测试集的误差结果如下图:

这里写图片描述

从上面两个图可以看出,在网络很深的时候(56 层相比 20 层),模型效果却越来越差了(误差率越高),并不是网络越深越好。

通过实验可以发现:随着网络层级的不断增加,模型精度不断得到提升,而当网络层级增加到一定的数目以后,训练精度和测试精度迅速下降,这说明当网络变得很深以后,深度网络就变得更加难以训练了。

下图是一个简单神经网络图,由输入层、隐含层、输出层构成:

这里写图片描述

回想一下神经网络反向传播的原理,先通过正向传播计算出结果output,然后与样本比较得出误差值Etotal

这里写图片描述

根据误差结果,利用著名的“链式法则”求偏导,使结果误差反向传播从而得出权重w调整的梯度。下图是输出结果到隐含层的反向传播过程(隐含层到输入层的反向传播过程也是类似):

这里写图片描述

通过不断迭代,对参数矩阵进行不断调整后,使得输出结果的误差值更小,使输出结果与事实更加接近。

从上面的过程可以看出,神经网络在反向传播过程中要不断地传播梯度,而当网络层数加深时,梯度在传播过程中会逐渐消失(假如采用 Sigmoid 函数,对于幅度为 1 的信号,每向后传递一层,梯度就衰减为原来的 0.25,层数越多,衰减越厉害),导致无法对前面网络层的权重进行有效的调整。

那么,如何又能加深网络层数、又能解决梯度消失问题、又能提升模型精度呢?

13.1 ResNet的提出

前面描述了一个实验结果现象,在不断加神经网络的深度时,模型准确率会先上升然后达到饱和,再持续增加深度时则会导致准确率下降,示意图如下:

这里写图片描述

那么我们作这样一个假设:假设现有一个比较浅的网络(Shallow Net)已达到了饱和的准确率,这时在它后面再加上几个恒等映射层(Identity mapping,也即 y=x,输出等于输入),这样就增加了网络的深度,并且起码误差不会增加,也即更深的网络不应该带来训练集上误差的上升。而这里提到的使用恒等映射直接将前一层输出传到后面的思想,便是著名深度残差网络 ResNet 的灵感来源。

ResNet 引入了残差网络结构(residual network),通过这种残差网络结构,可以把网络层弄的很深(据说目前可以达到 1000 多层),并且最终的分类效果也非常好,残差网络的基本结构如下图所示,很明显,该图是带有跳跃结构的:

这里写图片描述

残差网络借鉴了高速网络的跨层连接的思想,但是对其进行了改进,残差项原本是带权值的,但 ResNet 用恒等映射代替了它。

假设:

神经网络输入:x
期望输出:H(x),即 H(x) 是期望的复杂映射,如果要学习这样的模型,训练的难度会比较大。

此时,如果已经学习到较为饱和的准确率,或者发现下层的误差变大时,接下来的目标就转化为恒等映射的学习,也就是使得输入x近似于输出 H(x),以保持在后面的层次中不会造成精度下降。

上图的残差网络中,通过捷径连接的方式直接将输入x传到输出作为初始结果,输出结果为 H(x)=F(x)+x,当 F(x)=0 时,H(x)=x,也就是恒等映射。于是,ResNet 相当于将学习目标改变了,不再是学习一个完整的输出,而是目标值H(X)和x的差值,也就是所谓的残差 F(x) := H(x)-x,因此,后面的训练目标就是要将残差结果逼近于 0,使到随着网络加深,准确率不下降。

学习的目标:目标值 H(x) 和输入 x 的差值,即 F(x):=H(x)-x,将残差逼近于 0,使得随着网络加深,准确率不下降。

13.2 ResNet的意义

这里写图片描述

图像是层次非常深的数据,所以要层次深的网络来进行特征提取,网络深度是很有意义的。

一般的卷积神经网络,输入图像 x,输出卷积后的特征 F(x),一次性抽出所有的信息,梯度消失会出现,Res网络就说只学习残差即可。

  • 第一条直接向下传递的网络:试图从 x 中直接学习残差 F(x)

  • 第二条捷径网络:输入 x

  • 整合:将残差和x相加,即 H(x)=F(x)+x,也就是所要求的映射 H(x)

  • 好处:只有一条通路的反向传播,会做连乘导致梯度消失,但现在有两条路,会变成求和的形式,避免梯度消失。后面的层可以看见输入,不至于因为信息损失而失去学习能力。

  • 如果连乘的方式会造成梯度消失的话,那么连加。传统的网络每次学习会学习 x->f(x) 的完整映射,那么 ResNet 只学习残差的映射,

随着网络的加深,出现了训练集准确率下降的现象,但是我们又可以确定这不是由过拟合造成的,因为过拟合的情况下,训练集应该准确率很高,所以作者针对这个问题提出了一种全新的网络,称为深度残差网络,它能够允许网络尽可能的假设,其中引入了一种全新的结构:

这里写图片描述

残差指什么:

ResNet 提出了两种 mapping:

  • 其一:identity mapping,指的 “本身的线”,也就是公式中的 x x x,就是图中弯曲的曲线;

  • 其二:residual mapping,指的是“差”,也就是 y − x y-x yx,所以残差指的是 F ( x ) F(x) F(x) 部分,也就是除过 identity mapping 之外的其余的线;

  • 所以最后的输出为, y = F ( x ) + x y=F(x)+x y=F(x)+x

为什么 ResNet 可以解决随着网络加深,准确率不下降的问题?

理论上,对于 “随着网络加深,准确率下降”的问题,Resnet 提供了两种选择方式,也就是 identity mapping 和 residual mapping,如果网络已经到达最优,继续加深网络,residual mapping 将被 push 为 0,只剩下 identity mapping,这样理论上网络一直处于最优状态了,网络的性能也就不会随着深度增加而降低了。

13.3 ResNet结构

传统的神经网络都是以层叠卷积层的方式提高网络深度,从而提高识别精度,但层叠过多的卷积层会出现一个问题,就是梯度消失,使得反向传播的过程中无法有效的将梯度更新到前面的网络层,导致前面的层的参数无法更新。

而 BN 和 ResNet 的 skip connection 就是为了解决这个问题,BN 通过规范化输入数据,改变数据的分布,在前向传播的过程中,防止梯度消失的问题,而 skip connection 则能在后传过程中更好地把梯度传到更浅的层次中。

问题:为什么加了一个捷径就可以把梯度传到浅层网络?

这和神经网络参数更新的过程密切相关,cs231n 2016 视频有很好的讲解。

前向传播:

  • 首先 x 与 w1 相乘,得到 1
  • 1 与 w2 相乘,得到 0.1
  • 以此类推,如下面的 gif 图绿色数字表示
    这里写图片描述

反向传播:

假设从下一层网络传回来的梯度为 1(最右边的数字),后向传播的梯度数值如下面 gif 图红色数字表示:

这里写图片描述

那么这里可以看到,本来从上一层传过来的梯度为1,经过这个 block 之后,得到的梯度已经变成了 0.0001 和 0.01,也就是说,梯度流过一个 blcok 之后,就已经下降了几个量级,传到前一层的梯度将会变得很小!

当权重很小的时候,前向传播之后到输出层的参数值会非常小,反向传播时依然要和小的权重值相乘,参数值只会越来越小,数量级下降的非常快。

这就是梯度弥散。假如模型的层数越深,这种梯度弥散的情况就更加严重,导致浅层部分的网络权重参数得不到很好的训练,这就是为什么在 Resnet 出现之前,CNN 网络都不超过二十几层的原因。

防止梯度消失的方法:

这里写图片描述

假如,我们在这个 block的 旁边加了一条 “捷径”(如图 5 橙色箭头),也就是常说的 “skip connection”。假设左边的上一层输入为 x,虚线框的输出为 f(x),上下两条路线输出的激活值相加为h(x),即 h(x) = F(x) + x,得出的 h(x) 再输入到下一层。

当进行后向传播时,右边来自深层网络传回来的梯度为 1,经过一个加法门,橙色方向的梯度为 dh(x)/dF(x)=1,蓝色方向的梯度也为 1。这样,经过梯度传播后,现在传到前一层的梯度就变成了 [1, 0.0001, 0.01],多了一个 “1”!正是由于多了这条捷径,来自深层的梯度能直接畅通无阻地通过,去到上一层,使得浅层的网络层参数等到有效的训练!

这个想法是何等的简约而伟大,不得不佩服作者的强大的思维能力!

ResNet网络:

这里写图片描述
直观理解:

这里写图片描述

如图,左边来了一辆装满了“梯度”商品的货车,来领商品的客人一般都要排队一个个拿才可以,如果排队的人太多,后面的人就没有了。于是这时候派了一个人走了“快捷通道”,到货车上领了一部分“梯度”,直接送给后面的人,这样后面排队的客人就能拿到更多的“梯度”。

它使用了一种连接方式叫做 “shortcut connection”,顾名思义,shortcut就是 “抄近道” 的意思,看下图我们就能大致理解:

这里写图片描述

图1 Shortcut Connection

这是文章里面的图,我们可以看到一个“弯弯的弧线“这个就是所谓的 “shortcut connection”,也是文中提到 identity mapping,这张图也诠释了 ResNet 的真谛,当然真正在使用的 ResNet 模块并不是这么单一,文章中就提出了两种方式:

这里写图片描述

图2 两种 ResNet 设计

这两种结构分别针对 ResNet34(左图)和 ResNet50/101/152(右图),一般称整个结构为一个 “building block”,其中右图为“bottleneck design”,目的就是为了降低参数数目,第一个 1x1 的卷积把 256 维的 channel 降到 64 维,然后在最后通过 1x1 卷积恢复,整体上用到参数数目 3x3x64x64 + 1x1x64x256 = 69632,而不使用 bottleneck 的话就是两个 3x3x256 的卷积,参数数目: 3x3x256x256x2 = 1179648,差了 16.94 倍。

对于常规 ResNet,可以用于 34 层或者更少的网络中,对于 Bottleneck Design 的 ResNet 通常用于更深的如 101 这样的网络中,目的是减少计算和参数量(实用目的)。

问题:图1中的 F(x)和 x 的 channel 个数不同怎么办,因为 F(x) 和 x 是按照 channel 维度相加的,channel 不同怎么相加呢?

解释:

针对 channel 个数是否相同,要分成两种情况考虑,如下图:

这里写图片描述

图3 两种 Shortcut Connection 方式

如图 3 所示,我们可以清楚的实线和虚线两种连接方式:

  • 实线的的 Connection 部分 (”第一个粉色矩形和第三个粉色矩形“) 都是 3x3x64 的特征图,他们的 channel 个数一致,所以采用计算方式: y = F ( x ) + x y=F(x)+x y=F(x)+x

  • 虚线的 Connection 部分(”第一个绿色矩形和第三个绿色矩形“)分别是 3x3x64 和 3x3x128 的特征图,他们的 channel 个数不同(64和128),所以采用计算方式: y = F ( x ) + W x y=F(x)+Wx y=F(x)+Wx,其中W是卷积操作,用来调整x的channel维度的;

两个实例:

这里写图片描述

图4 两种 Shortcut Connection 方式实例(左图 channel 一致,右图 channel 不一样)

13.4 ResNet50 和 ResNet101

这里把 ResNet50 和 ResNet101 特别提出,主要因为它们的出镜率很高,所以需要做特别的说明。给出了它们具体的结构:

这里写图片描述

表2,Resnet 不同的结构

首先我们看一下表 2,上面一共提出了 5 中深度的 ResNet,分别是 18,34,50,101 和 152,首先看表 2 最左侧,我们发现所有的网络都分成 5 部分,分别是:conv1,conv2_x,conv3_x,conv4_x,conv5_x,之后的其他论文也会专门用这个称呼指代ResNet50 或者 101 的每部分。

拿 101-layer 那列,我们先看看 101-layer 是不是真的是 101层 网络,首先有个输入 7x7x64 的卷积,然后经过 3 + 4 + 23 + 3 = 33 个 building block,每个 block 为 3 层,所以有 33 x 3 = 99 层,最后有个 fc 层(用于分类),所以 1 + 99 + 1 = 101 层,确实有101 层网络;

注:101层网络仅仅指卷积或者全连接层,而激活层或者Pooling层并没有计算在内;

这里我们关注 50-layer 和 101-layer 这两列,可以发现,它们唯一的不同在于 conv4_x,ResNet50 有 6 个 block,而 ResNet101 有 23 个 block,差了 17 个 block,也就是 17 x 3 = 51 层。

13.5 基于 ResNet101 的 Faster RCNN

文章中把 ResNet101 应用在 Faster RCNN 上取得了更好的结果,结果如下:

这里写图片描述

这里写图片描述

表3,Resnet101 Faster RCNN 在 Pascal VOC07/12 以及 COCO 上的结果

问题:Faster RCNN 中 RPN 和 Fast RCNN 的共享特征图用的是 conv5_x 的输出么?

针对这个问题我们看看实际的基于 ResNet101 的 Faster RCNN 的结构图:

这里写图片描述

图5 基于 ResNet101 的 Faster RCNN

图 5 展示了整个 Faster RCNN 的架构,其中蓝色的部分为 ResNet101,可以发现 conv4_x 的最后的输出为 RPN 和 RoI Pooling 共享的部分,而 conv5_x (共9层网络)都作用于 RoI Pooling 之后的一堆特征图 (14 x 14 x 1024),特征图的大小维度也刚好符合原本的 ResNet101 中 conv5_x 的输入;

最后一定要记得最后要接一个 average pooling,得到 2048 维特征,分别用于分类和框回归。

14、区域 CNN:R-CNN(2013年)、Fast R-CNN(2015年)、Faster R-CNN(2015年)

一些人可能会认为,R-CNN 的出现比此前任何关于新的网络架构的论文都有影响力。第一篇关于 R-CNN 的论文被引用了超过 1600 次。Ross Girshick 和他在 UC Berkeley 的团队在机器视觉上取得了最有影响力的进步。正如他们的文章所写, Fast R-CNN 和 Faster R-CNN 能够让模型变得更快,更好地适应现代的物体识别任务。

R-CNN 的目标是解决物体识别的难题。在获得特定的一张图像后, 我们希望能够绘制图像中所有物体的边缘。这一过程可以分为两个组成部分,一个是区域建议,另一个是分类。

论文的作者强调,任何分类不可知区域的建议方法都应该适用。Selective Search 专用于 RCNN。Selective Search 的作用是聚合 2000 个不同的区域,这些区域有最高的可能性会包含一个物体。在我们设计出一系列的区域建议之后,这些建议被汇合到一个图像大小的区域,能被填入到经过训练的 CNN (论文中的例子是 AlexNet),能为每一个区域提取出一个对应的特征。这个向量随后被用于作为一个线性 SVM 的输入,SVM 经过了每一种类型和输出分类训练。向量还可以被填入到一个有边界的回归区域,获得最精准的一致性。非极值压抑后被用于压制边界区域,这些区域相互之间有很大的重复。

这里写图片描述

Fast R-CNN:

原始模型得到了改进,主要有三个原因:训练需要多个步骤,这在计算上成本过高,而且速度很慢。Fast R-CNN 通过从根本上在不同的建议中分析卷积层的计算,同时打乱生成区域建议的顺利以及运行 CNN,能够快速地解决问题。

这里写图片描述

Faster R-CNN

Faster R-CNN 的工作是克服 R-CNN和 Fast R-CNN 所展示出来的,在训练管道上的复杂性。作者 在最后一个卷积层上引入了一个区域建议网络 (RPN)。这一网络能够只看最后一层的特征就产出区域建议。从这一层面上来说,相同的 R-CNN 管道可用。
这里写图片描述

重要性:

能够识别出一张图像中的某一个物体是一方面,但是,能够识别物体的精确位置对于计算机知识来说是一个巨大的飞跃。更快的 R-CNN 已经成为今天标准的物体识别程序。

15、生成式对抗网络

按照 Yann LeCun 的说法,生成对抗网络可能就是深度学习下一个大突破。假设有两个模型,一个生成模型,一个判别模型。判别模型的任务是决定某幅图像是真实的(来自数据库),还是机器生成的,而生成模型的任务则是生成能够骗过判别模型的图像。这两个模型彼此就形成了“对抗”,发展下去最终会达到一个平衡,生成器生成的图像与真实的图像没有区别,判别器无法区分两者。

这里写图片描述

左边一栏是数据库里的图像,也即真实的图像,右边一栏是机器生成的图像,虽然肉眼看上去基本一样,但在 CNN 看起来却十分不同。

为什么重要?

听上去很简单,然而这是只有在理解了 “数据内在表征” 之后才能建立的模型,你能够训练网络理解真实图像和机器生成的图像之间的区别。因此,这个模型也可以被用于 CNN 中做特征提取。此外,你还能用生成对抗模型制作以假乱真的图片。

16、深度学习在计算机视觉上的应用

计算机视觉中比较成功的深度学习的应用,包括人脸识别,图像问答,物体检测,物体跟踪。

人脸识别:

这里说人脸识别中的人脸比对,即得到一张人脸,与数据库里的人脸进行比对;或同时给两张人脸,判断是不是同一个人。

这方面比较超前的是汤晓鸥教授,他们提出的 DeepID 算法在 LWF 上做得比较好。他们也是用卷积神经网络,但在做比对时,两张人脸分别提取了不同位置特征,然后再进行互相比对,得到最后的比对结果。最新的 DeepID-3 算法,在 LWF 达到了 99.53% 准确度,与肉眼识别结果相差无几。

图片问答问题:

这是 2014 年左右兴起的课题,即给张图片同时问个问题,然后让计算机回答。比如有一个办公室靠海的图片,然后问“桌子后面有什么”,神经网络输出应该是“椅子和窗户”。
这里写图片描述

这一应用引入了 LSTM 网络,这是一个专门设计出来具有一定记忆能力的神经单元。特点是,会把某一个时刻的输出当作下一个时刻的输入。可以认为它比较适合语言等,有时间序列关系的场景。因为我们在读一篇文章和句子的时候,对句子后面的理解是基于前面对词语的记忆。

图像问答问题是基于卷积神经网络和 LSTM 单元的结合,来实现图像问答。LSTM 输出就应该是想要的答案,而输入的就是上一个时刻的输入,以及图像的特征,及问句的每个词语。

物体检测问题:

① Region CNN

深度学习在物体检测方面也取得了非常好的成果。2014 年的 Region CNN 算法,基本思想是首先用一个非深度的方法,在图像中提取可能是物体的图形块,然后深度学习算法根据这些图像块,判断属性和一个具体物体的位置。

这里写图片描述

为什么要用非深度的方法先提取可能的图像块?因为在做物体检测的时候,如果你用扫描窗的方法进行物体监测,要考虑到扫描窗大小的不一样,长宽比和位置不一样,如果每一个图像块都要过一遍深度网络的话,这种时间是你无法接受的。

所以用了一个折中的方法,叫 Selective Search。先把完全不可能是物体的图像块去除,只剩2000左右的图像块放到深度网络里面判断。那么取得的成绩是 A P是 58.5,比以往几乎翻了一倍。有一点不尽如人意的是,region CNN 的速度非常慢,需要 10 到 45 秒处理一张图片。

② Faster R-CNN 方法

Faster R-CNN方法,一个超级加速版 R-CNN 方法。它的速度达到了每秒七帧,即一秒钟可以处理七张图片。技巧在于,不是用图像块来判断是物体还是背景,而把整张图像一起扔进深度网络里,让深度网络自行判断哪里有物体,物体的方块在哪里,种类是什么?

经过深度网络运算的次数从原来的 2000 次降到一次,速度大大提高了。

Faster R-CNN 提出了让深度学习自己生成可能的物体块,再用同样深度网络来判断物体块是否是背景?同时进行分类,还要把边界和给估计出来。

Faster R-CNN 可以做到又快又好,在 VOC2007 上检测 AP 达到 73.2 ,速度也提高了两三百倍。

③ YOLO

YOLO 网络,也是进行物体检测,最快达到每秒钟 155 帧,达到了完全实时。它让一整张图像进入到神经网络,让神经网络自己判断这物体可能在哪里,可能是什么。但它缩减了可能图像块的个数,从原来 Faster R-CNN 的 2000 多个缩减缩减到了 98 个。

这里写图片描述

同时取消了 Faster R-CNN 里面的 RPN 结构,代替 Selective Search 结构。YOLO 里面没有 RPN 这一步,而是直接预测物体的种类和位置。

YOLO 的代价就是精度下降,在 155 帧的速度下精度只有 52.7,45 帧每秒时的精度是 63.4。

④ SSD
这里写图片描述

它是 YOLO 的超级改进版,吸取了 YOLO 的精度下降的教训,同时保留速度快的特点。它能达到58帧每秒,精度有 72.1。速度超过 Faster R-CNN 有 8 倍,但达到类似的精度。

物体跟踪

所谓跟踪,就是在视频里面第一帧时锁定感兴趣的物体,让计算机跟着走,不管怎么旋转晃动,甚至躲在树丛后面也要跟踪。

这里写图片描述

深度学习对跟踪问题有很显著的效果。是第一在线用深度学习进行跟踪的文章,当时超过了其它所有的浅层算法。

ICCV 2015上面,马超提出的 Hierarchical Convolutional Feature 算法,在数据上达到最新的记录。它不是在线更新一个深度学习网络,而是用一个大网络进行预训练,然后让大网络知道什么是物体什么不是物体。

将大网络放在跟踪视频上面,然后再分析网络在视频上产生的不同特征,用比较成熟的浅层跟踪算法来进行跟踪,这样利用了深度学习特征学习比较好的好处,同时又利用了浅层方法速度较快的优点。效果是每秒钟10帧,同时精度破了记录。

最新的跟踪成果是基于 Hierarchical Convolutional Feature,由一个韩国的科研组提出的 MDnet。它集合了前面两种深度算法的集大成,首先离线的时候有学习,学习的不是一般的物体检测,也不是ImageNet,学习的是跟踪视频,然后在学习视频结束后,在真正在使用网络的时候更新网络的一部分。这样既在离线的时候得到了大量的训练,在线的时候又能够很灵活改变自己的网络。

基于嵌入式系统的深度学习

回到 ADAS 问题(慧眼科技的主业),它完全可以用深度学习算法,但对硬件平台有比较高的要求。在汽车上不太可能把一台电脑放上去,因为功率是个问题,很难被市场所接受。

现在的深度学习计算主要是在云端进行,前端拍摄照片,传给后端的云平台处理。但对于 ADAS 而言,无法接受长时间的数据传输的,或许发生事故后,云端的数据还没传回来。

那是否可以考虑 NVIDIA 推出的嵌入式平台?NVIDIA 推出的嵌入式平台,其运算能力远远强过了所有主流的嵌入式平台,运算能力接近主流的顶级 CPU,如台式机的 i7。那么慧眼科技在做工作就是要使得深度学习算法,在嵌入式平台有限的资源情况下能够达到实时效果,而且精度几乎没有减少。

具体做法是,首先对网络进行缩减,可能是对网络的结构缩减,由于识别场景不同,也要进行相应的功能性缩减;另外要用最快的深度检测算法,结合最快的深度跟踪算法,同时自己研发出一些场景分析算法。三者结合在一起,目的是减少运算量,减少检测空间的大小。在这种情况下,在有限资源上实现了使用深度学习算法,但精度减少的非常少。

17、深度有监督学习在计算机视觉领域的进展

17.1 图像分类

自从 Alex 和他的导师 Hinton(深度学习鼻祖)在 2012 年的 ImageNet 大规模图像识别竞赛(ILSVRC2012)中以超过第二名 10 个百分点的成绩 (83.6% 的 Top5 精度) 碾压第二名(74.2%,使用传统的计算机视觉方法)后,深度学习真正开始火热,卷积神经网络(CNN)开始成为家喻户晓的名字,从 12 年的 AlexNet(83.6%),到 2013 年 ImageNet 大规模图像识别竞赛冠军的 88.8%,再到 2014年 VGG 的 92.7% 和同年的 GoogLeNet 的 93.3%,终于,到了 2015 年,在 1000 类的图像识别中,微软提出的残差网(ResNet)以 96.43% 的 Top5 正确率,达到了超过人类的水平(人类的正确率也只有 94.9%).

Top5 精度是指在给出一张图片,模型给出 5 个最有可能的标签,只要在预测的 5 个结果中包含正确标签,即为正确

这里写图片描述

17.2 图像检测(Image Dection)

伴随着图像分类任务,还有另外一个更加有挑战的任务–图像检测,图像检测是指在分类图像的同时把物体用矩形框给圈起来。从 14 年到 16 年,先后涌现出 R-CNN ,Fast R-CNN, Faster R-CNN, YOLO, SSD 等知名框架,其检测平均精度(mAP),在计算机视觉一个知名数据集上 PASCAL VOC 上的检测平均精度(mAP),也从 R-CNN 的 53.3%,到 Fast RCNN的 68.4%,再到 Faster R-CNN 的 75.9%,最新实验显示,Faster RCNN 结合残差网(Resnet-101),其检测精度可以达到 83.8%。深度学习检测速度也越来越快,从最初的 RCNN 模型,处理一张图片要用 2 秒多,到Faster RCNN的198毫秒/张,再到 YOLO 的 155 帧/秒(其缺陷是精度较低,只有 52.7%),最后出来了精度和速度都较高的 SSD,精度 75.1%,速度 23 帧/秒。
这里写图片描述

17.3 图像分割(Semantic Segmentation)

图像分割也是一项有意思的研究领域,它的目的是把图像中各种不同物体给用不同颜色分割出来,如下图所示,其平均精度(mIoU,即预测区域和实际区域交集除以预测区域和实际区域的并集),也从最开始的 FCN 模型(图像语义分割全连接网络,该论文获得计算机视觉顶会 CVPR2015 的最佳论文的)的 62.2%,到 DeepLab 框架的 72.7%,再到牛津大学的 CRF as RNN的 74.7%。该领域是一个仍在进展的领域,仍旧有很大的进步空间。

这里写图片描述

17.4 图像标注–看图说话(Image Captioning)

图像标注是一项引人注目的研究领域,它的研究目的是给出一张图片,你给我用一段文字描述它,如图中所示,图片中第一个图,程序自动给出的描述是 “一个人在尘土飞扬的土路上骑摩托车”,第二个图片是“两只狗在草地上玩耍”。由于该研究巨大的商业价值(例如图片搜索),近几年,工业界的百度,谷歌和微软 以及学术界的加大伯克利,深度学习研究重地多伦多大学都在做相应的研究。

这里写图片描述

17.5 图像生成–文字转图像(Image Generator)

图片标注任务本来是一个半圆,既然我们可以从图片产生描述文字,那么我们也能从文字来生成图片。如图6所示,第一列“一架大客机在蓝天飞翔”,模型自动根据文字生成了 16 张图片,第三列比较有意思,“一群大象在干燥草地行走”(这个有点违背常识,因为大象一般在雨林,不会在干燥草地上行走),模型也相应的生成了对应图片,虽然生成的质量还不算太好,但也已经中规中矩。

这里写图片描述

18、强化学习(Reinforcement Learning)

在监督学习任务中,我们都是给定样本一个固定标签,然后去训练模型,可是,在真实环境中,我们很难给出所有样本的标签,这时候,强化学习就派上了用场。简单来说,我们给定一些奖励或惩罚,强化学习就是让模型自己去试错,模型自己去优化怎么才能得到更多的分数。2016 年大火的 AlphaGo 就是利用了强化学习去训练,它在不断的自我试错和博弈中掌握了最优的策略。利用强化学习去玩 flyppy bird,已经能够玩到几万分了。

这里写图片描述

强化学习在机器人领域和自动驾驶领域有极大的应用价值,当前 arxiv 上基本上每隔几天就会有相应的论文出现。机器人去学习试错来学习最优的表现,这或许是人工智能进化的最优途径,估计也是通向强人工智能的必经之路。

19、YOLO 系列

YOLO 系列中既有 anchor-free 的结构,也有 anchor-based 的结构


19.1 YOLOv1

详细介绍见 本文

论文:You Only Look Once: Unified, Real-Time Object Detection

代码:https://pjreddie.com/darknet/yolo/

作者:Joseph Redmon

时间:2016.05


YOLOv1 提出将目标检测任务定义为单个回归问题,直接从输入图像上得到框的位置和类别。将整个图像空间分割为固定数量的网格单元(例如,使用7×7网格)。每个 cell 都被认为是检测一个或多个物体存在的建议。

在最初的实现中,认为每个 cell 包含两个对象的中心。对每个 cell 进行预测:预测该位置是否有对象、边界框坐标和大小(宽度和高度)以及对象的类别。整个框架是一个单一的网络,它省略了建议生成步骤,可以端到端优化。


YOLO 也面临着一些挑战:

  • 它在给定位置只能检测到两个对象,这使得很难检测到小对象和拥挤的对象[40]
  • 只有最后一个特征图用于预测,不适合多尺度、多纵横比的目标预测。

YOLOv1 结构介绍:

  • 输入:将图像分为 S × S S\times S S×S 的网格(7x7),如果目标的中心点落入了对应网格,则由该网格负责预测该目标
  • 每个网格预测 2 个 bbox 和每个 bbox 中包含目标的概率,定义 confidence 为 P r ( o b j e c t ) × I o U p r e d t r u t h Pr(object) \times IoU_{pred}^{truth} Pr(object)×IoUpredtruth
  • 如果某个网格没有目标落入,则对应 confidence 为 0,否则期望 confidence score = IoU
  • 每个 bbox 的预测包含五个参数: ( x , y , w , h , c o n f i d e n c e ) (x, y, w, h, confidence) (x,y,w,h,confidence) ( x , y ) (x, y) (x,y) 为框的中心点和网格边界的距离(相对当前网格的偏移值), ( w , h ) (w, h) (w,h) 是宽高和全图比(相当于归一化了),confidence代表了所预测的box中含有 object 的置信度和这个 box 预测的有多准两重信息。
  • 每个网格也会预测类别 P r ( C l a s s i ∣ O b j e c t ) Pr(Class_i|Object) Pr(ClassiObject),也就是每个框会预测其对应类别。
  • 测试时,对每个框预测的类别如下,该类别包含了这个 bbox 中该类别的概率和位置匹配的准确性: P r ( c l a s s i ∣ o b j e c t ) ∗ P r ( O b j e c t ) ∗ I o U p r e d t r u t h = P r ( C l a s s i ) ∗ I o U p r e d t r u t h Pr(class_i|object)*Pr(Object)*IoU_{pred}^{truth}=Pr(Class_i)*IoU_{pred}^{truth} Pr(classiobject)Pr(Object)IoUpredtruth=Pr(Classi)IoUpredtruth
  • 在 PASCAL VOC 测试时,作者使用 S=7,B=2,C=20,最终得到 7x7x30 的向量

为什么每个网格输出 30 维向量:

30 维向量 = 20 个目标的类别概率(VOC 类别) + 2 个 bounding box x4 个坐标 + 2 个 bounding box 包含目标的置信度 confidence(前、背景)

在这里插入图片描述


网络结构:

  • 标准结构:24 conv layers + 2 fully connected layers
  • Fast 结构:9 conv layers + 2 fully connected layers
  • 输出:7x7x30 tensor

训练:

  • 输入 448x448 的图像
  • 输出每个网格中的每个框的 ( x , y , w , h , c o n f i d e n c e ) (x, y, w, h, confidence) (x,y,w,h,confidence)
  • 虽然每个网格中可能预测多个 bbox,在训练阶段,只期望对每个目标预测一个框,故此处指保留和 gt 的 IoU 最大的框。

推理:

  • 在每个图像中预测 98 个bbox(49 个网格,每个网格预测两个框,保留 IoU 最大的那个)
  • 每个网格会预测两个 bbox,通过 NMS 后,会保留一个 bbox

如何进行 NMS:

因为我们对一个网格要预测两个bbox,所以最后我们能得到个 7x7x2=98 个bbox。

首先,将这 98 个 bbox 中置信度低的框去掉,然后再根据置信度对剩下的bbox排序,使用 NMS 算法,把重复度高的框的置信度设为 0。

对于留下的框,再根据分类概率得到它们的类别,这里注意得到的框的大小都是相对于原图大小的,都是 0~1 之间的值,所以输出的时候还需要还原,才能得到真实的bbox的尺寸大小。

  • YOLO v1 定位错误较多,定位的错误高于其他所有错误的总和
  • Fast RCNN 定位错误的很少,但有很多背景误识别,13.6% 的检测结果是假正,即不包含任何目标,约是 YOLO v1 背景误识别的 3 倍。

优势如下:

  • YOLOv1 很快!由于不需要复杂的 pipeline,在 Titan X GPU 上能达到 45fps,能够实时处理视频流,且准确率是当时实时系统的 2 倍。
  • YOLOv1 在推理的时候在全图上进行,在训练和测试时都将全图看做一个整体,没有 RPN 等操作,比 Fast R-CNN 对背景的误检少了一半(Fast RCNN 由于无法看到全局的信息,所有很多背景的误检)。
  • YOLOv1 能够学习到目标更泛化的特征。
  • YOLOv1 虽然比当时 SOTA 的方法效果差些,但速度很快。

YOLO v1 的不足:

  • YOLO v1 在每个网格中预测两个框,并且属于同一个类别,这种空间约束限制了对距离近的目标的预测,会导致漏检,如多个小目标共现的区域
  • YOLO v1 模型是从训练数据中学习到的目标纵横比,所以难以泛化到少见的纵横比目标上,导致边界不准。
  • YOLO v1 的 loss 函数将大目标和小目标同等对待,大目标的小错误是可以容忍的,但小目标的小错误对 IoU 影响较大,会导致对小目标定位不准
  • 使用全连接层,参数量巨大,而且也因此在检测时,YOLO 训练模型只支持与训练图像相同的输入分辨率。
  • 一个网格只能预测一个物体。
  • anchor-free的方法没有anchor-based的准确。

19.2 YOLOv2

详细介绍见 本文

论文:Yolo9000: Better, faster, stronger

代码:https://github.com/pjreddie/darknet

出处:CVPR2017

作者:Joseph Redmon

时间:2016.12


YOLOv1 有很多不足,其中最主要的两点在于:

  • 定位不准
  • Recall 低

所以 YOLOv2 也主要在提高这两个问题上下功夫。但 YOLOv2 没有提高模型大小,同时速度更快了,主要从以下方面来让网络效果更好

即:更好、更快、更强三方面来进行优化


1、更好

  • 1、Batch Normalization:在 YOLOv1 的所有卷积层后面加 BN,提升了 2mAP

  • 2、High Resolution Classifier:YOLOv1 使用 224x224 大小预训练,YOLOv2 提升到了 448x448 大小,能帮助网络在大分辨率输入上更好提取特征

  • 3、回归使用了 anchor 来预测框。输入图像大小 416x416(为了保证奇数大小特征图),下采样 32 倍,得到 13x13 大小特征图,每张图上能预测的目标从 98 变成了 1k 多,也提出了objectness,预测每个 anchor 和 gt 的 IoU,和该 anchor 是目标的概率无 anchor 时 mAP=69.5,recall=81%,有 anchor 后,mAP=69.2,recall=88%。提升了 recall 后,表示模型有了更大的提升空间。

  • 4、使用了聚类的方法来选择 anchor 的尺度,避免了手动选择需要调参,在训练集上使用了 k-means 来自动选择最优的值。由于欧氏距离对尺寸很敏感,所以作者使用 d ( b o x , c e n t r o i d ) = 1 − I o U ( b o x , c e n t r o i d ) d(box, centroid) = 1-IoU(box, centroid) d(box,centroid)=1IoU(box,centroid) 的方式来度量距离。 5 种形心的聚类方法得到的框的效果和 9 种 anchor box 效果类似。使用 9 种形心的聚类方法能够得到更高的 IoU。

  • 5、多尺度预测,YOLOv2 在 13x13 的特征图上预测,但得益于大特征图的预训练,这样的大小也也足够大目标的预测了。但同时也在 26x26 大小的特征图上也引出了分支,得到了 1% 的性能提升。

  • 6、Multi-scale Training

    • YOLOv1 中使用大小为 448x448 的输入,YOLOv2 中由于要添加 anchor,所以改成了 416x416,但为了对不同大小的目标更加鲁棒,所以 YOLOv2 使用了多尺度训练。
    • 多尺度训练的模式:在每 10 个 epoch 随机选择训练的尺度,由于最后下采样 32 倍,所以作者选择了 32 的倍数:{320, 352, …, 608},最小的为 320, 最大的为 608。
    • 这种机制迫使网络学习跨各种输入维度进行良好的预测。这意味着同一个网络可以在不同的分辨率下预测检测结果。网络在较小的尺寸下运行速度更快,因此 YOLOv2 可以轻松地在速度和精度之间进行权衡。
    • 在低分辨率时,YOLOv2 是一种耗费小而相当精确的检测器,288x288 大小时,可以达到 90 FPS,且 mAP 和 Fast RCNN 类似。
    • 在高分辨率时,YOLOv2 在 VOC2007 上达到了 SOTA的 78.6 mAP,且接近实时速度。

2、更快

  • YOLOv2 中提出了一个新的分类模型,Darknet-19,共 19 层卷积层,5 层 maxpooling,结构见表 6

3、更强

  • 将 coco 和 ImageNet 联合训练,让网络从分类数据中学到更多的类别,从检测数据中学到更多的位置信息

19.3 YOLOv3

详细介绍见 本文

论文: YOLOv3: An Incremental Improvement

代码:https://github.com/pjreddie/darknet

作者:Joseph Redmon

时间:2018.08


由于 YOLO 系列对小目标的检测效果一直不太好,所以 YOLOv3 主要是网络结构的改进,使其更适合小目标检测;

YOLOv3 提出了 objectness score,使用 logistic 回归的方法来对每个框预测 objectness score:

  • 1:当一个先验框和 gt 的重合率大于其他先验框时,objectness score = 1
  • -1:当一个先验框的 IoU 不是最大,但大于阈值时(0.5),则 objectness score = -1,不参与训练

YOLOv3 在 3 个尺度上进行框的预测,最后输出三个信息:bbox、objectness、class

在 COCO 数据集中,就会在每个尺度上输出:

  • N × B × [ 3 ∗ ( 4 + 1 + 80 ) ] N\times B \times [3*(4+1+80)] N×B×[3(4+1+80)] 偏移信息
  • 1 个 objectness
  • 80 个类别预测

预测要点:

  • 使用 k-means 距离的方法来确定先验 bbox,9 个形心和 3 个尺度,然后使用尺度来将这些簇分开
  • COCO 上的 9 个簇分别为:(10x13), (16x30),(33x23), (30x61), (62x45), (59x119), (116x90), (156x198), (373x326)。

在 YOLOv2 中使用的是 Darknet-19,YOLOv3 使用 Darknet-53。

YOLOv3 的 APs 指标表现很好,但在大中型目标上效果较差,需要继续研究


19.4 YOLOv4

详细介绍见 本文

论文:YOLOv4: Optimal speed and accuracy of object detection

代码:https://github.com/AlexeyAB/darknet

作者:AlexeyAB

时间:2020.08


致力于设计一个快速的检测器,称为 YOLOv4,其结果如图 1 所示,贡献点如下:

  • 设计了一个又快又好的检测器
  • 验证了很多 Bag of Freebies 和 Bag of Specials 方法的效果
  • 证明了现有的 SOTA 的方法可以更有效并且在单个 GPU 上训练

YOLOv4 将目标检测器分为了 4 个部分:

  • Input:Image、Patches、Image Pyramid
  • Backbone:VGG-16、ResNet、EfficientNet 等
  • Neck:
    • Additional blocks:SPP、ASPP、RFB、SAM 等
    • Path-aggregation blocks:FPN、PAN、NAS-FPN、ASFF 等
  • Heads:
    • Dense Prediction(one-stage):
      • RPN、SSD、YOLO、RetinaNet(anchor based)
      • CornerNet、CenterNet、FCOS(anchor free)
    • Sparse Prediction(two-stage):
      • Faster RCNN、R-FCN、Mask RCNN(anchor based)
      • RepPoints(anchor free)

YOLOv4 由以下三个部分组成,使用了很多 BoF 和 BoS:

  • Backbone:CSPDarknet53
  • Neck:SPP, PAN
  • Head:YOLOv3

使用的策略:

  • Backbone:

    • BoF: CutMix and Mosaic data augmentation, DropBlock regularization, Class label smoothing
    • BoS: Mish activation, Cross-stage partial connections (CSP), Multiinput weighted residual connections (MiWRC)
  • detector:

    • BoF: CIoU-loss, CmBN, DropBlock regularization, Mosaic data augmentation, Self-Adversarial Training, Eliminate grid sensitivity, Using multiple anchors for a single ground truth, Cosine annealing scheduler [52], Optimal hyperparameters, Random training shapes
    • BoS: Mish activation, SPP-block, SAM-block, PAN path-aggregation block, DIoU-NMS

19.5 Scaled-YOLOv4

详细介绍见 本文

论文:Scaled-YOLOv4: Scaling Cross Stage Partial Network

代码:https://github.com/WongKinYiu/ScaledYOLOv4

作者:Chien-Yao Wang、Alexey AB

出处:CVPR2021

时间:2021.02


作者将 YOLOv4 经过尺度缩放,分别适用于:general GPU、low-end GPU、high-end GPU

YOLOv4 是为在 general GPU 上运行的实时目标检测网络,作者又重新设计了一下,得到更好的 speed/accuracy trade-off 网络 YOLOv4-CSP


Backbone:

CSPDarknet53 的设计, cross-stage 的下采样卷积的计算是没有包含在残差块中的,故可以推理出 CSPDarknet 的计算量为 w h b 2 ( 9 / 4 + 3 / 4 + 5 k / 2 ) whb^2(9/4+3/4+5k/2) whb2(9/4+3/4+5k/2),所以 CSPDarknet stage 在 k>1 的时候的计算量是优于 Darknet 的,CSPDarknet53 的每个 stage 的残差层分别为 1-2-8-8-4,为了得到更好的 speed/accuracy trade-off,将 CSP 的第一个 stage 转换成原始的 Darknet 残差层。


Neck:

为了进一步降低计算量,也把 YOLOv4 中的 PAN 进一步 CSP-ize,PAN 结构的计算过程如图 2a 所示,它主要是整合来自不同特征金字塔的特征,然后经过两组反向 Darknet 残差层(没有 shortcut 连接),CSP-ization 之后的计算过程如图 2b 所示,降低了 40% 的计算量。


SPP:

SPP 模块也被嵌入 CSPPAN 的第一个 group 的中间位置


19.6 YOLOv5

详细介绍见 本文

论文:暂无

代码:https://github.com/ultralytics/yolov5

官方介绍:https://docs.ultralytics.com/

出处:ultralytics 公司

时间:2020.05


YOLOv5 是基于 YOLOv3 改进而来,体积小,YOLOv5s 的权重文件为27MB。

YOLOv4(Darknet架构)的权重文件为 244MB。YOLOv5 比 YOLOv4 小近 90%。这意味着YOLOv5 可以更轻松地部署到嵌入式设备。

此外,因为 YOLOv5 是在 PyTorch 中实现的,所以它受益于已建立的 PyTorch 生态系统

YOLOv5 还可以轻松地编译为 ONNX 和 CoreML,因此这也使得部署到移动设备的过程更加简单。


19.7 YOLOv6

详细介绍见 本文

论文:YOLOv6: A Single-Stage Object Detection Framework for Industrial
Applications

代码:https://github.com/meituan/YOLOv6

官方博文:https://blog.csdn.net/MeituanTech/article/details/125437630

作者:美团

时间:2022.09


YOLO 系列算法回顾:

  • YOLOv1-v3,也是最初的 one-stage 检测器 YOLO 系列的开创者 Joseph Redmon 提出的,为后面的改进方法打了很好的基石
  • YOLOv4 将检测框架结构划分为 3 个部分:backbone、neck、head,然后使用了很多策略来设计了一个适合在单 GPU 上训练的网络结构
  • YOLOv5、YOLOX、PPYOLO、YOLOv7 都是为部署做了相关的工作,通过模型缩放的形式来适应于不同的场景

YOLOv6 主要做的工作如下:

  • 设计了对硬件友好的 backbone 和 neck:设计了更高效的 Backbone 和 Neck :基于 RepVGG style[4] 设计了可重参数化、更高效的骨干网络 EfficientRep Backbone 和 Rep-PAN Neck。
  • 有效的进行了 head 解耦:在维持精度的同时,进一步降低了一般解耦头带来的额外延时开销
  • 在训练策略上,采用Anchor-free 无锚范式,同时辅以 TAL(YOLOv6 第一版使用的 SimOTA[2] )标签分配策略以及 SIoU[9] 边界框回归损失来进一步提高检测精度。

YOLOv6 的改进集中在如下部分:

  • Network design
    • Backbone:RepVGG 很适合小网络,但很难扩展到大网络(参数爆炸),所以使用 RepBlock 作为小网络的基础 block,使用 CSPStackRep block 作为大网络的 block。
    • Neck:类似 YOLOv4 和 YOLOv5,使用 PAN 的结构,对大小网络都使用 Rep-PAN
    • Head:对 head 进行了解耦,使用 Efficient Decoupled Head
  • Label assignment:作者对很多方法都做了实验,最后选择了 TAL
  • Loss function:VariFocal 为分类 loss,SIoU/GIoU 为回归 loss
  • Data augmentation:Mosaic 和 Mixup
  • Industry-handy improvements:作者引入了 self-distillation 和 更多的 epochs 来提高性能。self-distillation 是每个学生网络的分类和回归都被教师网络监督。
  • Quantization and deployment:为了解决量化后的重参数化模型的性能下降问题,作者使用 RepOptimizer 的方法来得到 PTQ-friendly weights。

① Backbone:EfficientRep

  • 小模型:
    • 在训练中使用 Rep block,如图 3a
    • 在推理时使用 RepConv,3x3 卷积 + ReLU 堆积而成的结构,如图 3b
  • 大模型:
    • 使用 CSPStackRep block 来得到中/大模型,如图 3c,3 个 1x1 conv + 2 个 RepVGG (训练) / RepConv (测试) + 1 个残差通道

在这里插入图片描述

② Neck:Rep-PAN

Neck 延续了 YOLOv4 及 YOLOv5 的架构——PAN,同样为了降低在硬件上的延时,在Neck上的特征融合结构中也引入了Rep结构,形成了 Rep-PAN

③ Head:Efficient decoupled head

④ Anchor-free

YOLOv6 中使用 anchor-point-based 大方式,也就是 box regression 分支是预测 anchor point 到 bbox 的四个边的距离。

⑤ Label Assignment:TAL

SimOTA:

SimOTA 是 OTA 的简化版本,将标签分配问题构造成了一个最优传输问题,通过找到最优传输方式,来得到每个 anchor 和 gt 的匹配结果。YOLOv6 的早期版本其实是使用的 SimOTA 的,那个时候论文还没有放出来,只有 github 代码。但由于 SimOTA 会拉慢训练速度,容易导致训练不稳定,所以又寻找了代替的方法。

Task Alignment Learning:

TAL 是在 TOOD 中被提出的,其中设计了一个【分类得分和定位框质量的统一度量标准】,使用该度量结果代替 IoU 来帮助分配标签,有助于解决任务不对齐的问题,且更稳定,效果更好。

⑥ loss:VariFocal Loss (VFL),SIoU,其他使用 GIoU

⑦ 训练更多的 epochs

⑧ Self-distillation
为了提高模型效果,但不引入额外开销,作者使用了 KL 散度作为衡量学生网络和教师网络分布的指标。

为什么叫做 self-distillation 呢?就是因为这里 学生网络=教师网络。

KL 散度整你用来衡量数据分布的差异,所以只能适用于分类结果,作者又参照了 DFL loss,也将其用于回归结果的衡量,故总的衡量方法为:

在这里插入图片描述

所以,回归 loss 为:

在这里插入图片描述


19.8 YOLOv7

详细介绍见 本文

论文:YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors

代码:https:// github.com/WongKinYiu/yolov7

出处:暂无

作者:Chien-Yao,Alexey AB (和 YOLOv4 同)

时间:2022.07


从优化方法、优化模块等方面入手,通过提高训练过程的 cost 来提高检测效果,但不会提高推理过程的 cost。


YOLOv7 的思路是什么:

  • 重参数化和 label assignment 对网络的效果都比较重要,但近来提出的方法中,或多或少会有些问题
  • YOLOv7 会从发现的这些问题入手,并提出对应的解决方法

在正文前,YOLOv7 也总结了一下现有的 SOTA 实时目标检测器,大多基于 YOLO 和 FCOS,要想成为一个优秀的实时检测器,一般需要具有如下几个特点,并且主要从 4/5/6 三点来提出问题并解决:

  • a faster and stronger network architecture
  • a more effective feature integration method [22, 97, 37, 74, 59, 30, 9, 45]
  • a more accurate detection method [76, 77, 69]
  • a more robust loss function [96, 64, 6, 56, 95, 57]
  • a more efficient label assignment method [99, 20, 17, 82, 42]
  • a more efficient training method.

“结构重参数化” 的实质:训练时的结构对应一组参数,推理时我们想要的结构对应另一组参数,只要能把前者的参数等价转换为后者,就可以将前者的结构等价转换为后者。


20、ResNeXt

详细介绍见 本文

论文:Aggregated Residual Transformations for Deep Neural Networks

代码:https://github.com/miraclewkf/ResNeXt-PyTorch

出处:CVPR 2017


贡献:

  • 提出了 cardinality 的概念,即一个 block 中的基的数量,或者分组的数量
  • 实验证明提高模型 cardinality 比提高宽度或深度更能带来效果的提升,且不会增加额外的计算量
  • 可以看做将 ResNet 中每个 block 的卷积替换成了分组卷积,并且带来了效果的提升

ResNeXt 是怎么做的:

  • 套用 ResNet 的重复堆叠结构
  • 引入 Inception 的 split-tranform-merge 策略,但并行拆开的分支卷积核大小是相同的,然后相加(如图 1 右边)。此外,这种结构和图 3 的其他两种结构是等价的。可以看做将 ResNet 中每个 block 的卷积替换成了分组卷积。

在这里插入图片描述


ResNeXt 提出了一个新的概念——cardinality,the size of the set of transformations,和网络深度以及宽度一起作为网络的设计量。

cardinality 也可以翻译为“基”或者“势”,表示一个 block 中,可以理解为特征被分为了几个基本单元,或者几组,如果被分为 32 组,则cardinality = 32。

ResNeXt 的设计也是重复的堆叠,且设计遵循两个规则,设计的结构如表 1 所示:

  • 如果使用相同大小的卷积核来处理特征图,则 blocks 之间共享参数
  • 如果特征图下采样 2 倍,则 channels 宽度扩展 2 倍

在这里插入图片描述


ResNeXt 的结构和下面两个结构是很类似的:

① Inception-ResNet

如图 1 右侧所示的结构(也就是下图 3a),其实和图 3b 的结构是等价的,只是和 Inception-ResNet 不同的是,ResNeXt 的并行通道的卷积核大小是相同的,在设计上更简单通用。

② Grouped Convolutions

如图 3c 所示,如果将图 3b 的第一层多个 1x1 卷积聚合起来,输出 128-d 特征向量,然后使用分组卷积(32组)来进行后续的特征提取,其实和图 3b 的并行分支是等价的,最后将分组卷积的每组卷积的输出 concat,就得到最后的输出。

在这里插入图片描述


21、DenseNet

详细介绍见 本文

论文:Densely Connected Convolutional Networks

代码:https://github.com/liuzhuang13/DenseNet

出处:CVPR2017 | 康奈尔大学 清华大学 Facebook


越来越深的神经网络会带来梯度消失问题,ResNet 和 Highway Network 使用了恒等映射的方式,让网络都超过了 100 层且效果良好,也就是给梯度增加了一条高速路,可以顺畅的在浅层和深层之间传输。

但这些传输只能在前后两层之间传递,没有最大化信息传输,所以作者提出了 DenseNet。


DenseNet 挣脱了加深和加宽模型的思路,而是通过最大限度的特征重用和旁路的思想来提升网络效果。

DenseNet 的动机:让信息在网络中的所有层中传递最大化

DenseNet 的做法:在一个 block 内部(即特征图大小都相同),将所有的层都进行连接,即第一层的特征会直接传输给后面的所有层,后面的层会接受前面所有层的输出特征。如图 1 所示。

DenseNet 的特征是如何结合的:不像 ResNet 那样相加起来,而是 concat,所以越往后通道越多

DenseNet 的参数少的原因:DenseNet 的通道很少(如每层 12 个通道),且层浅


下图展示了一个 Dense block 内部的结构,一个 block 内部会有多个卷积层,每个卷积层的输入来自前面所有层的输出,前面所有层的特征输出会 concat 然后送入当前层。

Dense 连接只会在每个 Dense block 内部进行,不会进行跨 block 的 Dense 连接

在这里插入图片描述

在这里插入图片描述


首先看一下 ResNet 的网络结构:每层接收上一层的特征输出和上一层的原始输出

在这里插入图片描述

然后再来看 DenseNet 的网络结构:每层接收前面所有层的特征输出,然后进行对应层的特征提取

在这里插入图片描述


DenseNet 的优点:

  • 网络更窄,参数更少
  • 旁路密集连接增加了特征的重用
  • 信息流通最大化,训练简单
  • 缓解了梯度消失的问题

22、 CSPNet

详细介绍见 本文

论文:CSPNet: A new backbone that can enhance learning capability of CNN

代码:https://github.com/open-mmlab/mmdetection/blob/master/mmdet/models/backbones/csp_darknet.py

出处:CVPR2019


CSPNet 的提出解决了什么问题:

  • 强化 CNN 的学习能力:现有 CNN 网络一般在轻量化以后就会降低效果,CSPNet 希望能够在轻量化的同时保持良好的效果。CSPNet 在嵌入分类任务的 ResNet、ResNeXt、DenseNet 等网络后,可以在保持原有效果的同时,降低计算量 10%~20%
  • 移除计算瓶颈:过高的计算瓶颈会导致推理时间更长,在其计算的过程中其他很多单元空闲,所以作者期望所有的计算单元的效率差不太多,从而提升每个单元的利用率,减少不必要的损耗。
  • 减少内存占用:CSPNet 使用 cross-channel pooling 的方法来压缩特征图

Cross Stage Partial Network (CSPNet) 的主要设计思想:让网络中的梯度进行丰富的结合,降低冗余,减少计算量

在这里插入图片描述


在介绍 CSPNet 之前,先看看 DenseNet 的结构

图 2a 展示了 DenseNet 的一个 stage 结构:每一层的输入来自于前面所有层输出的 concat 结果

  • 每个 stage 都包括一个 dense block + transition layer
  • 每个 dense block 由 k 个 dense layer 组成
  • 每个 dense layer 的输出会作为下一个 dense layer 的输入
  • Transition layer 也就是过渡层,是连接 block 的层,一般包含瓶颈层(1x1)和池化层,用于降维和降分辨率

DenseNet 的过程可以用如下方式表示,其中 * 表示卷积, x i x_i xi 表示第 i i i 个 dense layer 的输出。

在这里插入图片描述

反向传播过程表示如下, g i g_i gi 表示传递给第 i 个 dense layer的梯度。可以看出,大量的梯度信息是被不同 dense layer 重复使用的:

在这里插入图片描述


图 2b 展示了 CSPDenseNet 的一个 stage,CSPDenseNet 的组成:

  • Partial dense block:
    每个 stage 的特征图都根据 channel 被分为两个部分 x 0 = [ x 0 ′ , x 0 ′ ′ ] x_0 = [x_0', x_0''] x0=[x0,x0′′]
    • x 0 ′ x_0' x0 :会经过 dense block, x 0 ′ ′ x_0'' x0′′ :会直接送入 stage 的最后一层,不经过任何特征提取
    • 每个 stage 的输出可以表示为: [ x 0 ′ ′ , x 1 , . . . , x k ] [x_0'', x_1, ..., x_k] [x0′′,x1,...,xk],然后输入 transition layer
  • Partial transition layer
    • 上面的 transition layer 的输出为 x T x_T xT,然后会和 x 0 ′ ′ x_0'' x0′′ 进行 concat ,最后输入后面的 transition layer,得到输出 x U x_U xU,如图 3 所示

由于这里 transition layer 使用的是 concat 方法,而 concat 方法的梯度传播会分开进行,就是还是会传递到对应的来源处去,所以经过密集 block 和未经过密集 block 的特征是分别优化的,梯度单独更新。


CSPDenseNet 保留了 DenseNet 特性重用特性的优点,但同时通过截断梯度流防止了过多的重复梯度信息。该思想通过设计一种分层的特征融合策略来实现,并应用于局部过渡层。

下图 3 也展示了不同时间进行特征融合的方式:

  • 使用 Fusion First 中梯度会被大量重复利用,没有明显的计算量下降, top-1 acc 下降了 1.5%

  • 使用 Fusion Last 先使用 transition 降低了 dense block 的维度,极大降低了计算量,top-1 acc 仅仅下降了0.1个百分点

  • 同时使用 Fusion First 和 Fusion Last 相结合的 CSP 所采用的融合方式可以在降低计算代价的同时,提升准确率(图 3b)

在这里插入图片描述


将 CSPNet 和其他结构结合,如图 5 所示,CSPNet 可以和 ResNet、ResNeXt 进行结合,由于每个 Res block 只有一半的 channel 会经过,所以不需要引入 bottleneck。

在这里插入图片描述


23、 RepVGG

详细介绍见 本文

论文:RepVGG: Making VGG-style ConvNets Great Again

代码:https://github.com/megvii-model/RepVGG

出处:CVPR2021 | 清华大学 旷世


RepVGG 的贡献:

  • 使用结构重参数化的方法将训练和推理结构进行解耦,训练使用多分支结构,推理使用单分支结构,实现了一个 speed-accuracy trade-off 的简单网络结构
  • 在分类和分割上展示了良好的效果,且易于部署

随着 Inception、ResNet、DenseNet 等方法的提出,卷积神经网络越来越复杂,还有一些基于自动或手动框架选择,虽然这些复杂的网络能够带来好的效果,但仍然会有很多问题:

  • 复杂的多分支网络让模型更复杂,执行或定制起来更难,降低推理效率
  • 很多组件(如 depthwise、Xception、MobileNet等)会提高显存,在一些设备上难以支持,虽然这些方法都验证了自己的 FLOPs,但该指标并不能准确的反应其真实的速度,有些在指标上快于 VGG 和 ResNet,但实际跑起来也不一定快。

所以本文提出了 RepVGG,是一个 VGG-style 的结构,有如下优势:

  • RepVGG 和 VGG 结构类似,没有旁路分支
  • 只使用了 3x3 conv 和 ReLU
  • 整个具体的结构没有使用自动查找、微调等,也没有复杂的设计

RepVGG 面临的问题:

  • 只用单路的结构很难打得过 resnet 那种多路的结构,resnet 的多路结构能保证其梯度传递

RepVGG 如何解决上述问题:结构重参数化(训练和推理使用不同的结构)

  • 既然多路结构有利于训练,那么就使用多路结构来训练,如图 2B 所示,使用 1x1 conv 和恒等映射作为旁路
  • 但多路结构不利于推理,那么就使用单路结构来推理,如图 2C 所示,只有 3x3 conv + ReLU

在这里插入图片描述


RepVGG 的设计过程:

1、使用简单结构的卷积神经网络,更加灵活(ResNet 使用残差就限制了必须等大,且多分支结构难以通道剪枝)

2、在训练的时候使用多分支结构(ResNet 证明了多分支结构的效果):虽然多分支的结构在推理的时候效率严重不足,但其胜在训练的效果,所以 RepVGG 在训练的时候选择了多分支结构,而且选择的是 3 分支结构(1 个主分支,1 个 1x1 分支,1 个恒等映射分支, y = x + g ( x ) + f ( x ) y = x + g(x) + f(x) y=x+g(x)+f(x)),当有 n 个 blocks 时,相当于有 3 n 3^n 3n 个模型

3、在推理阶段进行重参数化:卷积有可加性,将每个 BN 和其前面的 conv 可以转换成一个【conv with bias vector】,然后将得到的 3 组卷积相加

  • 将 3 分支网络等价转换,简化成单分支网络
  • 具体实现方法是依据卷积核的可加性,先对卷积 “吸BN”(即将 conv+bn 转换成一个带 bias 的 conv),恒等映射分支可以看做 1x1 卷积,吸 BN 后得到 2 个 1x1 卷积,1 个 3x3 卷积,然后将三个卷积以中心点为基准相加,将 3 个卷积合并为 1 个

在这里插入图片描述


RepVGG 结构:

表 2 展示了 RepVGG 的设计细节,包括宽度和深度,其中主要使用了 3x3 conv,没有使用 max pooling。

深度:

  • 有 5 个 stages,每个 stage 的第一层的 3x3 conv 会下采样 2 倍
  • RepVGG-A:每个 stage 分别有 1,2,4,14,11 层(对比 ResNet-18/34/50)
  • RepVGG-B:每个 stage 分别有 1,4,6,16,11 层(对比更大的模型)
  • 第一个和最后一个 block 没有增加层数的原因在于,第一层图分辨率很大,容易带来耗时,最后一层通道很多,也同样带来耗时

宽度:

  • 每个 stage 的基础通道数设置为 [64, 128, 256, 512]
  • 使用 a a a 作为前 4 层的缩放比, b b b 作为最后一层的缩放比,且一般 b > a b>a b>a
  • 为了进一步降低参数和耗时,使用了分组卷积,给 RepVGG-A 的 3/5/7…/21 层设置了分组数 g g g,给 RepVGG-B 的 23/25/27 层也设置了分组数 g g g

在这里插入图片描述


24、 MobileNet 系列

详细介绍见 本文


24.1 MobileNetV1

论文:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications

出处:CVPR 2017 | 谷歌


贡献:

  • 提出了深度可分离卷积,将标准卷积用逐通道卷积+逐点卷积来代替
  • 能够在边端设备使用,在保证效果的通道提升速度

更强的卷积神经网络一般情况下意味着更深和更宽的网络结构,但这样就会导致速度和效率的缺失,所以,MobileNet 的作者提出了一个搞笑的网络结构,致力于建立一个适用于移动端和嵌入式设备的网络结构。MobileNetV1 可以理解为把 VGG 中的标准卷积层换成深度可分离卷积


深度可分离卷积是 MobileNet 的一个非常重要的核心点,由两部分构成:

  • depthwise convolution:每个卷积核负责一个输入通道的卷积,图 2b
  • pointwise convolution:1x1xC 的形式,对 depthwise 得到的卷积特征进行点对点的特征聚合,图 2c

普通卷积是计算量:

  • 假设输入特征图 F F F D F × D F × M D_F \times D_F \times M DF×DF×M,输出特征图 G G G D G × D G × N D_G \times D_G \times N DG×DG×N
  • 普通卷积核 K K K 的参数量为 D K × D K × × M × N D_K \times D_K \times \times M \times N DK×DK××M×N
  • 普通卷积核的计算量为 D K ⋅ D K ⋅ M ⋅ N ⋅ D F ⋅ D F D_K \cdot D_K \cdot M \cdot N \cdot D_F \cdot D_F DKDKMNDFDF

深度可分离卷积的计算量:

  • 输入特征图 F F F D F × D F × M D_F \times D_F \times M DF×DF×M,输出特征图 G G G D G × D G × N D_G \times D_G \times N DG×DG×N
  • 首先对每个通道分别使用一个卷积核进行特征提取,计算量为 D K ⋅ D K ⋅ M ⋅ D F ⋅ D F D_K \cdot D_K \cdot M \cdot D_F \cdot D_F DKDKMDFDF
  • 然后对得到的特征图使用 1x1 的卷积核进行特征融合,计算量为 M ⋅ N ⋅ D F ⋅ D F M \cdot N \cdot D_F \cdot D_F MNDFDF
  • 总的计算量为: D K ⋅ D K ⋅ M ⋅ D F ⋅ D F + M ⋅ N ⋅ D F ⋅ D F D_K \cdot D_K \cdot M \cdot D_F \cdot D_F + M \cdot N \cdot D_F \cdot D_F DKDKMDFDF+MNDFDF

故使用深度可分离卷积的计算量和普通卷积的计算量之比如下:

D K ⋅ D K ⋅ M ⋅ D F ⋅ D F + M ⋅ N ⋅ D F ⋅ D F D K ⋅ D K ⋅ M ⋅ N ⋅ D F ⋅ D F = 1 N + 1 D K 2 \frac{D_K \cdot D_K \cdot M \cdot D_F \cdot D_F + M \cdot N \cdot D_F \cdot D_F}{D_K \cdot D_K \cdot M \cdot N \cdot D_F \cdot D_F} = \frac{1}{N} + \frac{1}{D_K^2} DKDKMNDFDFDKDKMDFDF+MNDFDF=N1+DK21


MobileNetV1 网络结构:

在这里插入图片描述

在这里插入图片描述


24.2 MobileNetV2

论文:MobileNetV2: Inverted Residuals and Linear Bottlenecks

出处:CVPR 2018 | 谷歌


贡献:

  • 提出了倒残差结构:先 1x1 升维,使用 3x3 提取特征,最后再 1x1 降维,和残差结构的先降维后升维的结构是反的
  • 提出了线性瓶颈
  • MobileNetV2 是在 V1 基础上的提升,在移动设备上不增加额外参数的情况下,效果带来了提升

深度可分离卷积:

V2 依然使用的深度可分离卷积,深度可分离卷积相比普通卷积大约能够降低 k 2 k^2 k2 的计算量,V2 的卷积核为 3x3,所以大约比普通卷积计算量少 8~9 倍,准确率仅仅跌了很少。

在这里插入图片描述


线性瓶颈:

线性瓶颈结构,就是末层卷积使用线性激活的瓶颈结构(将 ReLU 函数替换为线性函数),因为 ReLU 激活函数对低维信息会造成很大损失

在这里插入图片描述

在这里插入图片描述


模型框架:

在这里插入图片描述


24.3 MobileNetV3

论文:Searching for MobileNetV3

出处:ICCV 2019 | 谷歌


贡献:

  • 使用 NAS 的方法搜寻更适合移动 CPU 的结构
  • 提出了 MobileNetV3-Large 和 MobileNetV3-Small,并引入了 h-swish 和 SE 等模块进行效果优化

MobileNetV3 提出的目标就是为了实现移动设备上的模型的准确率和耗时的平衡。

  • MobileNetV1 引入了深度可分离卷积,来代替传统卷积

  • MobileNetV2 引入了线性瓶颈和反残差结构,来提升速度

  • MobileNetV3 为了 NAS 来搜寻更合适的网络,并且引入了 Swish 非线性方法的优化版本 h-swish 和 SE 模块,建立更高效的网络

在这里插入图片描述


NAS:这里使用 NAS 的目的是搜寻到更适合移动设备平台的 block 结构


网络优化:

1、重新设计计算复杂的层

NAS 得到搜寻的结构后发现,前面几层和后面几层计算复杂度很高,做了一些修整:

  • 精简 last stage:V2 的倒残差网络,在最后一层使用的 1x1 卷积来升维,会造成很大的延时,为了降低延时和保留高维特征,移除掉了一些层,不需要使用瓶颈层来降低计算量了,如图 5 所示,降低了 7ms 延时,约占 11% 的允许时间,几乎没有精度的损失
  • 降低卷积核数量并且使用不同的激活方式来降低冗余:还有一个很大的耗时点在于初始卷积,初始的图很大,使用卷积核数量是 32 个,所以减少了第一个卷积层的卷积核个数(32—>16),并且在该层使用 hard swish 非线性激活,能在减少卷积核的个数的同时保持准确率(和使用 32 个卷积核并在该层使用 ReLU 是的效果比),计算量反而会降低,检测速度更快

在这里插入图片描述


2、非线性激活的改进

swish 的形式如下:

在这里插入图片描述

使用 swish 的有个问题,sigmoid 函数计算量很大,所以 V3 从以下两个方面解决:

  • 使用 piece-wise linear hard analog ( R e L U 6 ( x + 3 ) 6 \frac{ReLU6(x+3)}{6} 6ReLU6(x+3))来代替 sigmoid,故 hard-swish 形式如下,对比效果如图 6:
    在这里插入图片描述

在这里插入图片描述


3、引入 SE 模块

在 V3 中使用 SE 模块,因为SE结构会消耗一定的时间,所以作者在含有 SE 的结构中,将 expansion layer 的 channel 变为原来的 1/4,这样作者发现,即提高了精度,同时还没有增加时间消耗。并且SE结构放在了depthwise 之后。实质为引入了一个 channel 级别的注意力机制。


4、不同大小的模型设计

V3 设计了两种体量的模型,Large 和 Small,都是经过 NAS 和优化后的。

在这里插入图片描述

在这里插入图片描述


25、 ShuffleNet 系列

详细介绍见 本文


25.1 ShuffleNetV1

论文:ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices

出处:CVPR 2018 | 旷世


现有的表现良好的网络结构动辄上百层,上千个通道,FLOPs(浮点计算次数)大概在十亿次,ShuffleNet 的提出是为了适应于算力较弱的移动端,以实现大概几十到几百的 MFLOPs 为目标。


现有网络的问题:

现有的高效结构如 Xception 和 ResNeXt,其实在极小的网络上的计算效率依然不太高,主要在于很耗费计算量的 1x1 卷积。

ShuffleNet 如何解决:使用 point-wise 分组卷积和 channel shuffle 两个操作,很好的降低计算量并保持准确率。这种结构能够允许网络使用更多的通道,帮助 encode 阶段提取更多的信息,这点对极小的网络非常关键。

  • 使用 point-wise 卷积来降低 1x1 卷积的计算量
  • 使用 channel shuffle 能够让不同通道的信息进行交互

这里再介绍几个基本概念:

  • 分组卷积:AlexNet 中提出的概念,在 ResNeXt 中有使用,也就是将特征图分为 N 个组,每组分别进行卷积,然后将卷积结果 concat 起来
  • 深度可分离卷积:和 MobileNet 中都有使用,也就是每个特征图使用一个卷积核来提取特征,之后使用 1x1 的卷积进行通道间的特征融合
  • channel shuffle:shuffle 可以翻译为重新洗牌,也就是把不同组的 channel 再细分一下,打乱重新分组
  • 模型加速:加速推理时候的速度,如剪枝、量化

ShuffleNetV1 是怎么做的:

在这里插入图片描述


1、Channel shuffle for group convolutions

Xception 使用了深度可分离卷积, ResNeXt 使用了分组卷积,但都没有考虑 1x1 的瓶颈层,该瓶颈层也会带来很大的计算量。

ResNeXt 中在分组卷积中使用的卷积大小为 3x3,对每个残差单元,逐点的卷积占了 93.4%。在极小的网络中,这样大的占比就难以降低网络计算量的同时来提升效果了。

为了解决上面 1x1 瓶颈层的问题,要怎么做呢:

  • 一般会考虑使用更稀疏的通道,如在 1x1 内部也使用分组卷积。但是这样也会有问题,因为 1x1 是瓶颈层,所以该层的输出是下一层 block 的输入,如果在 1x1 卷积中使用分组策略,则 1x1 瓶颈层的输出特征的每个通道并没有接收其他前面的所有输入,只接收了一小部分输入的特征(如图 1a)。
  • 所以,如何解决图 1a 的问题呢,可以使用图 1b 的方法,将每个 group 里边再细分,细分后放入不同的组内,这个过程可以叫做 channel shuffle,打乱后如图 1c 所示。

2、ShuffleNet unit

作者又针对小网络提出了 ShuffleNet unit:

从如图 2a 的 bottleneck 单元开始,在 bottleneck 特征图上,使用 3x3 深度卷积,然后使用 point-wise group convolution + channel shuffle,来构成 ShuffleNet unit,如图 2b 所示

在这里插入图片描述


3、网络结构

ShuffleNet 结构如图 1 所示,是一个由 ShuffleNet units grouped 堆叠起来的 3 stage 网络,在每个 stage 的开头,stride = 2。

  • 每个 stage 的超参数都是相同的
  • 下一个 stage 的的输出是上一个 stage 通道数的 2 倍
  • bottleneck channels 的个数是 ShuffleNet unit 的输出通道数的 1/4
  • 在 ShuffleNet unit 内,group number 数 g g g 控制着 point-wise convolution 的稀疏程度,表 1 做了实验,验证了在胸膛计算量情况下,不同的 g g g 的效果。大的 g g g 的输出通道更多,能够帮助 encode 更多的信息,但也可能由于输入特征有限,导致单个卷积滤波器的退化
  • 为了针对不同的需求设计不同大小的网络,作者还对通道数设计了缩放因子 s s s,表 1 中的结构为 ShuffleNet 1x,ShuffleNet s s sx 则表示将滤波器个数扩充 s s s 倍,同时计算量会是 ShuffleNet 1x 的 s 2 s^2 s2 倍。

在这里插入图片描述


25.2 ShuffleNetV2

论文:ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design

出处:ECCV 2018 | 旷世 清华


贡献:

  • 提出了更应该使用直接的效率度量方法(如速度、耗时等)
  • 在 V1 的 channel shuffle 的基础上,又提出了 channel split,增强特征的重用性的同时也减少了计算量
  • 提出了 4 条设计高效网络的方法:使用输入输出通道相同的卷积、了解使用分组卷积的代价(分组越多,MAC 越大)、合理的设定分组格式、降低网络并行的分支(并行越多 MAC 越大)、减少逐点运算

基础概念:

  • FLOPS:每秒浮点计算数量

  • FLOPs:浮点计算数量

  • MAC:Memory Access Cost,内存访问成本,MAC 描述了这个复杂的网络到底需要多少参数才能定义它,即存储该模型所需的存储空间


目前卷积神经网络的设计大都依据计算量,也就是 FLOPs,浮点计算次数,但 FLOPs 不是一个直接的衡量方式,是一个大概的预估,而且也可能和我们更关系的直接衡量方法(如速度和时间)得到的结果不等,且实际模型的的速度等还依赖于内存消耗、硬件平台等,所以 ShuffleNetV2 会在不同的硬件平台上更直接的来评估,而非只依靠 FLOPs。

在这里插入图片描述

如图 1 所示,MobileNet v2 是 NASNET-A 快很多,但 FLOPs 却基本没差别,也证明了有相同 FLOPs 的模型可能速度有很大的不同,所以,只使用 FLOPs 作为衡量指标不是最优的。


FLOPs 和 speed 之间的不对等可能有以下两个原因:

  • 第一个原因:很多对速度有影响的因子没有被考虑到 FLOPs 中去,如内存访问成本 (MAC)。在某些操作 (如组卷积) 中,这种代价构成了运行时的很大一部分。它可能会成为具有强大计算能力的设备的瓶颈,例如 gpu。在设计网络体系结构时,不应该简单地忽略这个代价。另一个是并行度。在相同的 FLOPs 下,具有高并行度的模型可能比另一个具有低并行度的模型快得多。
  • 第二个原因:FLOPs 相同的一些操作的运行速度可能不同。如 tensor 分解,能够加速矩阵乘法,但也有研究证明分解后可能在 GPU 上运行更慢,虽然 FLOPs 降低了 75%。这是由于新版的 CUDNN 针对 3x3 卷积进行了优化,所以不一定 3x3 的卷积就比 1x1 的卷积慢。

如下图 2 所示,FLOPs 主要衡量卷积部分,虽然这一部分可能很耗时,但其他的如 data shuffle、element-wise operation(AddTensor、ReLU)等等也同样很耗费时间,所以 FLOPs 不应该作为唯一的衡量指标。

在这里插入图片描述

基于上面的分析,作者认为一个方法高效与否应该从下面两个方面来衡量:

  • 使用直接方法来度量效果而非间接方法
  • 所以的度量要在对应的硬件设备上进行

ShuffleNetV2 首先提出了 4 条设计高效网络的方法:

  • G1:Equal channel width minimizes memory access cost (MAC):当卷积层的输入特征矩阵与输出特征矩阵 channel 相等时 MAC 最小 (保持FLOPs不变时)
  • G2: Excessive group convolution increases MAC:当 GConv 的 groups 增大时(保持FLOPs不变时),MAC 也会增大,所以建议针对不同的硬件和需求,更好的设计对应的分组数,而非盲目的增加
  • G3: Network fragmentation reduces degree of parallelism:网络设计的碎片化程度(或者说并行的分支数量)越高,速度越慢(Appendix Fig 1)
  • G4:Element-wise operations are non-negligible:Element-wise操作,即逐点运算,带来的影响是不可忽视的,轻量级模型中,元素操作占用了相当多的时间,特别是在GPU上。这里的元素操作符包括 ReLU、AddTensor、AddBias 等。将 depthwise convolution 作为一个 element-wise operator,因为它的 MAC/FLOPs 比率也很高

1、G1:输入输出通道相同的时候,MAC 最小,模型最快

很多网络都使用了深度可分离卷积,但其中的逐点卷积(1x1 卷积)计算量很大,1x1 卷积的计算量和其输入通道数 c 1 c_1 c1 和输出通道数 c 2 c_2 c2 有很大的关系,1x1 卷积的 FLOPs = h w c 1 c 2 hwc_1c_2 hwc1c2

假设内存很大,则内存消耗 MAC = h w ( c 1 + c 2 ) + c 1 c 2 hw(c_1+c_2)+c_1c_2 hw(c1+c2)+c1c2,和输入输出通道数相关性非常大,也有 M A C > = 2 ( h w B ) + B h w MAC >= 2 \sqrt(hwB) + \frac{B}{hw} MAC>=2( hwB)+hwB, MAC 的下线是由 FLOPs 决定的,当 1x1 卷积的输入输出通道数量相同的时候,MAC 最小。

如表 1,当固定 FLOPs 时,输入输出通道相同的时候,MAC 最小,模型最快。

在这里插入图片描述


2、G2:当分组卷积的分组数增大时(保持FLOPs不变时),MAC 也会增大,所以建议针对不同的硬件和需求,更好的设计对应的分组数,而非盲目的增加

1x1 分组卷积的 MAC 和 FLOPs 如下:

在这里插入图片描述

  • g g g 是分组数量, B = h w c 1 c 2 / g B = hwc_1c_2/g B=hwc1c2/g 是 FLOPs
  • 给定固定的输入尺度和 FLOPs,MAC 会随着分组数量的增大而增大
  • 所以建议针对不同的硬件和需求,更好的设计对应的分组数,而非盲目的增加

在这里插入图片描述


3、G3:网络设计的碎片化程度越高(或者说并行的分支数量越多),速度越慢(Appendix Fig 1)

在这里插入图片描述

如表 3 所示,4 分支并行的网络约比单分支的网络慢 3x

在这里插入图片描述


4、G4:不要过多的使用逐点运算

如图 2,点乘操作会耗费很长时间,点乘会出现在 ReLU、AddTensor、AddBias 等操作中,虽然 FLOPs 很低,但 MAC 很高。深度可分离卷积也有点乘操作,所以也有高的 MAC/FLOPs ratio。

比如使用 ResNet 中的 bottleneck (1x1 + 3x3 + 1x1,ReLU,shortcut)做实验,将 ReLU 和 shortcut 去掉后,提升了 20% 的速度。

所以基于上述准则,设计高效网络要遵循如下准则:

  • 使用输入输出通道相同的卷积
  • 了解使用分组卷积的代价,合理的设定分组格式
  • 降低网络并行的分支
  • 减少逐点运算

ShuffleNet V2 的结构:

介绍 V2 的结构之前,先看看 V1 的设计问题:

  • pointwise 分组卷积和 bottleneck 结构会提升 MAC(G1 和 G2),其计算消耗是不可忽略的,尤其是小模型。

  • 使用大的分组数会不符合 G3

  • 残差连接中的逐点相加操作也会带来大量计算,不符合 G4

所以,如果想要同时实现高容量和计算效率,关键问题是如何使用大量且等宽的 channel,而不是很多的分组


ShuffleNet V2 中提出了 Channel Split:

在 block 刚开始的时候,就将 channel 一分为二,如图 3c 为基本结构,下采样时候的结构如图 3d

在这里插入图片描述

  • 在每个 unit 的起始,将输入的 c c c 维通道分为两份,也就是两个分支
  • 为了遵守 G3,一个分支保留恒等映射
  • 为了遵守 G1,另外一个分支使用 3 层卷积,且输入输出相同
  • 为了遵守 G2,两个 1x1 卷积不使用 group-wise,因为分成两个分支,原理上已经进行了分组
  • 得到两个分支的输出后,concat 起来,然后 channel 数量就和输入相同了(遵守了 G1),然后使用 channel shuffle 来让两个分支的信息进行交互
  • channel shuffle 之后,就开始了下一个 unit
  • 要注意的是,这里没有使用 V1 中的相加操作,ReLU 和深度可分离卷积也只存在于一个分组中
  • 为了遵循 G4,将 concat、channel shuffle、channel split 这三个操作进行了 merge,合并成了一个 element-wise 操作
  • 下采样时,unit 会进行修改,如图 3d,移除了 channel split,输出的 channel 数量会翻倍
  • 整个 V2 的网络结构是重复的堆叠起来的,为了简化, c ′ = c / 2 c'=c/2 c=c/2,整个网络结构和 V1 也很类似,只有一个不同点,就是在 global average pooling 之前加了一个 1x1 卷积,用于特征混合。

ShuffleNetV2 不仅仅高效,而且准确性也有保证,主要有两个原因:

  • 每个 block 都是高效的,这就允许网络使用更大的 channel 数量
  • 每个 block 中,只使用约一半的 channel 经过本个 block 的层进行特征提取,另外一半的 channel 直接输入下一个 block,可以看做特征重用

26、 VoVNet

详细介绍见 本文

论文:An Energy and GPU-Computation Efficient Backbone Network for Real-Time Object Detection

出处:CVPR 2019 Workshop


贡献:

  • 讨论了 MAC 和 GPU 计算的效率,并研究了如何设计更高效的结构
  • 抛出了 DenseNet 网络结构中的问题,包括低效的、冗余的操作等,VoVNet 主要是对 DenseNet 的密集连接方式的改进
  • 提出了 One-shot Aggregation(OSA),将中间的特征一次性聚合(在最后一层聚合一次),如图 1b 所示,能够在保留 concat 优势的同时优化 MAC(中间层输入输出通道相同) 和 GPU 计算效率(无需 1x1 卷积)
  • 基于 OSA 模块,构建了 VoVNet,一个 backbone 网络结构,并且将该 backbone 用于 DSOD、RefineDet、Mask R-CNN 等方法中,取得了比 DenseNet、ResNet 等方法更好的效率和准确率的平衡

VoVNet 的目标是什么:

将 DenseNet 优化成一个更高效的网络,同时保留其在目标检测任务上的良好效果

在这里插入图片描述


VoVNet 和 DenseNet 的最主要的区别:

  • DenseBlock 中的每一层的输入都是前面所有层 feature map 的叠加
  • VoVNet 只有最后一层的输入是前面所有层 feature map 的叠加。

ResNet 和 DenseNet 的不同在于特征聚合的方式:

  • ResNet 是将特征相加来聚合的
  • DenseNet 是将特征 concat 来聚合的

这两种聚合方式有一些不同:

  • 当特征和浅层特征图相加的时候,会被弱化
  • 而使用 concat 的话,特征会得到较好的保留
  • 而检测网络需要利用目标的多分辨率特征,所以使用 concat 能更好的保留和利用这些特征

DenseNet 的参数量和 FLOPs 也更低一些,原因在于,除了 FLOPs 之外,还有很多影响模型运行时间的因素:

  • 第一个就是 MAC,内存访问成本,也是存储特征图需要的空间,如图 1a 所示,DenseNet 的前面几层都使用密集连接,连接到后面的层,导致 MAC 随着网络深度的增大以平方的形式增大,导致更多的资源消耗
  • 第二个就是 GPU 并行计算倍限制了,DenseNet 会被瓶颈层的计算限制,一般来说 GPU 的并行计算很有效,但由于输入通道的增大,DenseNet 需要使用 1x1 bottleneck 来降低输入维度和 FLOPs,导致 GPU 运算效率很低

高效网络设计的重要因素有如下两点:

  • MAC:Memory Access Cost,内存访问成本,MAC 描述了这个复杂的网络到底需要多少参数才能定义它,即存储该模型所需的存储空间,每个卷积层的 MAC 可以计算如下:
    在这里插入图片描述

  • GPU 计算效率:

    之所以一般要通过降低 FLOPs 的方法来加速的原因是,一般认为每个浮点运算的过程在相同设备上都是相同的。

    但在 GPU 上却不是这样,因为 GPU 有并行加速策略,所以 GPU 呢给个同时处理多个浮点运算,这也是高效的一个很大的原因。

    GPU 并行计算能力在计算大型 tensor 的时候很能体现出来,当把大的卷积核 split 后,GPU 并行的计算效率会变低,因为并行的部分变少了。

    基于此,建立一个 layer 数量较少的网络可能会更好点


所以结论如下:

  • 虽然深度可分离卷积和 1x1 瓶颈层能力降低 FLOPs,但会损害 GPU 的计算效率
  • 不同网络结构的 GPU 计算效率是不同的

所以本文提出了一个新的概念:FLOPs per Second:FLOP/s,来衡量对 GPU 能力的利用情况,该值越大,则 GPU 的利用越高效


DenseNet 的 Dense Connection 的问题:

中间层的密集连接会必不可少的导致效率低下,因为随着层数的增加,输入 channel 数量也会线性增加。会有以下的问题:

  • 密集连接会导致 MAC 的增大,当保持计算量不变时,输入输出通道数相同的时候,MAC 最小。而密集连接增加的输入的通道数,输出的通道数是没变的,所以在相同计算量的情况下, DenseNet 的 MAC 很高
  • 密集连接就会需要使用 1x1 瓶颈层,瓶颈层不能很好的利用 GPU 的并行计算能力,使得 GPU 计算效率低。线性增长的输入尺寸是一个很大的问题,随着深度的增加,计算量是平方增长的。DenseNet 使用 1x1 卷积来保证输入 3x3 卷积的输入是不变的。但是,虽然 1x1 卷积能够降级 FLOPs,但会影响 GPU 的并行计算效率。瓶颈层将一个 3x3 卷积层拆分成两个更小的层,就会导致更多的串行计算(1x1+3x3 卷积),会拉低推理速度

在这里插入图片描述

只使用能相互互补(或相关性较小)的中间层特征,而非使用所有的中间层特征来生成最后的特征,会避免很多冗余


故此,作者认为,使用所有的中间层来进行密集连接其实带来的收益不多,所以,作者提出了一种新的密集链接方式:只使用每个 block 的最后一层进行特征聚合


One-shot Aggregation modules:

OSA 模块就是只聚合每个 block 的最后一层特征,也就是在每个 block 的最后一层,对该 block 的前面所有层的特征进行 concat,只进行着一次的聚合。

该模块将中间层的特征聚合到最后一层。如图 1 所示。每个卷积层包含双向连接,一个连接到下一层以产生具有更大感受野的特征,而另一个仅聚合到最终输出特征映射。

在这里插入图片描述

OSA 能够提升 GPU 是计算效率,OSA 中间层的输入输出通道数相同,也不大需要使用 1x1 瓶颈层来降维,所以,OSA 层数更少、更高效


OSA 与 DenseNet 的不同之处总结如下:

  • 每一层的输出并没有按路线(route)到所有后续的中间层,这使得中间层的输入大小是恒定的。这样就提高了 GPU 的计算效率。
  • 另外一个不同之处在于没有了密集连接,因此 MAC 比 DenseNet 小得多
  • 此外,由于 OSA 模块聚集了浅层特征,它包含的层更少。因此,OSA 模块被设计成只有几层,可以在 GPU 中高效计算。

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

卷积神经网络超详细介绍 的相关文章

随机推荐

  • 《Apache MINA 2.0 用户指南》第十五章: 代理

    有待官方完善中
  • SpringBoot 中操作 Redis 及工具类的封装

    在我们项目开发中总是免不了会使用缓存 Redis现在基本是我们公司中非常常见的缓存方案 包括在用户token的缓存 热点信息的缓存等 这篇文章主要讲讲在SpringBoot项目中如何去操作Redis 及最后工具类的封装 一 引入依赖及进行配
  • 【问题解决】docker login报错 org.freedesktop.Secret.Error.IsLocked: Cannot create an item in a locked collec

    问题场景 环境 docker 24 0 2 社区版 Ubuntu Server 18 04LTS 刚刚执行 docker login 登录仓库报错 hellxz bigdata dockerTest docker login harbor
  • 成功GET一款高大上又不显俗的Linux时间锁屏软件-GLUQLO

    闲来无事 总觉得目前的Ubuntu桌面锁屏看烦了 依然记得之前手机端曾经流行过一款锁屏软件 想想这个应该会有Linux版了 度娘果然查到了 名字就叫GLUQLO 而且也有Linux版还是开源的 那就开始动起来 一 安装环境 机器环境 Lin
  • 程序员到了35岁就会失业吗?三位程序员UP主这样说……

    Q 你自己也是 up 然后会接触很多程序员群体 你觉得你在跟这些程序员沟通下来 他们会有一些关于年龄方面的焦虑嘛 A 很多人都有 而且很多人都是 还没入行就开始焦虑了 就开始问我 水哥水哥 咱这程序员是不是真的到了 35 岁 就 就完蛋了
  • 【Rust】003-基础语法:流程控制

    Rust 003 基础语法 流程控制 文章目录 Rust 003 基础语法 流程控制 一 概述 二 if 表达式 1 语法格式 2 多个 3 获取表达式的值 三 循环 1 loop 无限循环 可跳出 无限循环 跳出循环 返回值 2 whil
  • EL-FROM动态添加item并设置必填

  • 短视频批量剪辑--矩阵源码---无人直播如何搭建技术开发

    一 核心技术 1 AI自动直播 智能系统通过丰富可定制的文案库 拥有有料有趣的灵魂 不仅能自动语音讲解内容 还可以在直播中和用户灵活互动 直播中可将团购商品同话术自动上下架 2 AI剪辑 可一键智能批量成片 也可跟着模板剪同款视频 更可针对
  • 全速下载微云方法

    下载tim 测试版 版本TIM 2 5 8 apk https www lanzous com iaroy3i 登陆QQ小号 转储文件至微云 QQ小号登陆tim 文件 微云文件 找到文件 点进去 点右上角转发到qq大号上 全速下载
  • OpenGL编程指南-freeglut安装(Windows平台)

    OpenGL编程指南 freeglut安装 Windows平台 1 前言 学习OpenGL编程首先需要可以跟着书中的示例代码进行学习 书中使用GLUT作为示例代码的演示 GLUT于1998年作者不在维护并不开源 freeglut是一个完美的
  • Regex-后向引用

    使用小括号指定一个子表达式后 匹配这个子表达式的文本 也就是此分组捕获的内容 可以在表达式或其它程序中作进一步的处理 默认情况下 每个分组会自动拥有一个组号 规则是 从左向右 以分组的左括号为标志 第一个出现的分组的组号为1 第二个为2 以
  • 在同一个canvas中绘制多个不同形状,颜色的图形

    今日踩坑 在同一个canvas中绘制多个不同形状 颜色的图形时 后面的总是将前面的颜色覆盖 解决方法 beginPath 和 closePath 这两个函数可以起到类似 div 的作用 用它来把每个图形包围 就可以绘制不同颜色的图形了 例如
  • 已上架的App在AppStore上无法搜索到的问题

    前言 如果还没有苹果开发者账号 自行注册苹果开发者中心 opens new window 并缴费成为开发者 证书配置 证书教程 opens new window Win系统请使用 appuploader opens new window 进
  • Android Studio更新3.1版本之后编译出现Program type already present: android.support.design.widget.CoordinatorLa

    前言 今天上午打包项目的时候出现了编译异常 怎么会出现这个问题 昨天编译都OK 然后想了下之后原来今天上午刚更新了新版本studio3 12 这有点尴尬了 感觉每次studio更新版本 都会遇到坑 要么gradle出现问题 要么编译异常提示
  • linux中$?,$#等代表什么

    0 这个程式的执行名字 n 这个程式的第n个参数值 n 1 9 这个程式的所有参数 此选项参数可超过9个 这个程式的参数个数 这个程式的PID 脚本运行的当前进程ID号 执行上一个背景指令的PID 后台运行的最后一个进程的进程ID号 执行上
  • C++primer plus 第十一章编程练习

    银行账户类 头文件 ifndef HEAD H define HEAD H include
  • muduo的高性能异步日志

    1 一个日志库大体可分为前端 frontend 与后端 backend 前端是供应用程序使用的接口 API 并生成日志信息 后端则是负责将日志信息写到目的地 每个线程都有自己的前端 而整个程序共用一个后端 对于生产者 前端 而言 要尽量做到
  • sql-labs 41-65关

    Less 41 这关还是堆叠注入 而且还是数字型闭合 可以照搬39关代码 但是与39不同的是 这关没有报错的显示位 查数据 id 1 id 0 union select 1 select group concat username from
  • 计数排序--时间复杂度为线性的排序算法

    我们知道基于比较的排序算法的最好的情况的时间复杂度是O nlgn 然而存在一种神奇的排序算法 不是基于比较的 而是空间换时间 使得时间复杂度能够达到线性O n k 这种算法就是本文将要介绍的计数排序 一 适用情况 这个算法在n个输入元素中每
  • 卷积神经网络超详细介绍

    文章目录 1 卷积神经网络的概念 2 发展过程 3 如何利用CNN实现图像识别的任务 4 CNN的特征 5 CNN的求解 6 卷积神经网络注意事项 7 CNN发展综合介绍 8 LeNet 5结构分析 9 AlexNet 10 ZFNet 1