微信公众号开发

人脸识别智能小程序 | 卷积神经网络基础 | 02

本文主要是介绍人脸识别智能小程序 | 卷积神经网络基础 | 02,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录
  • 什么是卷积神经网络
  • 卷积神经网络的重要组成单元
  • 卷积中的重要参数
  • 卷积的定义和使用
  • 池化的基本概念
  • 激活函数的基本概念
  • BatchNorm层/批量归一化层
  • 全连接层
  • Dropout层/丢弃法
  • 损失层
  • 常见的卷积神经网络结构
    • LeNet
    • AlexNet
    • ZFNet
    • VGG
    • Inception
    • ResNet
  • 从卷积的角度思考,如何减小网络中的计算量
  • 卷积神经网络结构对比
  • 卷积神经网络中的Attention机制
  • 模型压缩
  • 模型剪枝
  • 小结

什么是卷积神经网络

卷积神经网络:以卷积结构为主(除了conv,还有pooling,dropout等层次结构),搭建起来的深度网络。

  • 将图片作为输入:卷积输入数据的维度\((n,h,w,c)\),分别表示batch_size,高度,宽度,色彩通道。
  • 自动提取特征:参数优化
  • 图片的变形具有高度不变性:对于图像的形变是不敏感的,是鲁棒的

特征提取通常是在输出结果前的一层,FC层,经过这个FC层,卷积特征就会变成一个向量,这个向量具体多少维,取决于FC的参数。

卷积神经网络的重要组成单元

这里需要重点介绍的有:

  • 卷积层
  • 池化层
  • 激活层
  • BN层
  • LOSS层
  • 全连接层

卷积:对图像和滤波矩阵(卷积核)做互相关运算(对应元素相乘再求和)的操作。

卷积操作简单来说就是图像和滤波矩阵进行先乘后加的操作。

  • 滤波器
  • 每一种卷积对应一种特征
  • Im2col实现卷积运算:实现卷积运算不是两重循环,而是先把图片转换成向量,然后进行向量的运算。

右下图是一个卷积的具体例子,卷积核和对应图片的一个区域,每个元素与对应元素进行相乘,最后在逐个相加,得到结果(一个数)!

卷积中的重要参数

卷积核

  • 最常用为2D卷积核\((k_w*k_h)\)
  • 权重和偏置项
  • 常用卷积核:1*1,3*3,5*5,7*7 (一般不会超过7*7)

为什么卷积核都是奇数的大小?因为有“中间点”,feature map存在“中间点”与原来的图像进行一一对应,可以保留图像的空间信息。

一般而言,卷积操作后feature map的尺寸会变小,padding可以使得feature map的尺寸与原图像一致。

卷积——权值共享局部连接(局部感受野/局部感知)

  • 卷积运算作用在局部(这里的filter size应该被认为是卷积后的feature size的大小)
  • Feature map使用同一个卷积核运算后得到一种特征(权值共享)
  • 多种特征采用多个卷积核(channel)

从层和层之间的连接关系来看,输入层和输出层是局部连接的。也就是当前的一个局部区域,对应到输出的feature map的一个点。

全连接就是feature map上的点和输入层的每一个点都存在连接关系。

上面的示例图说的就是权值共享&局部连接。

  • 局部连接:

    对于一个1000 × 1000的输入图像而言,如果下一个隐藏层的神经元数目为10^6个,采用全连接则有1000 × 1000 × 10^6 = 10^12个权值参数,如此数目巨大的参数几乎难以训练;而采用局部连接,隐藏层的每个神经元仅与图像中10 × 10的局部图像相连接,那么此时的权值参数数量为10 × 10 × 10^6 = 10^8,将直接减少4个数量级。

  • 权值共享:

    尽管减少了几个数量级,但参数数量依然较多。能不能再进一步减少呢?能!方法就是权值共享。具体做法是,在局部连接中隐藏层的每一个神经元连接的是一个10 × 10的局部图像,因此有10 × 10个权值参数,将这10 × 10个权值参数共享给剩下的神经元,也就是说隐藏层中10^6个神经元的权值参数相同,那么此时不管隐藏层神经元的数目是多少,需要训练的参数就是这 10 × 10个权值参数(也就是卷积核(也称滤波器)的大小),如下图。

这大概就是CNN的一个神奇之处,尽管只有这么少的参数,依旧有出色的性能。但是,这样仅提取了图像的一种特征,如果要多提取出一些特征,可以增加多个卷积核,不同的卷积核能够得到图像的不同映射下的特征,称之为Feature Map。如果有100个卷积核,最终的权值参数也仅为100 × 100 = 10^4个而已。另外,偏置参数也是共享的,同一种滤波器共享一个。

卷积核的大小就对应感受野的区域大小,比如\(3*3\)d的卷积核,其感受野的大小就是\(5*5\)。

卷积核越大,意味着感受野越大,感受野越大,意味着感知到这个图像的区域信息就会越多。但是如果用大卷积核,不见得学到的结果就好。例如上图,以2D举例,\(3*3\)卷积核的参数个数为9,\(5*5\)卷积核的参数个数为25,\(7*7\)卷积核的参数个数为49,参数过多容易导致过拟合。

小卷积核是减少了计算量,但是如何实现大卷积核的效果呢?答案是叠加卷积。

例如右上图,\(3*3\)大小的卷积核卷积一次得到的feature map的大小为\(3*3\),在用\(3*3\)的卷积核再卷积一次,那么其大小就会变成\(1*1\),其效果等价于直接使用\(5*5\)的卷积核进行一次卷积。

使用小卷积核替代大卷积核的好处:参数量和计算量明显降低!

通过多个小卷积核来替代一个大卷积核,不仅可以保证感受野的大小不变,而却网络的深度会加深,那么就可以在卷积层和卷积层的其中加入一些非线性层,使得网络的非线性能力更加的强,意味着网络描述一个事物的能力会变强。

评估卷积的参数量是必须掌握的。

参数越多,那么对机器的性能就越高,在保证性能的前提下,当然是希望参数越小越好!参数越多,意味着我们的模型越复杂。

步长(Stride)

  • 下采样的过程
  • 输出Feature Map的大小变化:\((N-F)/stride+1\)

stride一般都是设置为1或2。

Pad

  • 确保Feature Map整数倍变化,对尺度相关的任务尤为重要

比如\(8*8\)大小的矩阵,卷积核的大小为\(3*3\),那么经过pooling得到的Feature Map的大小为\(6*6\),\(8*8\)和\(6*6\)相差不是整数倍!

具体要pad多少呢?和卷积核的大小相关

  • F=3 =》zero pad with 1
  • F=5 =》zero pad with 2
  • F=7 =》zero pad with 3

卷积的定义和使用

在tensorflow中定义卷积的话,实际上有很多方法,使用tf.nn原生方法来定义的话,需要自己先定义权值项filter_weight和偏置项biases,

slim是对tensorflow更加高层的一个封装,也可以方便的定义卷积。

池化的基本概念

池化:对输入的特征图进行压缩

  • 使特征图变小,简化网络计算复杂度(stride就是有下采样的作用)
  • 进行特征压缩,提取主要特征
  • 增大感受野

池化是对Feature Map进行压缩,得到更小的Feature Map!

压缩Feature Map,一方面是可以减少计算量,还有这也是一个特征提取的过程,另外,对Feature Map压缩可以增大感受野。

注意: 池化层是没有参数的,所以进行BP的时候是无关池化层的事情!

激活函数的基本概念

激活函数:增加网络的非线性,进而提升网络的表达能力

如何理解线性和非线性?

从分类器的角度来理解:

  • 线性分类器就是用一个“超平面”将正、负样本隔离开,如:
    (1)二维平面上的正、负样本用一条直线来进行分类;
    (2)三维立体空间内的正、负样本用一个平面来进行分类;
    (3)N维空间内的正负样本用一个超平面来进行分类。
  • 非线性分类器就是用一个“超曲面”或者多个超平(曲)面的组合将正、负样本隔离开(即,不属于线性的分类器),如:
    (1)二维平面上的正、负样本用一条曲线或折线来进行分类;
    (2)三维立体空间内的正、负样本用一个曲面或者折面来进行分类;
    (3)N维空间内的正负样本用一个超曲面来进行分类。

从函数定义角度来说:

  • 线性:1、变量之间的变化率为恒量,函数关系是直线;2、满足叠加原理,即f(ax + by) = af(x) + bf(y)。
  • 非线性:所有不满足线性条件的关系就是非线性。
  • 可以写成多元一次方程组形式的,就是线性。二次以上就是非线性。

sigmoid函数将输入的值归一化到0到1中去 \(x => [0,1]\),\([0,1]\)之间有什么特点呢?可以表达概率。因此如果是分类任务,可以使用sigmod函数将结果映射到\([0,1]\)当中,这样就拿到一个关于结果预测的概率分布。

sigmoid函数很少在网络的中间层,主要原因就是sigmoid容易出现梯度弥散/梯度饱和这样的问题,BP由链式法则进行乘法叠加,那么就会有梯度弥散(就是梯度很小,收敛很慢)。

指数运算是一个非常耗时的运算!

sigmoid更多是作为最后的输出层。

sigmoid和tanh在RNN中应用会更多,在CNN中应用是较少的!

tanh和sigmoid的问题是类似的,一个就是梯度弥散的问题,一个就是指数运算的问题。

tanh和sigmoid的区别在于输出是否以零为中心。

一般在设计CNN的时候都是不会用到tanh和sigmoid的,sigmoid还CNN还会有用到,tanh基本是不会在CNN中出现的

RuLU激活函数是现在CNN的标配激活函数!

BatchNorm层/批量归一化层

\(\beta,\gamma\)这两个是在BN层可以被进行学习的参数。

BatchNorm层:通过一定的规范化手段,把每层神经网络任意神经元这个输入值的分布强行拉回到均值为0,方差为1的标准正态分布。

为什么需要引入BatchNorm层对数据进行规范化处理呢?

对于原始的输入数据,如果我们不加规范化的话,输入数据的分布是不可控的,每个层的数据分布都是有差异的。而且这个差异,在训练的过程中,由于经过多轮的BP算法,每一轮的BP算法都会改变相应层的参数,这一层参数的改变,也意味着这一层的输入输出也会发生变化,输入输出发生变化,数据的部分又不可控,这个时候带来的一个现象就是训练过程中,每一层的分布是不停在变化的,这对于网络的收敛是非常不利的,也正是因为这样的一个原因,才会对输入的数据进行约束。

BatchNorm层使用在激活函数之前,BatchNorm层本质上是一种线性变换,激活函数是非线性变换。

引入BatchNorm层,对数据进行规范化的约束,会带来很多优点。

  • 可以取消Dropout层和L2正则项
  • BN层可以加速模型收敛,因此学习率可以稍微增大
  • BN可以理解为在每个小批量里加入了噪音,以此来控制模型的复杂度

上面是TensorFlow中三种使用BN的方式。

全连接层

全连接层:连接所有的特征,及那个输出值送给分类器(比如softmax分类器)

  • 将网络的输出变成一个向量: 卷积层输出的结果,一定是一个四维的特征图\((n,h,w,c)\),需要将这个四维矩阵转化为一维向量进行全连接
  • 可以采用卷积代替全连接层
  • 全连接层是尺度敏感的:全连接层的参数是固定的,如果输入的个数改变,那么运算的式子也会跟着改变。
  • 配合使用dropout层: 因为全连接层的参数量非常大,所以使用dropout层随机丢弃一些节点

全连接层就是一个线性运算。

通常而言,一个卷积网的参数量,大部分都是占据在全连接层的,比如VGG,80%的参数都是来自最后的FC层。

Dropout层/丢弃法

使用全连接层由于参数量非常大,所以会使用dropout层,来对节点进行杀死。

dropout:在训练过程中,随机的丢弃一部分输入,此时丢弃部分对应的参数不会更新(置零)。

防止模型过拟合有两种处理方式:

  • 一种是让模型变得比较小(就是减少参数) =》 丢弃法
  • 一种是让每个参数选择值的范围比较小 =》 权重衰退

下面是范数知识的补充

关于权重衰退知识的补充

损失层

损失函数:用来评估模型的预测值与真实值的不一致程度。

  • 经验风险最小:得到的结果最优
  • 结构风险最小:防止模型过于复杂(过拟合)

交叉熵损失、softmax这些都是经验风险最小的损失函数,需要在损失函数中加入一个惩罚项。

常见的结构风险最小的函数有L0,L1,L2。

损失层一般都是定义了经验风险最小, 那么结构风险最小需要另外加约束,比如对卷积的核函数参数\((w,b)\),那么可以对其添加L2正则化。

交叉熵损失实际上是源于逻辑回归中的似然损失。

什么是似然?我们在学习概率统计的时候经常会去区分两个概念,就是概率和似然。

  • 概率通常是一个统计上的概念,某一个事件出现的频次
  • 似然是在已知结果的情况下,反推产生这些结果的原因(在深度学习中这些原因就是我们要进行学习的参数)

非负性:对于损失,都是大于等于0的,因为只有大于等于0,这样才能找到一个最小值。

上面的公式是以二分类作为例子给出的。

L1在0点不可导,L2在0点可导,但是L2越靠近0,那么梯度的值就越来越小。

Smooth L1是综合考虑了L1和L2的特点。在\((-1,1)\)中靠近0点使用L2,其他使用L1加速收敛。

常见的卷积神经网络结构

模型是要设计的越复杂还是更加的轻量?

工业界希望是在保证准确率的情况下,模型设计的越轻量越好。

学术界则希望模型能够设计的更加的复杂,这样来保证模型的正确率。

LeNet

LeNet应用于一个十分类问题(手写数字识别 mnist)。

从LeNet可以看到分类任务的大概思路。

图片输入,经过(conv,pooling),在经过全连接层(FC n分类就n维),最后经过softmax,得到一个\([0,1]\)的概率值。

AlexNet

2012年显卡的显存还是有限的,网络模型图中给出的两个分支,表示使用两张显卡进行分布式训练。

  • conv-relu-pooling-LRN

网络图所示,图片经过多轮卷积,\(11*11,5*5,3*3,3*3,3*3\),AlexNet在设计的时候,每一个卷积之后,都会配有relu,pooling,LRN三个层。

relu 增加非线性能力

pooling 下采样,增大图像感受野,对图像进一步提取

LRN 归一化,将数据约束在一定

  • fc-rule-dropout

在经过两个fc层,后面跟着rule和dropout,因为fc层的参数量非常大,所以这里要使用dropout层进行一些参数的删除(置零)。

  • fc-softmax

最终将特征映射到一个1000维的向量上。

最终训练出来的参数在60M以上,整个模型大小在200M以上。

  • ReLU激活函数

ReLU激活函数相对于其他的激活函数,能实现一个更快的计算速度,并且在x大于0时,不会出现梯度消失这样的问题。

ReLU也成了后面我们设计卷积神经网络的一个标配。

  • Dropout层

FC+Dropout层是标配,dropout可以减少过拟合的风险,因为FC中存在过多的参数,通过dropout能够对FC的参数进行约束。

  • LRN层

后面研究发现LRN层其实没有多大作用,现在基本已经被弃用了,现在使用的最多的是BN层。

ZFNet

ZFNet对于AlexNet并没有多大的改进,只是对AlexNet进行了一些细致的调整。ZFNet的最大贡献是对卷积网络为什么有效进行了分析。

ZFNet中提出的几点结论,是非常有普适性的。

ZFNet将特征进行可视化展示,具体是如何实现呢?上图的右边是正常卷积网的一个数据流向,对于我们最终下采样拿到的一个图片,我们该如何还原成最初的图片呢?实际上如果想进行百分百的还原,这是不可能的,因为经过激活层和pooling层的时候,会对图像造成不可逆的破坏,因此这个还原只是对特征高层次的语义分析,具体是通过上采样和反卷积操作来完成的,最终得到与原始图像大小一致的特征图。

通过观察这些还原出来的特征图,作者总结出下面的结论。

  • 特征分层次体系结构

对于CNN,特征的层次结构是非常明显的,通过浅层的卷积网络,可以得到纹理、颜色这些低层次的特征,再经过卷积,可以得到更加精细的纹理结构,这些特征图再经过多次深层的卷积,这时候在反卷积可视化,实际上很难在视觉上描述是什么特征,这称为高层次的语义特征。

下图是训练时的特征演变。

越浅层的网络提取出来的特征就越低,

  • 深层特征更鲁棒

这个鲁棒体现在哪里呢?如果输入的图像发生了轻微的扰动,那么浅层的特征会发生明显的变化,但是对于深层的特征,产生的变化会越来越小。

也就说,深层次的特征对输入的图像变得越来越不敏感,越来越鲁棒。

  • 深层特征更有区分度

利用这些深层特征,可以更好的完成图像的分类。

  • 深层特征收敛更慢

网络加深之后很难收敛,也就是越来越难训练,但是加深网络确实效果会更好。

ResNet解决了网络加深后收敛变慢的这个问题。

VGG

VGG

  • 为了研究网络深度对模型准确度的影响,并采用小卷积堆叠的方式,来搭建整个网络结构

都是采用了\(3*3\)的小卷积。

  • 参数量:138M;模型大小>500M

VGG的网络更大,对比参数量的大小和模型大小就可以知道。

上面的VGG示例图只列出了卷积的结构,实际上在卷积当中还会插入激活层和池化层。

上面列出了11层、13层、16层、19层(卷积层、FC层是需要进行参数训练的,池化层不需要训练)。

这里输入图像的大小是\(224*224\),这个尺寸是对应ImageNet挑战赛图像分类任务的图像尺寸,这也是为什么我们在设计分类识别任务的时候采用\(224*224\)来设计和训练网络。我们想要使用ImageNet挑战赛上表现优秀的模型来进行模型迁移,那么就需要保证和训练的模型数据的一致性,所以在设计网络的时候会尽量保证尺寸为\(224*224\)。

  • 更深的网络结构,结构更加规整、简答

  • 全部使用\(3*3\)的小型卷积核核\(2*2\)的最大池化层

不难发现一点,VGG的网络非常深,相比AlexNet,它的卷积是非常多的,另外可以发现这里的卷积核都是\(3*3\)的卷积核,没有大于\(3*3\)的卷积核。

小卷积核可以实现大卷积核的感受野范围,同时计算量会更小。

  • 每次池化后Feature Map宽高降低一半,通道数量增加一倍

每次经过一个pooling层,channel的数量会乘2,保证提取的数量。

  • 网络层数更多,结构更深,模型参数更大

  • 证明了更深的网络,能够提取更好的特征

  • 成为后续很多网络的backbone

利用VGG来进行特征的提取,虽然VGG只在ImageNet挑战赛获得第二名,但是使用VGG提取出来的图像特征往往更有效。

这也是为什么VGG也成为后续很多网络的主干网络。

  • 规范化了后续网络设计的思路

VGG也规范了后面网络的设计思路,后续的网络设计基本都是非常的规整。

基本都有一个最小的结构单元,然后在这个单元上进行堆叠。

还有就是一个默认:每次下采样过后,channel的数量也会相应的增加。

Inception

Inception结构,在设计网络结构时,不仅强调网络的深度,也会考虑网络的宽度

网中网的结构,也就是Inception结构。

Inception结构在后面设计网络结构的时候也是经常会被用到的一个网络结构。

Inception提出后,Google也进行了一系列的改进,提出v2、v3..

更多的卷积:网络的宽度(channel数量)

更深的层次:网络的深度

为什么GoogleNet的网路深度很深,宽度也很宽,可最终的参数量却很小呢?主要就是有效的利用了\(1*1\)的卷积核。

Inception结构是GooLeNet的最小结构单元,当然GoogLeNet中包含多个Inception结构, 每个Inception结构都有一些细微的差别。

不同于VGG的”串“结构,GoogLeNet表现为一个”网中网“的结构,输入的中间的这样一个层,它的每个结点同样也是一个卷积。

值得学习的一个点就是在经过\(3*3\)和\(5*5\)的卷积核之前,会使用\(1*1\)的卷积核来减少channel的数量。

GoogLeNet为了保证网络变深之后能够收敛的更好,利用了2个loss来进行训练。

GoogoLeNet最大的启示就是教会我们如何巧妙的利用\(1*1\)的卷积核。

理解为什么什么\(1*1\)的卷积核可以实现降维?

这个就是卷积运算本身的内容,卷积核的channel是多少,那么最后的结果是把每个channel进行相加。

也就是如果输入\(28*28*192\)经过一个\(1*1*64\)的卷积核后,尺寸会变成\(28*28*3\)。

上图的左右和右边分别表示在图片输入之前有没有加入\(1*1\)的卷积核。

  • 更深的网络结构,同时考虑了网络的宽度

GoogLeNet在设计的时候不仅考虑网络的深度,也考虑的网络的宽度。

  • 两个LOSS层,降低过拟合风险
  • 巧妙地利用\(1*1\)的卷积核来进行通道降维,减小计算量

这里的更新是 利用两个\(3*3\)替换\(5*5\),利用\(n*1\)和\(1*n\)替换了\(n*n\)。

使用小卷积核替换大卷积核的好处:

  • 参数量减少,计算量减少
  • 网络变深,那么可以插入更多的激活函数,增加网络的非线性能力。

实验表明,对于卷积的这种拆分,最好是在网络的中间使用,不要再输入的开始就进行这样的卷积拆分。

ResNet

ResNet引入跳连结构来防止梯度消失问题,可以进一步加大网络的深度。

ResNet也是后面许多网络结构作为主干网络进行特征提取的首选。

VGG最多有19层,ResNet可以达到上百层。为什么ResNet的网络结构可以这么深呢?因为引入了跳连的结构。

这种跳连结构直接将输入层的特征传递到输出层,然后和卷积之后的结果进行相加,最后可以得到一个结合了原始输入特征的输出特征。

在网络加入这样跳连的线,实际上并没有增加参数量,虽然网络结构发生了变化,但是网络的参数量是没有发生变化的,这也是跳连结构的一个优点。

ResNet在设计的时候同样采用卷积堆叠的方式,但是不再是串联,而是这种带有跳连的结构来作为核心单元。然后网络使用这样的单元来进行堆叠。

输入使用\(7*7\)的卷积核,由于初始channel为3,问题不大。可以发现后面深层一点的卷积核都是\(1*1\)和\(3*3\)的。

ResNet在最后分类的时候,采用的不是FC,而是average pool。VGG的80%的参数集中在FC层,使用一个池化层来替换掉FC层,会减少很多的参数量,因为池化层本身是没有参数的。

对于像50、101、152层的ResNet,其中还采用了\(1*1\)的卷积核来减少计算量,整个还是可以接受的。

上图有给出网络需要的计算量FLOPs。

还有就是ResNet对缓存有要求,如下图,从A->C不是直接串联下来的,而是需要把A先进行缓存,如果feature map比较大或channel比较多,对机器的缓存就有要求。

例如上图,网络当然不是越深越好,这是一定的,比如F3的网络可能最优解比F6找到的要更好,这种虽然网络更深,但是并没有表现得更好,这就是模型偏移。

ResNet的思想就是可以保证模型不会变差。

如下图,输入的特征为x,输出特征为\(H(x)=f(x)+x\)

也就是,即使没有\(f(x)\),那么\(H(x)\)也有x作为保底。

从卷积的角度思考,如何减小网络中的计算量

从GoogleNet中,可以总结出下面几个结论,来减少卷积网络中的计算量。

  • 小卷积核来对大卷积核进行拆分

对于\(5*5\)和\(7*7\)这样的大卷积核(不可能比7更大),最多只会使用再输入层,因为原始图片输入channel为3,那么channel为3的计算量还是很小的,但是后续的channel的可能是32、64、128,这就是非常大一个channel数量。

后面一般都是采用\(3*3\)或\(1*1\)的卷积核,不太会采用其他的大小的卷积核。像类似\(1*3\)和\(3*1\)也很少使用,只用在Inception中使用了。

  • stride=2代替pooling层

stride=2可以直接降低当前卷积层的计算量。

  • 巧妙地利用\(1*1\)的卷积核来进行降维

\(1*1\)卷积核可以帮助减少channel的数量。

我们在设计卷积的时候,要压缩网络的时候,就可以从上面的点来进行考虑。

卷积神经网络结构对比

AlexNet:开启了卷积神经网络的风暴

VGG:加深了卷积神经网络

GoogLeNet:加深、加宽了网络

ResNet:更加加深了网络

卷积神经网络中的Attention机制

注意力机制可能大家在循环神经网中大家了解会比较多一点,实际上在卷积神经网络中也存在attention机制。

attention是模仿人脑在观察图片的时候,会像关注重要的信息。

引入attention机制,使得网络有更好的可解释性。

attention就是对图像相应位置进行不同程度的加权

Hard-Attention:0/1这样的mask

Soft-Attention:0~1这样的mask

attention就是一种加权的思路,这种加权的思路不仅可以用在特征图,还可以用在原始图、空间尺度...

上部分是一个标准的ResNet结构,下部分就是在计算特征图上每个点的权值,通过卷积和反卷积,得到和feature map大小一致的结果,然后对这个输出结果进行激活,然后和特征结果进行点乘,再进行相加,这就完成了对特征图的加权。

上图是将特征图作用在通道上的一种加权的方法。

模型压缩

想要让模型跑在嵌入设备中

  • 一种方法就是设计一些轻量型的卷积神经网络
  • 还有就是对大的模型进行模型压缩

模型压缩也是在精度和速度之间的一种平衡。

学院派希望精度越高越好,工程派希望在精度一定时候,能够让模型尽可能的轻量,减少计算量。

模型剪枝

小结

什么是卷积神经网络

卷积神经网络:以卷积结构为主(除了conv,还有pooling,dropout等层次结构),搭建起来的深度网络。
*   将图片作为输入:卷积输入数据的维度$(n,h,w,c)$,分别表示batch_size,高度,宽度,色彩通道。
*   自动提取特征:参数优化
*   图片的变形具有高度不变性:对于图像的形变是不敏感的,是鲁棒的

特征提取通常是在输出结果前的一层,FC层,经过这个FC层,卷积特征就会变成一个向量,这个向量具体多少维,取决于FC的参数。

卷积的基本定义

卷积:对图像和滤波矩阵(卷积核)做互相关运算(对应元素相乘再求和)的操作。

卷积操作简单来说就是图像和滤波矩阵进行先乘后加的操作。

*   滤波器
*   每一种卷积对应一种特征
*   Im2col实现卷积运算:实现卷积运算不是两重循环,而是先把图片转换成向量,然后进行向量的运算。

卷积核,以及卷积核的大小为什么都是奇数?

卷积核

*   最常用为2D卷积核$(k_w*k_h)$
*   权重和偏置项
*   常用卷积核:1\*1,3\*3,5\*5,7\*7 (一般不会超过7\*7)



为什么卷积核都是奇数的大小?因为有“中间点”,feature map存在“中间点”与原来的图像进行一一对应,可以保留图像的空间信息。

一般而言,卷积操作后feature map的尺寸会变小,padding可以使得feature map的尺寸与原图像一致。

卷积中的局部连接和权值共享

局部连接:图片中只有局部与输出的feature map的点有关
全连接:feature map的店与图像中的全部点都有关

权值共享:没有必要每一个局部都训练出一个卷积核的参数,一个就行了(提取同一种特征,而且与位置无关)

局部连接&权值共享大大减小了图片的网络参数数量!

卷积核与感受野

**使用小卷积核替代大卷积核的好处:参数量和计算量明显降低!**

通过多个小卷积核来替代一个大卷积核,不仅可以保证感受野的大小不变,而却网络的深度会加深,那么就可以在卷积层和卷积层的其中加入一些非线性层,使得网络的非线性能力更加的强,意味着网络描述一个事物的能力会变强。

如何估算卷积的参数量?

32*32*3image
filter size:5*5
filter num:100

那么参数的个数为
5*5*3*1*100

如果没有权值共享,那么为 (5*5*3)*(28*28)*100

步长

步长(Stride)

*   下采样的过程(把高维矩阵通过一个隐层映射为一个维数较低的矩阵)
*   输出Feature Map的大小变化:$(N-F)/stride+1$

stride一般都是设置为1或2。

pad

Pad

*   确保Feature Map整数倍变化,对尺度相关的任务尤为重要

比如$8*8$大小的矩阵,卷积核的大小为$3*3$,那么经过pooling得到的Feature Map的大小为$6*6$,$8*8$和$6*6$相差不是整数倍!

具体要pad多少呢?和卷积核的大小相关

*   F=3 =》zero pad with 1
*   F=3 =》zero pad with 2
*   F=3 =》zero pad with 3

池化层

池化:对输入的特征图进行压缩

*   使特征图变小,简化网络计算复杂度(stride就是有下采样的作用)
*   进行特征压缩,提取主要特征
*   增大感受野



池化是对Feature Map进行压缩,得到更小的Feature Map!
压缩Feature Map,一方面是可以减少计算量,还有这也是一个特征提取的过程,另外,对Feature Map压缩可以增大感受野。

注意: 池化层是没有参数的,所以进行BP的时候是无关池化层的事情!

什么是线性?什么是非线性?

从分类器的角度来理解:

*   线性分类器就是用一个“超平面”将正、负样本隔离开,如:
    (1)二维平面上的正、负样本用一条直线来进行分类;
    (2)三维立体空间内的正、负样本用一个平面来进行分类;
    (3)N维空间内的正负样本用一个超平面来进行分类。
*   非线性分类器就是用一个“超曲面”或者多个超平(曲)面的组合将正、负样本隔离开(即,不属于线性的分类器),如:
    (1)二维平面上的正、负样本用一条曲线或折线来进行分类;
    (2)三维立体空间内的正、负样本用一个曲面或者折面来进行分类;
    (3)N维空间内的正负样本用一个超曲面来进行分类。



从函数定义角度来说:

*   线性:1、变量之间的变化率为恒量,函数关系是直线;2、满足叠加原理,即f(ax + by) = af(x) + bf(y)。
*   非线性:所有不满足线性条件的关系就是非线性。
*   可以写成多元一次方程组形式的,就是线性。二次以上就是非线性。

激活函数,sigmoid,tanh,ReLU

激活函数:增加网络的非线性,进而提升网络的表达能力

sigmoid:
sigmoid函数将输入的值归一化到0到1中去 $x => [0,1]$,$[0,1]$之间有什么特点呢?可以表达概率。因此如果是分类任务,可以使用sigmod函数将结果映射到$[0,1]$当中,这样就拿到一个关于结果预测的概率分布。

sigmoid函数很少在网络的中间层,主要原因就是sigmoid容易出现梯度弥散/梯度饱和这样的问题,BP由链式法则进行乘法叠加,那么就会有梯度弥散(就是梯度很小,收敛很慢)。

指数运算是一个非常耗时的运算!
sigmoid更多是作为最后的输出层。
**sigmoid和tanh在RNN中应用会更多,在CNN中应用是较少的!**

tanh:
tanh和sigmoid的问题是类似的,一个就是梯度弥散的问题,一个就是指数运算的问题。
tanh和sigmoid的区别在于输出是否以零为中心。
**一般在设计CNN的时候都是不会用到tanh和sigmoid的,sigmoid还CNN还会有用到,tanh基本是不会在CNN中出现的**

ReLU:
**RuLU激活函数是现在CNN的标配激活函数!**

BatchNorm层/批量归一化层

BatchNorm层:通过一定的规范化手段,把每层神经网络任意神经元这个输入值的分布强行拉回到均值为0,方差为1的标准正态分布。

效果:非常的work!现在基本是深层卷积网络的标配。(典型的工程走在理论前面!)
作用:可能就是通过在每个小批量里加入噪音来控制模型的复杂度(防止过拟合),还有就是BN层可以加速收敛速度,但是对精度不会影响太多(所以一般大家都乐意加上BN层,能加速何乐而不为呢)


引入BatchNorm层,对数据进行规范化的约束,会带来很多优点。
*   可以取消Dropout层(丢弃法)和L2正则项
*   BN层可以加速模型收敛,因此学习率可以稍微增大
*   BN可以理解为在每个小批量里加入了噪音,以此来控制模型的复杂度


为什么需要引入BatchNorm层对数据进行规范化处理呢?

对于原始的输入数据,如果我们不加规范化的话,输入数据的分布是不可控的,每个层的数据分布都是有差异的。而且这个差异,在训练的过程中,由于经过多轮的BP算法,每一轮的BP算法都会改变相应层的参数,这一层参数的改变,也意味着这一层的输入输出也会发生变化,输入输出发生变化,数据的部分又不可控,这个时候带来的一个现象就是训练过程中,每一层的分布是不停在变化的,这对于网络的收敛是非常不利的,也正是因为这样的一个原因,才会对输入的数据进行约束。

特征缩放方法

归一化: MinMaxScaler
标准化: StandardScaler

全连接层

全连接层:连接所有的特征,及那个输出值送给分类器(比如softmax分类器)

*   将网络的输出变成一个向量: 卷积层输出的结果,一定是一个四维的特征图$(n,h,w,c)$,需要将这个四维矩阵转化为一维向量进行全连接
*   可以采用卷积代替全连接层
*   全连接层是尺度敏感的:全连接层的参数是固定的,如果输入的个数改变,那么运算的式子也会跟着改变。
*   配合使用dropout层: 因为全连接层的参数量非常大,所以使用dropout层随机丢弃一些节点


全连接层就是一个线性运算。

通常而言,一个卷积网的参数量,大部分都是占据在全连接层的,比如VGG,80%的参数都是来自最后的FC层。

权重衰退&丢弃法(dropout)

如何防止模型过拟合?
* 让模型变得简单:丢弃法
* 让权重不要太大:权重衰退(权重不要那么大,就不会学习的那么激烈)

权重衰退和dropout都是防止过拟合的手段,能够一定程度上提升模型的表现效果。

什么是范数?

非正式地说,一个向量的范数告诉我们一个向量有多大。
在线性代数中,向量范数是将向量映射到标量的函数f。

常用的范数有 L1,L2(默认 欧氏距离就是L2范数)

L1范数:它表示为向量元素的绝对值之和。
L2范数:假设n维向量x中的元素是x1,…,xn,其L2范数是向量元素平方和的平方根。

损失函数(目标函数)

损失函数:用来评估模型的预测值和真实值的不一致程度。
目标函数 = 损失函数(经验风险最小) + 正则化(结构风险最小)

L0,L1,L2正则化(范数约束/正则项/惩罚项)

L0:参数中取值为0的个数(参数的0越多,表示模型越简单)
L1:所有数的绝对值相加
L2:所有数平方相加开根号(距离)

L0是没有办法求导的,所以有了L1,L1是对L0的线性逼近。
L2是对L1的凸优化

L0、L1可以实现参数稀疏,模型稀疏的话泛化能力会更好

什么是似然?

什么是似然?我们在学习概率统计的时候经常会去区分两个概念,就是概率和似然。

*   概率通常是一个统计上的概念,某一个事件出现的频次
*   似然是在已知结果的情况下,反推产生这些结果的原因(在深度学习中这些原因就是我们要进行学习的参数)

损失函数

分类任务:交叉熵损失函数
回归任务:L1、L2、smooth L1(一般都是选择smooth L1作为回归任务的损失函数)

卷积神经网络中的设计标配

激活函数:ReLU
FC+d

LeNet

LeNet应用于一个十分类问题(手写数字识别 mnist)。

从LeNet可以看到分类任务的大概思路。

图片输入,经过(conv,pooling),在经过全连接层(FC n分类就n维),最后经过softmax,得到一个$[0,1]$的概率值。

AlexNet

2012年显卡的显存还是有限的,网络模型图中给出的两个分支,表示使用两张显卡进行分布式训练。

*   conv-relu-pooling-LRN

网络图所示,图片经过多轮卷积,$11*11,5*5,3*3,3*3,3*3$,AlexNet在设计的时候,每一个卷积之后,都会配有relu,pooling,LRN三个层。

relu 增加非线性能力
pooling 下采样,增大图像感受野,对图像进一步提取
LRN 归一化,将数据约束在一定


*   fc-rule-dropout

在经过两个fc层,后面跟着rule和dropout,因为fc层的参数量非常大,所以这里要使用dropout层进行一些参数的删除(置零)。

*   fc-softmax

最终将特征映射到一个1000维的向量上。
最终训练出来的参数在60M以上,整个模型大小在200M以上。

*   ReLU激活函数
ReLU激活函数相对于其他的激活函数,能实现一个更快的计算速度,并且在x大于0时,不会出现梯度消失这样的问题。

ReLU也成了后面我们设计卷积神经网络的一个标配。

*   Dropout层
FC+Dropout层是标配,dropout可以减少过拟合的风险,因为FC中存在过多的参数,通过dropout能够对FC的参数进行约束。

*   LRN层
后面研究发现LRN层其实没有多大作用,现在基本已经被弃用了,现在使用的最多的是BN层。

ZFNet

ZFNet对于AlexNet并没有多大的改进,只是对AlexNet进行了一些细致的调整。ZFNet的最大贡献是对卷积网络为什么有效进行了分析。

ZFNet中提出的几点结论,是非常有普适性的。

ZFNet将特征进行可视化展示,具体是如何实现呢?上图的右边是正常卷积网的一个数据流向,对于我们最终下采样拿到的一个图片,我们该如何还原成最初的图片呢?实际上如果想进行百分百的还原,这是不可能的,因为经过激活层和pooling层的时候,会对图像造成不可逆的破坏,因此这个还原只是对特征高层次的语义分析,具体是通过上采样和反卷积操作来完成的,最终得到与原始图像大小一致的特征图。

通过观察这些还原出来的特征图,作者总结出下面的结论
* 特征分层次体系结构
* 深层特征更鲁棒
* 深层特征更有区分度
* 深层特征收敛更慢

VGG

VGG

*   为了研究**网络深度**对模型准确度的影响,并采用小卷积堆叠的方式,来搭建整个网络结构
都是采用了$3*3$的小卷积。

*   参数量:138M;模型大小>500M
VGG的网络更大,对比参数量的大小和模型大小就可以知道。



上面的VGG示例图只列出了卷积的结构,实际上在卷积当中还会插入激活层和池化层。

上面列出了11层、13层、16层、19层(卷积层、FC层是需要进行参数训练的,池化层不需要训练)。

这里输入图像的大小是$224*224$,这个尺寸是对应ImageNet挑战赛图像分类任务的图像尺寸,这也是为什么我们在设计分类识别任务的时候采用$224*224$来设计和训练网络。我们想要使用ImageNet挑战赛上表现优秀的模型来进行模型迁移,那么就需要保证和训练的模型数据的一致性,所以在设计网络的时候会尽量保证尺寸为$224*224$。

VGG的特点

*   更深的网络结构,结构更加规整、简答
*   全部使用$3*3$的小型卷积核核$2*2$的最大池化层
不难发现一点,VGG的网络非常深,相比AlexNet,它的卷积是非常多的,另外可以发现这里的卷积核都是$3*3$的卷积核,没有大于$3*3$的卷积核。
小卷积核可以实现大卷积核的感受野范围,同时计算量会更小。
*   每次池化后Feature Map宽高降低一半,通道数量增加一倍
每次经过一个pooling层,channel的数量会乘2,保证提取的数量。
*   网络层数更多,结构更深,模型参数更大

VGG的意义

*   证明了更深的网络,能够提取更好的特征
*   成为后续很多网络的backbone
利用VGG来进行特征的提取,虽然VGG只在ImageNet挑战赛获得第二名,但是使用VGG提取出来的图像特征往往更有效。
这也是为什么VGG也成为后续很多网络的主干网络。

*   规范化了后续网络设计的思路
VGG也规范了后面网络的设计思路,后续的网络设计基本都是非常的规整。
基本都有一个最小的结构单元,然后在这个单元上进行堆叠。
还有就是一个默认:每次下采样过后,channel的数量也会相应的增加。

GoogLeNet/Inception

Inception结构,**在设计网络结构时,不仅强调网络的深度,也会考虑网络的宽度**。
网中网的结构,也就是Inception结构。
Inception结构在后面设计网络结构的时候也是经常会被用到的一个网络结构。
Inception提出后,Google也进行了一系列的改进,提出v2、v3..

更多的卷积:网络的宽度(channel数量)
更深的层次:网络的深度

为什么GoogleNet的网路深度很深,宽度也很宽,可最终的参数量却很小呢?主要就是有效的利用了$1*1$的卷积核。


GoogoLeNet最大的启示就是教会我们如何巧妙的利用$1*1$的卷积核。
理解为什么什么$1*1$的卷积核可以实现降维?

这个就是卷积运算本身的内容,卷积核的channel是多少,那么最后的结果是把每个channel进行相加。
也就是如果输入$28*28*192$经过一个$1*1*64$的卷积核后,尺寸会变成$28*28*3$。

GoogLeNet的特点

*   更深的网络结构,同时考虑了网络的宽度
GoogLeNet在设计的时候不仅考虑网络的深度,也考虑的网络的宽度。
*   两个LOSS层,降低过拟合风险
*   巧妙地利用$1*1$的卷积核来进行通道降维,减小计算量

关于\(1*1\)卷积和stride=2

1*1卷积可以减少channel的数量,也可以理解成“全连接”,因为减少channel实际上就是让channel进行了线性堆叠

stride=2不仅可以减少当前卷积层的计算量,而且可以替换了池化层,因为池化层丢弃的参数会更多。 但是每层卷积都是有参数的,这样计算量会增大不少。

从卷积角度思考,如何减少网络中的计算量?

从GoogleNet中,可以总结出下面几个结论,来减少卷积网络中的计算量。

*   小卷积核来对大卷积核进行拆分
对于$5*5$和$7*7$这样的大卷积核(不可能比7更大),最多只会使用再输入层,因为原始图片输入channel为3,那么channel为3的计算量还是很小的,但是后续的channel的可能是32、64、128,这就是非常大一个channel数量。

后面一般都是采用$3*3$或$1*1$的卷积核,不太会采用其他的大小的卷积核。像类似$1*3$和$3*1$也很少使用,只用在Inception中使用了。

*   stride=2代替pooling层
stride=2可以直接降低当前卷积层的计算量。

*   巧妙地利用$1*1$的卷积核来进行降维
$1*1$卷积核可以帮助减少channel的数量。



我们在设计卷积的时候,要压缩网络的时候,就可以从上面的点来进行考虑。

关于深层网络梯度爆炸和梯度消失的理解

BP算法求梯度,是一个一个导数相乘的 x*x*x*...  这里可以抽象为 x^n
如果 x>1 n->∞, 那么 x->∞  梯度爆炸
如果 x<1 n->∞, 那么 x->0  梯度消失

ResNet

ResNet引入跳连结构来防止梯度消失问题,可以进一步加大网络的深度。

ResNet也是后面许多网络结构作为主干网络进行特征提取的首选。

VGG最多有19层,ResNet可以达到上百层。为什么ResNet的网络结构可以这么深呢?因为引入了跳连的结构。

这种跳连结构直接将输入层的特征传递到输出层,然后和卷积之后的结果进行相加,最后可以得到一个结合了原始输入特征的输出特征。

在网络加入这样跳连的线,实际上并没有增加参数量,虽然网络结构发生了变化,但是网络的参数量是没有发生变化的,这也是跳连结构的一个优点。

ResNet在设计的时候同样采用卷积堆叠的方式,但是不再是串联,而是这种带有跳连的结构来作为核心单元。然后网络使用这样的单元来进行堆叠。

输入使用$7*7$的卷积核,由于初始channel为3,问题不大。可以发现后面深层一点的卷积核都是$1*1$和$3*3$的。

ResNet在最后分类的时候,采用的不是FC,而是average pool。VGG的80%的参数集中在FC层,使用一个池化层来替换掉FC层,会减少很多的参数量,因为池化层本身是没有参数的。

对于像50、101、152层的ResNet,其中还采用了$1*1$的卷积核来减少计算量,整个还是可以接受的。

上图有给出网络需要的计算量FLOPs。



还有就是ResNet对缓存有要求,如下图,从A->C不是直接串联下来的,而是需要把A先进行缓存,如果feature map比较大或channel比较多,对机器的缓存就有要求。

ResNet的设计点

如下图,输入的特征为x,输出特征为$H(x)=f(x)+x$
也就是,即使没有$f(x)$,那么$H(x)$也有x作为保底。


* 核心单元简单堆叠
* 跳连结构解决网络梯度消失问题
* average pooling层代替FC层
* BN层加快网络训练速度和收敛时的稳定性
* 加大网络深度,提高模型特征提取能力

卷积中的attention

attention实际上就是一种加权的思想。
这篇关于人脸识别智能小程序 | 卷积神经网络基础 | 02的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!