人脸识别智能小程序 | 卷积神经网络基础 | 02
2021/7/29 22:10:13
本文主要是介绍人脸识别智能小程序 | 卷积神经网络基础 | 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的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-20微信小程序开发入门指南
- 2024-12-20小程序 createCameraContext() 怎么实现识别条形码功能?-icode9专业技术文章分享
- 2024-11-22微信小程序的接口信息py可以抓到吗?-icode9专业技术文章分享
- 2024-11-22怎样解析出微信小程序二维码带的参数?-icode9专业技术文章分享
- 2024-11-22微信小程序二维码怎样解析成链接?-icode9专业技术文章分享
- 2024-11-22微信小程序接口地址的域名需要怎么设置?-icode9专业技术文章分享
- 2024-11-22微信小程序的业务域名有什么作用-icode9专业技术文章分享
- 2024-11-22微信小程序 image有类似html5的onload吗?-icode9专业技术文章分享
- 2024-11-22微信小程序中怎么实现文本内容超出行数后显示省略号?-icode9专业技术文章分享
- 2024-11-22微信小程序怎么实现分享样式定制和图片定制功能?-icode9专业技术文章分享