- 有关神经网络的部分可以查看这里的
BP神经网络
的部分:https://github.com/lawlite19/MachineLearning_Python
- 典型的深度学习模型就是很深层的神经网络,包含多个
隐含层
,多隐层的神经网络很难直接使用BP算法
进行直接训练,因为反向传播误差时往往会发散,很难收敛 CNN
节省训练开销的方式是权共享weight sharing,让一组神经元使用相同的权值- 主要用于图像识别领域
-
卷积核
(Convolution Kernel),也叫过滤器filter
,由对应的权值W
和偏置b
体现 -
下图是
3x3
的卷积核在5x5
的图像上做卷积的过程,就是矩阵做点乘之后的和
第i
个隐含单元的输入就是:,其中就时与过滤器filter过滤到的图片 -
另外上图的步长
stride
为1
,就是每个filter
每次移动的距离 -
卷积特征提取的原理
-
卷积特征提取利用了自然图像的统计平稳性,这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。
-
当有多个
filter
时,我们就可以学到多个特征,例如:轮廓、颜色等 -
多个过滤器
filter
(卷积核) -
一张图片有
RGB
三个颜色通道,则对应的filter过滤器也是三维的,图像经过每个filter
做卷积运算后都会得到对应提取特征的图像,途中两个filter
:W0和W1,输出的就是两个图像 -
这里的步长
stride
为2
(一般就取2,3) -
在原图上添加
zero-padding
,它是超参数
,主要用于控制输出的大小 -
同样也是做卷积操作,以下图的一步卷积操作为例:
与w0[:,:,0]卷积:0x(-1)+0x0+0x1+0x1+0x0+1x(-1)+1x0+1x(-1)+2x0=-2
与w0[:,:,1]卷积:2x1+1x(-1)+1x1=2
与w0[:,:,2]卷积:1x(-1)+1x(-1)=-2
最终结果:-2+2+(-2)+1=-1
(1为偏置)
- 也叫做下采样
Pooling
过程- 把提取之后的特征看做一个矩阵,并在这个矩阵上划分出几个不重合的区域,
- 然后在每个区域上计算该区域内特征的均值或最大值,然后用这些均值或最大值参与后续的训练
-下图是使用最大
Pooling
的方法之后的结果 Pooling
的好处- 很明显就是减少参数
Pooling
就有平移不变性((translation invariant) 如图feature map
是12x12
大小的图片,Pooling区域为6x6,所以池化后得到的feature map
为2x2
,假设白色像素值为1,灰色像素值为0,若采用max pooling
之后,左上角窗口值为1
将图像右移一个像素,左上角窗口值仍然为1
将图像缩放之后,左上角窗口值仍然为1
Pooling
的方法中average
方法对背景保留更好,max
对纹理提取更好- 深度学习可以进行多次卷积、池化操作
- 在每次卷积操作之后一般都会经过一个非线性层,也是激活层
- 现在一般选择是
ReLu
,层次越深,相对于其他的函数效果较好,还有Sigmod,tanh
函数等 sigmod
和tanh
都存在饱和的问题,如上图所示,当x轴上的值较大时,对应的梯度几乎为0,若是利用BP反向传播算法, 可能造成梯度消失的情况,也就学不到东西了
- 看到知乎上的一个回答还不错:https://www.zhihu.com/question/52668301
- 每个过滤器可以被看成是特征标识符
( feature identifiers)
- 如下图一个曲线检测器对应的值
- 我们有一张图片,当过滤器移动到左上角时,进行卷积运算
- 当与我们的过滤器的形状很相似时,得到的值会很大
- 若是滑动到其他的部分,可以看出很不一样,对应的值就会很小,然后进行激活层的映射。
- 过滤器
filter
的值怎么求到,就是我们通过BP
训练得到的。
- 代码和说明放到了另外一个
Tensorflow
学习的仓库里了 - 全部代码:https://github.com/lawlite19/MachineLearning_TensorFlow/blob/master/Mnist_03_CNN/mnist_cnn.py
- 说明部分(第七部分):https://github.com/lawlite19/MachineLearning_TensorFlow
- 参考论文:http://cogprints.org/5869/1/cnn_tutorial.pdf
- 或者在这里查看:https://github.com/lawlite19/DeepLearning_Python/blob/master/paper/cnn_tutorial.pdf
- BP神经网络之前写过推导,可以查看这里的第三部分BP神经网络:https://github.com/lawlite19/MachineLearning_Python
- 我们假设CNN中每个卷积层下面都跟着一个Pooling池化层(下采样层)
- 文章的理解可能会有问题
l
..................当前层- ..................输入maps的集合
- up()..................上采样函数
- ㅇ....................表示对应每个元素相乘
β
....................下采样对应的“权重”(定义为常量)- ...................中在卷积运算中逐个与相乘的
patch
- down()..................下采样函数
-
1)卷积层计算公式
-
可以对照到上面多个卷积核的例子看
-
j
相当于是第几个卷积核 -
i
相当于对应卷积核或是map的维度 -
2)卷积层梯度计算
-
paper中叫做使用BP计算当前层layer单元的灵敏度(sensitivity)
-
也就是误差的计算,之前我在BP神经网络中推导过,这里不再给出
-
当前层的第
j
个unit的灵敏度结果就是:先对下一层的节点(连接到当前层l
的感兴趣节点的第l+1
层的节点)的灵敏度求和(得到),然后乘以这些连接对应的权值(连接第l
层感兴趣节点和第l+1
层节点的权值)W
。再乘以当前层l
的该神经元节点的输入u
的激活函数f的导数值 -
下采样的“weights”可以定义为常量
β
(可以查看下面Pooling层输出的表示) -
up
表示上采样操作,因为我们之前假设每个卷积层之后跟着一个Pooling层,所以反向传播需要进行上采样 -
up
上采样可以使用克罗内克积(Kronecker)实现,如果A是一个m x n
的矩阵,而B是一个p x q
的矩阵,克罗内克积则是一个mp x nq
的矩阵, -
所以偏置的梯度为: (因为神经网络中对
b
的梯度为:((δ就是误差,根据定义的代价函数E得来的),其中u
为layer的输入:) -
所以卷积核权值的梯度为: (其中:为中在卷积运算中逐个与相乘的
patch
,因为权重的系数就是对应的patch
,对权重求导,就是这个系数)
-
1)子采样层计算公式
-
乘以一个常数权重
β
,再加上偏置,然后再调用激活函数(这里和上面的pooling的操作有所不同,但总的来数还是下采样的过程) -
2)梯度计算
-
和上面的其实类似,就是换成下一层对应的权重
k
,rot180()是旋转180度,因为卷积的时候是将卷积核旋转180度之后然后在点乘求和的 -
对偏置
b
的梯度与上面的一样
- 参考论文:http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf
- 或者查看这里,我放在github上了:https://github.com/lawlite19/DeepLearning_Python/blob/master/paper/Understanding%20the%20difficulty%20of%20training%20deep%20feedforward%20neural%20networks.pdf
- 这是2010年的论文,当时只是讨论的
Sigmoid
,tanh
和Softsign
激活函数,解决深层神经网络梯度消失的问题,并提出了一种初始化权重weights
的方法,但是对于ReLu
激活函数还是失效的,下一篇再讲。
- 论文先是指出了
Sigmoid
激励函数是不适合作为深度学习的激励函数的,因为它的均值总是大于0
的,导致后面隐含层hidden layer的神经元趋于饱和
- 构建了含有4个隐层的神经网络,激活函数为
Sigmoid
,观察每一层的激活值的均值和标准差的岁训练次数的变化情况,layer1
表示第一个隐含层,一次类推。 - 初始化权重,即服从均匀分布
- 如下图所示,实线表示均值mean value,垂直的条表示标准差。
- 因为使用的均匀分布进行的初始化,所以前几层x的均值近似为0,所以对应
Sigmoid
函数的值就是0.5 - 但是最后一层layer4的输出很快就饱和了(激活值趋于0),训练到大100的时候才慢慢恢复正常
- 作者给出当有5个隐含层的时候,最后一层始终处于饱和状态
- 标准差反应的是数值的波动,可以看出后面才有了标准差的值
- 直观解释
- 最后使用的是
softmax(b+Wh)
作为预测,刚开始训练的时候不能够很好的预测y
的值,因此误差梯度会迫使Wh
趋于0
,所以会使h
的值趋于0
h
就是上一层的激活输出,所以对应的激活值很快降为0
tanh
激活函数是关于原点对称的,趋于0是没有问题的,因为梯度能够反向传回去。
- 首先代价函数使用的是交叉熵代价函数,相比对于二次代价函数会更好,看下对比就知道了,二次代价函数较为平坦,所以使用梯度下降会比较慢。(图中
W1
表示第一层的权重,W2
表示第二层的权重)
- 以
tanh
激活函数为例 - 符号说明
- ………………………………第i层的激活值向量
- ………………………………第i+1层的输入
- x…………………………………输入
- ………………………………..第i层神经元个数
- W………………………………权重
- Cost………………………………代价函数
- 所以第
i+1
层的输入:
- 激活之后的值表示:
, ❶
根据BP反向传播可以得到:
❷
权重的偏导(梯度)就为:
- 还是BP反向传播的推导,可以查看我之前给的BP反向传播的推导。
- 它这里
W
是从0
开始的,所以对应可能不太一致。 tanh
的导数为:
- 所以:
- 当的很小时,可以得到:
- 这里实际上他是假设激励函数是线性的,下一篇论文中也有提到。
- 根据方差公式:
可以得到❸
:
,
推导如下: - (式子太长,直接截图的,没用LaTex解析)
- 因为输入的均值为0,可以得到:
- 所以:,代入上面即可。
- 因为之前,所以可以得到
❹
:
- 将
❸❹
代入到对权重w偏导❷
(即为梯度)的方差为: - 对于正向传播,我们希望:
- 对于反向传播,同样希望:
- 两种情况可以转化为:
❺
和❻
(比如第一种:
, ,所以 ,第二种情况同理) ❺❻
两式相加得:
- 最后提出了一个归一化的初始化方法,因为W服从均匀分布
U[-c,c]
,根据均匀分布的方差公式得:
- 所以:
- 求出,
- 所以◆◆最终给出初始化权重的方法为:
- 这就是Xavier初始化方法
- 参考论文:https://arxiv.org/pdf/1502.01852v1.pdf
- 或者查看这里,我放在github上了:https://github.com/lawlite19/DeepLearning_Python/blob/master/paper/Delving%20Deep%20into%20Rectifiers%20Surpassing%20Human-Level%20Performance%20on%20ImageNet%20Classification%EF%BC%88S%E5%9E%8B%E5%87%BD%E6%95%B0%E6%9D%83%E9%87%8D%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%89.pdf
- 目前
ReLu
激活函数使用比较多,而上面一篇论文没有讨论,如果还是使用同样初始化权重的方法(Xavier初始化)会有问题 - PReLu函数定义如下:
- 等价于:
- ReLu(左)和PReLu(右)激活函数图像
- 符号说明
- ε……………………………………目标函数
- μ……………………………………动量
- α……………………………………学习率
- f()………………………………激励函数
- l……………………………………当前层
- L……………………………………神经网络总层数
- k……………………………………过滤器
filter
的大小 - c……………………………………输入通道个数
- x……………………………………
k^2c*1
的向量 - d……………………………………过滤器
filter
的个数 - b……………………………………偏置向量
- ..............................................................(1)
- 根据式
(1)
得:
..................................................(2) - 因为初始化权重
w
均值为0,所以期望:,方差: - 根据式
(2)
继续推导:
............................................(3) - 对于
x
来说:,除非x
的均值也是0, - 对于
ReLu
函数来说:,所以不可能均值为0 w
满足对称区间的分布,并且偏置,所以也满足对称区间的分布,所以:
..........................................(4)- 将上式
(4)
代入(3)
中得:
.......................................................(5) - 所以对于
L
层:
.....................................................................(6) - 从上式可以看出,因为累乘的存在,若是,每次累乘都会使方差缩小,若是大于
1
,每次会使方差当大。 - 所以我们希望:
- 所以初始化方法为:是
w
满足均值为0,标准差为的高斯分布,同时偏置初始化为0
-
对于正向和反向两种初始化权重的方式都是可以的,论文中的模型都能够收敛
-
所以也不是逐渐缩小的
-
实验给出了与第一篇论文的比较,如下图所示,当神经网络有30层时,Xavier初始化权重的方法(第一篇论文中的方法)已经不能收敛。
-
当
a=0
时就是对应的ReLu激励函数 -
当
a=1
是就是对应线性函数
- 参考论文:http://jmlr.org/proceedings/papers/v37/ioffe15.pdf
- 或者查看这里,我放在github上了:https://github.com/lawlite19/DeepLearning_Python/blob/master/paper/%EF%BC%88BN%EF%BC%89Batch%20Normalization%20Accelerating%20Deep%20Network%20Training%20by%20Reducing%20Internal%20Covariate%20Shift.pdf
- 2015年Google提出的Batch Normalization
- 训练深层的神经网络很复杂,因为训练时每一层输入的分布在变化,导致训练过程中的饱和,称这种现象为:
internal covariate shift
- 需要降低学习率Learning Rate和注意参数的初始化
- 论文中提出的方法是对于每一个小的训练batch都进行标准化(正态化)
- 允许使用较大的学习率
- 不必太关心初始化的问题
- 同时一些例子中不需要使用
Dropout
方法避免过拟合 - 此方法在
ImageNet classification
比赛中获得4.82% top-5
的测试错误率
-
如果输入数据是白化的(whitened),网络会更快的收敛
-
白化目的是降低数据的冗余性和特征的相关性,例如通过线性变换使数据为0均值和单位方差
-
并非直接标准化每一层那么简单,如果不考虑归一化的影响,可能会降低梯度下降的影响
-
标准化与某个样本和所有样本都有关系
-
解决上面的问题,我们希望对于任何参数值,都要满足想要的分布;
-
这样做的计算代价是非常大的,因为需要计算x的协方差矩阵
-
上面两种都不行或是不好,进而得到了BN的方法
-
既然白化每一层的输入代价非常大,我们可以进行简化
-
简化1
-
标准化特征的每一个维度而不是去标准化所有的特征,这样就不用求协方差矩阵了
-
标准化之后均值为0,方差为1,数据就会落在近似线性的函数区域内,这样激活函数的意义就不明显
-
从式子来看就是对标准化的数据进行缩放和平移,不至于使数据落在线性区域内,增加数据的表达能力(式子中如果:, ,就会使恢复到原来的值了)
-
但是这里还是使用的全部的数据集,但是如果使用随机梯度下降,可以选取一个batch进行训练
-
简化2
-
第二种简化就是使用
mini-batch
进行随机梯度下降
-
注意这里使用
mini-batch
也是标准化每一个维度上的特征,而不是所有的特征一起,因为若果mini-batch
中的数据量小于特征的维度时,会产生奇异协方差矩阵, 对应的行列式的值为0,非满秩 -
假设mini-batch 大小为
m
的B
-
算法中的
ε
是一个常量,为了保证数值的稳定性 -
反向传播求梯度:
-
对于BN变换是可微分的,随着网络的训练,网络层可以持续学到输入的分布。
- 按照BN方法,输入数据
x
会经过变化得到BN(x)
,然后可以通过随机梯度下降进行训练,标准化是在mini-batch上所以是非常高效的。 - 但是对于推断我们希望输出只取决于输入,而对于输入只有一个实例数据,无法得到
mini-batch
的其他实例,就无法求对应的均值和方差了。 - 可以通过从所有训练实例中获得的统计量来代替mini-batch中m个训练实例获得统计量均值和方差
- 我们对每个
mini-batch
做标准化,可以对记住每个mini-batch
的B,然后得到全局统计量 - (这里方差采用的是无偏方差估计)
- 所以推断采用
BN
的方式为: - 作者给出的完整算法: