人类的视觉原理如下:从原始信号摄入开始(瞳孔摄入像素 Pixels),接着做初步处理(大脑皮层某些细胞发现边缘和方向),然后抽象(大脑判定,眼前的物体的形状,是圆形的),然后进一步抽象(大脑进一步判定该物体是只气球)。
下面是人脑进行人脸识别的一个示例:
对于不同的物体,人类视觉也是通过逐层分级进行认识的:
从中可见:最底层的特征基本上都是类似的(就是各种边缘),越向上越能够提取出该类物体的一些特征(车轮、眼睛、躯干),在最上层,不同的高级特征最终组合成相应的图像,从而让人类准确地区分不同的物体
卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一 ,是仿造生物的视知觉(visual perception)机制构建的。具有表征学习能力(representation learning),能够按其阶层结构对输入信息进行平移不变分类(shift-invariant classification),因此也被称为“平移不变人工神经网络(Shift-Invariant Artificial Neural Networks, SIANN)”
对卷积神经网络的研究始于二十世纪80至90年代,时间延迟网络和LeNet-5是最早出现的卷积神经网络;在二十一世纪后,随着深度学习理论的提出和数值计算设备的改进,卷积神经网络得到了快速发展,并被应用于计算机视觉、自然语言处理等领域 。
关于CNN的相关文章大部分都发在计算机视觉***学术会议之上
一张图片由像素构成,每个像素又是由颜色构成:一张1000*1000像素的图片,每个像素有RGB三个参数表示颜色通道,因此识别一张图片至少需要处理3000000(3百万)个参数
使用CNN进行处理,将参数减少而保留最重要的识别特征,达到网络训练的需求同时提高了运行效率
常规的方法之中我们将图像信息转换为向量信息:假如有圆形是1,没有圆形是0,那么圆形的位置不同就会产生完全不同的数据表达。但是从视觉的角度来看,图像的内容(本质)并没有发生变化,只是位置发生了变化。
当我们移动图像中的物体,用传统方式得出的参数会有较大差异,但是使用CNN,当图像做偏转、旋转或者换位时,其仍然可以有效识别出类似的图像
CNN之中将神经元设计为三个维度:width,height,depth;(此处的depth不是神经网络的深度,而是用来描述神经元的维度)。例如一张图片我们描述为 32 × 32 × 3 ( r g b ) 32×32×3(rgb) 32×32×3(rgb),那么输入神经元也就具有32×32×3的维度。图解如下:
传统神经网络:
CNN神经网络:
详解卷积神经网络(CNN)
卷积神经网络 – CNN
Deep Visualization:可视化并理解CNN
深度学习之卷积神经网络CNN及tensorflow代码实现示例
卷积神经网络(CNN,ConvNet)及其原理详解
卷积有多少种?一文读懂深度学习中的各种卷积
CNN卷积神经网络层级结构
深度学习算法之卷积神经网络(CNN)
卷积层负责提取图像中的局部特征;池化层用来大幅度降低参数量级(降维);全连接层类似传统神经网络BP,用来输出想要的结果
中间常常使用的一些功能层:
实际应用之中往往将卷积层和ReLU层共同称之为卷积层,所以卷积层经过卷积操作也是要经过激励函数的。具体说来,卷积层和全连接层(CONV/FC)对输入执行变换操作的时候,不仅会用到**函数,还会用到很多参数,即神经元的权值w和偏差b;而ReLU层和池化层则是进行一个固定不变的函数操作。卷积层和全连接层中的参数会随着梯度下降被训练,这样卷积神经网络计算出的分类评分就能和训练集中的每个图像的标签吻合了。
输入层(Input Layer):将原始数据或者其他算法预处理后的数据输入到卷积神经网络,数据没有明确定义,可以是数字图像,可以是音频识别领域经过傅里叶变换的二维波形数据,也可以是自然语言处理中一维表示的句子向量。输入层的作用是将输入数据送入卷积神经网络进行特征提取,然后获得我们想要的结果。同时根据计算能力差异,机器存储能力差异和模型参数多少可以控制输入不同数量的数据。
与传统的全连接神经网络的输入数据格式(一维向量)不相同,CNN输入层的输入格式保留了图像本身的结构
对于黑白的28×28的黑白图片,其输入就是一个28×28的二维神经元
对于彩色RGB格式的28×28的片,其输入就是3×28×28的三维神经元(RGB中的每一个颜色通道都有一个28×28的矩阵)
在信号/图像处理领域卷积定义:卷积、旋积或摺积(Convolution)是通过两个函数f 和g 生成第三个函数的一种数学算子,表征函数f 与g经过翻转和平移的重叠部分函数值乘积对重叠长度的积分。
∫
−
∞
∞
f
(
τ
)
g
(
x
−
τ
)
d
τ
\int_{-∞}^{∞}f(\tau)g(x-\tau)d\tau
∫−∞∞f(τ)g(x−τ)dτ
信号处理中的卷积。过滤器 g 经过反转,然后再沿水平轴滑动。在每一个位置,我们都计算 f 和反转后的 g 之间相交区域的面积。这个相交区域的面积就是特定位置出的卷积值
在深度学习中,卷积中的过滤器不经过反转。严格来说,这是互相关。我们本质上是执行逐元素乘法和加法。但在深度学习中,直接将其称之为卷积更加方便。这没什么问题,因为过滤器的权重是在训练阶段学习到的。如果上面例子中的反转函数 g 是正确的函数,那么经过训练后,学习得到的过滤器看起来就会像是反转后的函数 g。因此,在训练之前,没必要像在真正的卷积中那样首先反转过滤器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zAzbBose-1605182789674)(attachment:image-5.png)]
卷积层可以说是 CNN 架构中最重要的步骤之一。基本而言,卷积是一种线性的、平移不变性的运算,其由在输入信号上执行局部加权的组合构成。根据所选择的权重集合(即所选择的点扩散函数(point spread function))的不同,也将揭示出输入信号的不同性质。在频率域中,与点扩散函数关联的是调制函数——说明了输入的频率组分通过缩放和相移进行调制的方式。因此,选择合适的核(kernel)对获取输入信号中所包含的最显著和最重要的信息而言至关重要,这能让模型对该信号的内容做出更好的推断。
重要概念:
局部感知域:
如果想要保留图像中的空间信息,那么使用像素矩阵表示每个图像非常方便。然后编码局部结构的简单方法就是将相邻输入神经元的子矩阵连接成属于下一层的单隐藏神经元。
隐藏层中的神经元具有一个固定大小的感受域去感受上一层的部分特征。在全连接神经网络之中,隐藏层中的神经元的感受域连接了上一层的全部特征,而在CNN之中感受视野仅连接了一个很小的范围,只能看到上一次的部分特征。
假设输入的是一个
28
×
28
28×28
28×28的二维神经元,我们定义
5
×
5
5×5
5×5的local receptive fields(局部感受野),即隐藏层的神经元与这个
5
×
5
5×5
5×5的神经元连接。
步幅(stride)+卷积核(Convolution kernel)
一个感受视野对应一个卷积核,我们将感受视野中的权重w矩阵称为卷积核
,将感受视野对输入的扫描间隔称之为步幅(Stride)
。
边界扩充(padding):
当步长较大时(stride>1),为了扫描到边缘的一些特征,感受视野可能会出界,此时需要定义边界扩充(padding)
,边界扩充可以设置为0(zero-padding)
或者其他的值。(下图中灰色部分即为填充的值)
特征映射图(feature map):
对于下一层的全部神经元来说,他们从不同的位置上探测了上一层神经元的特征。我们将通过一个带有卷积核的感受视野扫描生成的下一层神经元矩阵称为一个feature map(特征映射图)
权值共享是基于这样的一个合理的假设:如果一个特征在计算某个空间位置 (x1,y1)(x1,y1)
的时候有用,那么它在计算另一个不同位置(x2,y2)(x2,y2)
的时候也有用。基于这个假设,可以显著地减少参数数量。换言之,就是将深度维度上一个单独的2维切片看做深度切片(depth slice)
,比如一个数据体尺寸为[55x55x96]
的就有96个深度切片,每个尺寸为[55x55]
,其中在每个深度切片上的结果都使用同样的权重和偏差获得的。在这样的参数共享下,假如第一个卷积层有96个卷积核,那么就有96个不同的权重集了,一个权重集对应一个深度切片,如果卷积核的大小是 11x11的,图像是RGB3
通道的,那么就共有96x11x11x3=34848
个不同的权重,总共有34944
个参数(因为要+96个偏差),并且在每个深度切片中的55x55 的结果使用的都是同样的参数。
我们不禁会问为什么要权重共享呢?一方面,重复单元能够对特征进行识别,而不考虑它在可视域中的位置。另一方面,权值共享使得我们能更有效的进行特征抽取,因为它极大的减少了需要学习的***变量的个数。通过控制模型的规模,卷积网络对视觉问题可以具有很好的泛化能力。
在反向传播的时候,都要计算每个神经元对它的权重的梯度,但是需要把同一个深度切片上的所有神经元对权重的梯度累加,这样就得到了对共享权重的梯度。这样,每个切片只更新一个权重集。这样做的原因可以通过下面这张图进行解释:
如上图所示,左侧的神经元是将每一个感受野展开为一列之后串联起来(就是展开排成一列,同一层神经元之间不连接)。右侧的 Deep1i 是深度为1的第 i 个神经元, Deep2i 是深度为2的第 i 个神经元,同一个深度的神经元的权值都是相同的,黄色的都是相同的(上面4个与下面4个的参数相同),蓝色都是相同的。所以现在回过头来看上面说的卷积神经网络的反向传播公式对梯度进行累加求和也是基于这点考虑(同一深度的不同神经元共用一组参数,所以累加);而每个切片只更新一个权重集的原因也是这样,不同深度的神经元不会公用相同的权重,所以只能更新一个权重集。
注意,如果在一个深度切片中的所有权重都使用同一个权重向量,那么卷积层的前向传播在每个深度切片中可以看做是在计算神经元权重和输入数据体的卷积(这就是“卷积层”名字由来)。这也是为什么总是将这些权重集合称为滤波器(filter)(或卷积核(kernel)),因为它们和输入进行了卷积。
注意,有时候参数共享假设可能没有意义,特别是当卷积神经网络的输入图像是一些明确的中心结构时候。这时候我们就应该期望在图片的不同位置学习到完全不同的特征(而一个卷积核滑动地与图像做卷积都是在学习相同的特征)。一个具体的例子就是输入图像是人脸,人脸一般都处于图片中心,而我们期望在不同的位置学习到不同的特征,比如眼睛特征或者头发特征可能(也应该)会在图片的不同位置被学习。在这个例子中,通常就放松参数共享的限制,将层称为局部连接层(Locally-Connected Layer)。
卷积核偏置(bias):
卷积核的大小需要用户自己来定义,即定义视野的大小;卷积核的权重矩阵的值便是卷积神经网络的参数,为了定义一个偏移项,卷积核可以附带一个偏移项b,其初值可以随机生成,也可以通过训练进行变化。对于
3
×
3
3×3
3×3的感受视野,其扫描时计算出的下一层的隐藏层神经元的值为:
y
=
∑
i
=
0
2
∑
j
=
0
2
ω
i
j
x
i
j
+
b
y = \sum_{i=0}^2\sum_{j=0}^{2}\omega_{ij}x_{ij} + b
y=i=0∑2j=0∑2ωijxij+b
二维输入神经元卷积计算流程(没加偏置bias):
三维输入神经元卷积计算流程
上图中, 最左边是输入的特征图矩阵, 深度为 3, 补零(Zero Padding)层数为 1, 每次滑动的步幅为 2. 中间两列粉色的矩阵分别是两组卷积核, 一组有三个, 三个矩阵分别对应着卷积左侧三个输入矩阵, 每一次滑动卷积会得到三个数, 这三个数的和作为卷积的输出. 最右侧两个绿色的矩阵分别是两组卷积核得到的特征图.
关于**函数我之前写过一遍博客:
机器学习——神经网络(四):BP神经网络
**层(Activation Layer)负责对卷积层抽取的特诊进行**,由于卷积操作是把输入图像和卷积核进行相应的线性变换,需要引入**层(非线性函数)对其进行非线性映射。**层由非线性函数组成,常见的如sigmoid、tanh、relu。
最常用的**函数是Relu,又叫线性整流器。公式表示为
h
(
x
)
=
m
a
x
(
x
,
0
)
h(x) = max(x,0)
h(x)=max(x,0)
经过**函数之后,得到的结果是:
Z
x
,
y
=
h
(
∑
i
p
∗
q
ω
i
v
i
+
b
)
Z_{x,y} = h(\sum_{i}^{p*q}\omega_iv_i + b)
Zx,y=h(i∑p∗qωivi+b)
当输入经过卷积层时,若感受视野
比较小,步长stride
比较小,得到的feature map
(特征图)还是比较大,可以通过池化层来对每一个feature map
进行降维操作,输出的深度还是不变的,依然为feature map
的个数。
目前主要的pooling操作有:
池化层的优点:
池化层的 ‘不足’:
全连接层(Full Connected Layer)就是一个线性特征映射的过程,将多维的特征输入映射为二维的特征输出,高维表示样本批次,低位常常对应任务目标(例如分类就对应每一个类别的概率)。全连接层主要对特征进行重新拟合,减少特征信息的丢失;输出层主要准备做好最后目标结果的输出。
由于网络中存在级联的非线性运算,所以多层架构是高度非线性的。除了整流非线性,归一化(normalization)是 CNN 架构中有重要作用的又一种非线性处理模块。
Batch Normalization(批量归一化)实现了在神经网络层的中间进行预处理的操作,即在上一层的输入归一化处理后再进入网络的下一层,这样可有效地防止“梯度弥散”
,加速网络训练。
Batch Normalization具体的算法如下图所示:
每次训练时,取batch_size
大小的样本进行训练,在BN层中,将一个神经元看作一个特征,batch_size
个样本在某个特征维度会有batch_size
个值,然后在每个神经元xi
维度上的进行这些样本的均值和方差,通过公式得到xi^
,再通过参数γ
和β
进行线性映射得到每个神经元对应的输出yi
。在BN层中,可以看出每一个神经元维度上,都会有一个参数γ
和β
,它们同权重w
一样可以通过训练进行优化。
在卷积神经网络中进行批量归一化时,一般对未进行ReLu
**的 feature map进行批量归一化,输出后再作为激励层的输入,可达到调整激励函数偏导的作用。一种做法是将feature map中的神经元作为特征维度,参数γ
和β
的数量和则等于 2×fmapwidth×fmaplength×fmapnum2×fmapwidth×fmaplength×fmapnum
,这样做的话参数的数量会变得很多;另一种做法是把一个feature map看做一个特征维度,一个feature map上的神经元共享这个feature map的参数γ
和β
,参数γ
和β
的数量和则等于 2×fmapnum2×fmapnum
,计算均值和方差则在batch_size
个训练样本在每一个feature map维度上的均值和方差。注:fmapnumfmapnum
指的是一个样本的feature map数量,feature map 跟神经元一样也有一定的排列顺序。
Batch Normalization 算法的训练过程和测试过程的区别:在训练过程中,我们每次都会将 batch_size 数目大小的训练样本放入到CNN网络中进行训练,在BN层中自然可以得到计算输出所需要的均值和方差。而在测试过程中,我们往往只会向CNN网络中输入一个测试样本,这是在BN层计算的均值和方差会均为 0,因为只有一个样本输入,因此BN层的输入也会出现很大的问题,从而导致CNN网络输出的错误。所以在测试过程中,我们需要借助训练集中所有样本在BN层归一化时每个维度上的均值和方差,当然为了计算方便,我们可以在batch_num
次训练过程中,将每一次在BN层归一化时每个维度上的均值和方差进行相加,最后再进行求一次均值即可。
近邻归一化(Local Response Normalization)的归一化方法主要发生在不同的相邻的卷积核(经过ReLu之后)的输出之间,即输入是发生在不同的经过ReLu之后的 feature map 中。
LRN的公式如下:
b
(
i
,
x
,
y
)
=
(
a
(
i
,
x
,
y
)
k
+
α
∑
j
=
m
a
x
(
0
,
i
−
n
2
)
m
i
n
(
N
−
1
,
i
+
n
2
)
a
(
j
,
x
,
y
)
2
)
β
b(i,x,y) = (\frac{a(i,x,y)}{k+\alpha\sum_{j=max(0,i-\frac{n}{2})}^{min(N-1,i+\frac{n}{2})}}a(j,x,y)^2)^{\beta}
b(i,x,y)=(k+α∑j=max(0,i−2n)min(N−1,i+2n)a(i,x,y)a(j,x,y)2)β
其中:
a(i,x,y)
表示第i个卷积核的输出(经过ReLu层)的feature map上的 (x,y) 位置上的值。b(i,x,y)
表示a(i,x,y)
经LRN后的输出。N
表示卷积核的数量,即输入的feature map的个数。n
表示近邻的卷积核(或feature map)个数,由自己来决定。k,α,
是超参数,由用户自己调整或决定。与BN的区别:BN依据mini batch
的数据,近邻归一仅需要自己来决定,BN训练中有学习参数;BN归一化主要发生在不同的样本之间,LRN归 一化主要发生在不同的卷积核的输出之间。
在一些应用中,需要对图片进行切割,独立地对某一部分区域进行单独学习。这样可以对特定部分进行通过调整 感受视野进行力度更大的学习。
融合层可以对切分层进行融合,也可以对不同大小的卷积核学习到的特征进行融合。例如在GoogleLeNet中,使用多种分辨率的卷积核对目标特征进行学习,通过 padding 使得每一个 feature map 的长宽都一致,之后再 将多个 feature map 在深度上拼接在一起:
融合的方法有几种,一种是特征矩阵之间的拼接级联,另一种是在特征矩阵进行运算 (+,−,x,max,conv)。