感知机
1943年,心理学家W.S.McCulloch和数理逻辑学家W.Pitts基于神经元的生理特征,建立了单个神经元的数学模型(MP模型)
实际上没啥依据
1957年,Frank Rosenblatt从纯数学的度重新考察这一模型,指出能够从一些输入输出对 中通过学习算法获得权重w和b 。(这被认为是第一个机器学习算法,SVM是90年代的算法)
问题:给定一些输入输出对(x,y),其中y=±1,求一个函数,使:f(x)=y
感知机算法:设定f(x)=sign(wTx+b),从一堆输入输出中自动学习,获得权重w和b 。
感知器算法(Perceptron Algorithm):
对于样本数据(x,y)
- 随机选取w和b
- 取一个训练样本(xi,yi),
- 若wTxi+b>0且yi=−1,则:w=w−xi,b=b−1
- 若wTxi+b<0且yi=+1,则:w=w+xi,b=b+1
- 再取另外一个(xi,yi),回到(2)
- 终止条件:直到所有输入和输出对都不满足(2)中的任意一条,退出循环
关于调整w和b 的一点点直观的解释:(和梯度下降法推导出来的不同,这里是原论文的方法,比较naive)
若wTx+b>0且y=−1,则:w=w−x,b=b−1,于是有:
w新Tx+b新=(w−x)Tx+b−1=(wTx+b)−(∥x∥2+1)
(∥x∥2+1)是大于1的正数,它会把wTx+b往负的方向调整。
wTx+b<0时同理
Frank Rosenblatt从数学上证明了,若数据集线性可分,那么以上的算法一定会收敛,下图是感知机在二维特征空间画出的一条直线
注意,感知机画出的直线与SVM有很大不同。感知机画出的直线只是做到了划分正负样本,而没有像SVM那样有最大的margin(毕竟SVM是90年代的东西,感知机早了将近半个世纪)
感知机算法收敛定理
刚刚我们提到了,Frank Rosenblatt从数学上证明了,若数据集线性可分,那么感知机算法一定会收敛。下面我们加以证明:
首先,为下面证明过程书写方便,
定义增广矩阵X:
- 若y=+1,则X=[x1]
- 若y=−1,则X=[−x−1]
定义增广矩阵W=[wb]
然后我们重写感知机算法:
对于样本数据X
- 随机选取W
- 取一个训练样本Xi
- 若WTXi<0且yi=−1,则:W=W+Xi
- 再取另外一个Xi,回到(2)
- 终止条件:直到所有输入和输出对都不满足(2)中的任意一条,退出循环
感知机算法收敛定理:
若样本数据集{Xi}i∼N线性可分,即∃Wopt,使
WoptTXi>0(i=1∼N)
则利用上述感知机算法,经过有限步后,得到一个W,使
WTXi>0(i=1∼N)
proof:不失一般性,设∥Wopt∥=1,假设第k步时的W是W(k),且有一个Xi使得W(k)TXi<0。根据感知机算法可以推导出:
W(k+1)=W(k)+Xi→∥W(k+1)−aWopt∥2=∥W(k)−aWopt+Xi∥2∥W(k)−aWopt+Xi∥2=∥W(k)−aWopt∥2+∥Xi∥2+2W(k)TXi−2aWoptTXi
注意到W(k)TXi<0以及WoptTXi>0,则一定可以取很大的a,使得
∥W(k+1)−aWopt∥2<∥W(k)−aWopt∥2
定义:β=i=1∼Nmax{∥Xi∥},γ=i=1∼Nmin{WoptTXi},取a=2γβ2+1,则∥W(k+1)−aWopt∥2<∥W(k)−aWopt∥2−1
取D=∥W(0)−aWopt∥,则至多经过D2步,W将会收敛至aWopt
注意是在条件W(k)TXi<0下,才有W将会收敛至aWopt,而通常情况下这个条件很快就会消失。这个证明的意思是,若数据线性可分,并且很难线性划分,Wopt几乎是唯一划分的选择,那么感知机最终也会收敛到Wopt这个决策平面
多层神经网络
1969年,Minsky指出了感知机没办法处理非线性可分的数据,在日常生活中很多分类问题是非线性的,人工智能进入了第一次冬天。
在80年代,人们创造了多层神经网络(Multiple Layer Neural Networks),从而可以实现对非线性可分数据集的分类,人工智能从新复苏。
下面是一个两层神经网络的例子:
若φ(⋅)为线性函数,则多层神经网络和单层没有区别
定理:当φ(x)=u(x)(即阶跃函数)时,三层网络可以模拟任意决策面
反向传播算法
反向传播算法(Back Propogation Algorithm):从后往前计算各个参数的偏导数,然后使用梯度下降法对模型进行训练,最终达到收敛。
以上图为例:
首先定义误差函数:E=21(y−Y)2,其中y为前向传播计算出的模型输出,Y为数据标签,优化目标为最小化E
模型中代求的偏导数为:
∂w1∂E=dydE∂w1∂y=(y−Y)z1∂w2∂E=dydE∂w2∂y=(y−Y)z2∂w11∂E=dydE∂z1∂yda1dz1∂ω11∂a1=(y−Y)ω1φ′(a1)x1∂w12∂E=dydE∂z1∂yda1dz1∂ω12∂a1=(y−Y)ω1φ′(a1)x2∂w21∂E=dydE∂z2∂yda2dz2∂ω21∂a2=(y−Y)ω2φ′(a2)x1∂w22∂E=dydE∂z2∂yda2dz2∂ω22∂a2=(y−Y)ω2φ′(a2)x2∂b1∂E=dydE∂z1∂yda1dz1∂b1∂a1=(y−Y)ω1φ′(a1)∂b2∂E=dydE∂z2∂yda2dz2∂b2∂a2=(y−Y)ω2φ′(a2)∂b3∂E=dydE∂b3∂y=(y−Y)
上面是一个小例子以帮助理解。
下面我们对反向传播算法进行向量化,并得到他的一般形式:
首先给出神经网络的向量化数学表达式
这是神经网络的第一层,记输入为x,x是一个N×1向量,N是输入特征的维数。
w(1)为第一层的参数矩阵:
w(1)=⎣⎢⎢⎢⎢⎡w11(1)w21(1)⋮wM1(1)w12(1)w22(1)wM2(1)⋯⋯⋯w1N(1)w2N(1)⋮wMN(1)⎦⎥⎥⎥⎥⎤
则有:
x⇒w(1)x+b(1)=z(1)φa(1)=φ(z(1))
关于维数和上下标的说明:b,z和a都是列向量,维数取决于这一层的行数,比如上图第一层有M个神经元,则b(1),z(1)和a(1)都是M维列向量;上标表示第几层,下标表示连接关系。例如wij(k)表示第(k−1)层的第j个输出到第(k)层的第i个神经元的参数。
PS:x=a(0)
那么多层神经网络就是上面的重复级联,每一层的行数不一定相等。为方便表示,我们默认一共有l层,则:
x⇒w(1)x+b(1)=z(1)φa(1)⇒w(2)a(1)+b(2)=z(2)φa(2)⇒⋯⋯⋯⋯⋯⋯⋯φa(l−1)⇒w(l)a(l−1)+b(l)=z(l)φa(l)=y
为方便计算,我们定义:δi(m)=∂zi(m)∂E
-
最后一层(m=l)
δi(l)=∂zi(l)∂E=∂yi∂E∂zi(l)∂yi=(yi−Yi)φ′(zi(l))
-
非最后一层(m=1∼l−1)
δi(m)=∂zi(m)∂E=∂ai(m)∂E∂zi(m)∂ai(m)=(j=1∑Sm+1∂ai(m+1)∂E)φ′(zi(m))=(j=1∑Sm+1wji(m+1)δj(m+1))φ′(zi(m))
这就是反向传播算法的名词由来,先计算最后的偏导数,再逐层向前推进
计算出δi(m)后,可以很方便计算出:
∂wij(m)∂E=∂zi(m)∂E∂wij(m)∂zi(m)=δi(m)aj(m−1)∂bi(m)∂E=∂zi(m)∂E∂bi(m)∂zi(m)=∂zi(m)∂E=δi(m)
BP算法:
-
随机初始化(w,b)
-
训练样本(x,Y),输入网络前向传播可求出所有的(z,a,y)
-
通过上述迭代方法计算出(∂wij(m)∂E,∂bi(m)∂E)
-
更新:
w(新)b(新)=w(旧)−α∂w∂E∣w(旧)=b(旧)−α∂b∂E∣b(旧)
-
回到(2),跳出循环条件:(∂wij(m)∂E,∂bi(m)∂E)足够小,或者E足够小
这是通过反向传播算法(BP算法)训练多层神经网络的基本方法,但是训练多层神经网络特别是深层神经网络是个错综复杂的问题,下面会讨论到。
激活函数φ(⋅)的选择
若使用感知机的激活函数φ(x)=u(x),则φ′(x)≡0(不考虑奇异函数,在x=0不可导就当x=0无定义)
由于φ′(x)≡0导致使用反向传播算法计算出来的关于各个参数的偏导数为0,则没有办法用梯度下降法优化模型,因此必须更换激活函数φ(⋅)
-
sigmoid函数
φ(x)φ′(x)=1+e−x1=φ(x)[1−φ(x)]
sigmoid函数是阶跃函数的模拟,并且做到了处处可导。
-
tanh函数
φ(x)φ′(x)=tanh(x)=ex+e−xex−e−x=1−φ2(x)
以上的激活函数都有一个问题,就是在x远离原点处的导数为0,这在深度网络的反向传播中通常会出现梯度消失(弥散)的现象,导致深层网络难以训练的问题。因此在深度学习出现以后,常常采用以下激活函数。
-
ReLU函数
修正线性单元(Rectify Linear Units)
φ(x)φ′(x)={x,x>00,x⩽0=max{0,x}={1,x>00,x<0
在x>0时的梯度弥散现象得到解决,但x<0时仍然存在梯度弥散现象
-
Leak ReLU函数
φ(x)φ′(x)={x,x>0βx,x⩽0={1,x>0β,x<0
神经网络参数设置方法
随机梯度下降
随机梯度(Stochastic Gradient Descent, SGD)
- 不用每输入一个样本就去变换参数,而是输入一批样本(叫做一个BATCH或MINI-BATCH),求出这些样本的梯度平均值后,根据这个平均值改变参数。(GD是BATCH为1的SGD)
- 在神经网络训练中,BATCH的样本数大致设置为50-200不等。
激活函数选择
训练数据初始化
标准差std也可以用(max−min)来代替
(w,b)的初始化
梯度消失现象:如果wTx+b一开始很大或很小,那么梯度将趋近于0,反向传播后前面与之相关的梯度也趋近于0,导致训练缓慢。 因此,我们要使wTx+b一开始在零附近。
一种比较简单有效的方法是:(w,b)初始化从区间(−d1,d1)均匀随机取值。其中d为(w,b)所在层的神经元个数。
可以证明,如果x服从正态分布,均值0,方差1,且各个维度无关,而(w,b)是(−d1,d1)的均匀分布,则wTx+b是均值为0, 方差为1/3的正态分布。
参数初始化是一个研究热点领域
Batch normalization
论文:Batch normalization accelerating deep network training by reducing internal covariate shift (2015)
基本思想:既然我们希望每一层获得的值都在0附近,从而避免梯度消失现象,那么我们为什么不直接把每一层的值做基于均值和方差的归一化呢?
对γ和β的说明:以sigmoid和tanh为例,若归一化后的样本过于聚集在0附近,则激活函数对外表现出几乎的线性,这是我们不希望看到的。因此增加了γ和β两个待学习的参数,使归一化在避免梯度消失和失去非线性中权衡。
目标函数选择
- 可加正则项 (Regulation Term)
L(w)=F(w)+R(w)=21(i=1∑batchsize∥yi−Yi∥2+βk∑l∑wk,l2)
-
如果是分类问题,F(w)可以采用Softmax函数和交叉熵的组合
(a)Softmax函数
qi=∑j=1Nexp(zj)exp(zi),i=1∑Nqi=1
(b)交叉熵(Cross Entropy)
E=−i=1∑NYilog(yi)
交叉熵可以作为误差函数,上面我们使用的误差函数为MSE,即E=21∑i=1N∥yi−Yi∥2。对于交叉熵,当p和q的分布越相近时,E的值越小。
综上,我们可以使用Softmax函数和交叉熵的组合作为目标函数:
E=−i=1∑Npilog(qi)
并且它的求导将会有非常简单的形式:∂zi∂E=qi−pi
参数更新策略
- 常规的更新 (Vanilla Stochastic Gradient Descent)
1 2
| nn.W{k} = nn.W{k} - nn.learning_rate*nn.W_grad{k}; nn.b{k} = nn.b{k} - nn.learning_rate*nn.b_grad{k};
|
SGD的问题:
(1)(w,b)的每一个分量获得的梯度绝对值有大有小,一些情况下,将会迫使优化路径变成Z字形状
(2)SGD求梯度的策略过于随机,由于上一次和下一次用的是完全不同的BATCH数据,将会出现优化的方向随机的情况。
-
AdaGrad(解决各个方向梯度不一致问题)
基本思想是:(1)引入了累计梯度的思想,希望这个梯度可以受过去梯度的影响;(2)对每一个梯度做了均值化,原来梯度大的地方变小一些,原来梯度小的地方放大一些,避免Z字形下降。
-
RMSProp(解决各个方向梯度不一致问题)
与AdaGrad唯一的区别是γ←ργ+(1−ρ)g⊙g,引入了一个新的参数ρ用于权衡过去梯度和现在梯度的权值
-
Momentum(解决梯度随机性问题)
1 2 3 4 5 6
| nn.vW{k} = 0.5*nn.vW{k} + nn.learning_rate*nn.W_grad{k}; nn.vb{k} = 0.5*nn.vb{k} + nn.learning_rate*nn.b_grad{k}; nn.W{k} = nn.W{k} - nn.vW{k}; nn.b{k} = nn.b{k} - nn.vb{k};
|
Momentum(动量)考虑了上一个梯度的对当前梯度的影响(AdaGrad和RMSProp考虑的是累计梯度对当前梯度的影响,没有Momentum那么有“冲劲”)
-
Adam(同时解决两个问题)
r是累计梯度,作为△Θ的分母可以解决各个方向梯度不一致;s是动量梯度,作为△Θ的分子可以解决梯度随机性问题
训练建议
(1)一般情况下,在训练集上的目标函数的平均值(cost)会随着训练的深入而不断减小,如果这个指标有增大情况,停下来。有两种情况:第一是采用的模型不够复杂,以致于不能在训练集上完全拟合;第二是已经训练很好了。
(2)分出一些验证集(Validation Set),训练的本质目标是在验证集上获取最大的识别率。因此训练一段时间后,必须在验证集上测试识别率,保存使验证集上识别率最大的模型参数,作为最后结果。
(3)注意调整学习率(Learning Rate),如果刚训练几步cost就增加,一般来说是学习率太高了;如果每次cost变化很小,说明学习率太低。
(4) Batch Normalization 比较好用,用了这个后,对学习率、参数更新策略等不敏感。建议如果用Batch Normalization, 更新策略用最简单的SGD即可,我的经验是加上其他反而不好。
(5)如果不用Batch Normalization, 我的经验是,合理变换其他参数组合,也可以达到目的。
(6)由于梯度累积效应,AdaGrad, RMSProp, Adam三种更新策略到了训练的后期会很慢,可以采用提高学习率的策略来补偿这一效应。