机器学习之神经网络

引言

在机器学习领域,主要存在着两大流派,一派是统计学习方法,一派就是神经网络。统计学习方法大多具有严谨的数学推理,模型都有很完备的数学解释,像是SVM,就是通过核把非线性问题映射到高维空间变为线性问题。而神经网络则不然,一直没有找到合理的数学解释,迄今为止都属于实验推动,虽然说是思想来源于人类的神经元的模拟,但是没有数学解释垫背,终究没有那么大的底气。

神经网络在1943年就已经被提出了,然而直到1969年提出了感知机的概念,才算是烧出了第一块砖。然而感知机毕竟只是一块砖,力量太过于薄弱了,处理线性可分的问题都好说,遇到非线性可分的问题就呵呵,包括最基本的异或问题都搞不定。后来人们尝试着把感知机组合起来生成神经网络,并且在1986年发明了反向传播算法,这样就形成了神经网络的早期的基石。随后人们不断尝试着把网络一层一层的加深,形成深度网络,然而由于梯度消失等问题,早期的深度网络存在极大的问题。屋漏偏逢连夜雨,Vapnik大神搞出了SVM,效果出奇的好,直接秒杀了早期的神经网络,致使神经网络的发展进入了低潮期。2006年Hinton横空出世, 提出了深度神经网络,利用受限玻尔兹曼机通过非监督学习的方式学习网络结构,然后利用反向传播算法学习网络内部的参数值,后面经过几位大神的推广和发展,导致如今深度学习遍地开花,硕果累累。

下面我们首先介绍感知机,然后通过感知机引出早期的神经网络,最后介绍反向传播算法是如何训练学习神经网络的。

感知机

感知机的详细定义可以参见维基百科,这里感知机其实就是一个给定输入空间,能够映射到输出空间{0,1}的函数。具体的形式如下图所示:

机器学习之神经网络

给定输入,可以产生一个指定的二进制输出,其数学公式如下:

output={0,ifjwjxjthresholds1,ifjwjxj>thresholds

用向量的方式表示的话,则可以简化为下面的格式:

output={0,if wx+b01,if wx+b>0

通过将过个感知机组合,可以形成感知机网络,如图所示,通过对上面的参数的学习,可以利用此感知机做决策。

机器学习之神经网络

S型神经元

上面介绍了感知机,但是如果输出结果只是0,1的话,那么这个好像不怎么好用啊,同时细微的参数变动有可能会引起结果的反转,这个模型就非常不理想了,因此引入S型神经元。

机器学习之神经网络

所谓的S型神经元就是输出函数为σ的感知机,函数如下所示:

σ=11+ez

其中

z=jwjxj+b

下图是S型神经元的函数形状,我们可以看到,sigmoid函数具有很优良的性质,首先他的输出可以是0到1之间的连续值,其次当我们选定阈值时,S型神经元可以退化为感知机。这是一个优良的数学模型。

机器学习之神经网络

神经网络

通过将多个S型神经元组合到一起,就搭建成了一个初步的神经网络,如下所示,其中input layer为输入层,output layer为输出层,中间的所有的层为隐藏层,所有的单节点都是一个S型神经元。

机器学习之神经网络

当然我们也可以构建多个输出的网络,如下所示:

机器学习之神经网络

给定了神经网络的架构,那么我们就可以很自然的通过给定输入然后得到相应的输出结果,那么现在还剩下一个问题,我们怎样去通过调整神经网络的参数来得到我们想要的结果呢?大神们已经为我们准备好了工具,那就是梯度下降算法。

代价函数

在介绍梯度下降算法之前,首先需要考虑一个问题,有了神经网络模型,给定了输入,可以得到输出,那么我们怎样去衡量输出的好坏呢?因此需要有个度量标准,这个度量标准就是代价函数。所谓的代价函数,就是衡量输出结果好坏的一个度量,一般我们可以定义下面的一个代价函数

C(w,b)=12nx||y(x)a||2

其中w表示网络中权重的集合, b表示偏置,n 是训练样本的个数,axy(x)$ 表示神经网络的输出。

因此我们希望的训练得到的模型就是使代价函数最小的模型,也就是说通过修改wb的值,使得输出结果与实际结果的误差总和最小。

梯度下降算法

通过上面的分析,我们可以得出结论,神经网络的训练问题实际上本质就是一个最小化函数C(w,b) 的问题。下面我们先通过一个二维的模型来讨论函数的最小化问题。

机器学习之神经网络

在上面的函数中,我们可以一眼看到函数的最小值在哪里。但是如果我们没有画出函数的几何形状呢,我们要如何找到函数的最小值点呢?

我们可以这样想,当我们沿着v1v2的方向分别移动一个很小的量Δv1Δv2,那么根据微积分,我们可以得到下面的函数:

ΔCCv1Δv1+Cv2Δv2

(上面的函数省略掉了二阶偏导,不过不重要。)

那么只要找到一个选择v1v2的方法使ΔC为负,那么就可以保证函数一直是减小的,那么最终函数一定能到达到最小值(其实很多情况下是局部最小值)。

定义C的偏导如下:

C=(Cv1,Cv2)

定义:

Δv=(Δv1,Δv2)T

则:

ΔC=CΔv

如果令

Δv=ηC

那么

ΔC=η||C||2
,只要保证η为正数,那么ΔC0

因此可以使v沿着Δv的方向移动,就可以得到最小值。即:

vv=vηv

将上面的二维函数扩展到多为函数,则可以得到相同的结论,即

vv=vηv

其中

Δv=ηC

C=(Cv1,......,Cvm)

Δv=(Δv1,......,Δvm)T

将上面的函数拓展到我们的神经网络中,可以得到下面的公式

wkwk=wkηCwk

blbl=blηCbl

上面的两个公式就是梯度下降算法。只要我们沿着梯度下降的方向更新wb的值,那么就能够最小化代价函数。

通过我们不懈的努力,我们最终找到了更新神经网络的参数的方法,那么现在又有一个问题了,怎么计算CwkCbl呢? 这又是一个难办的问题了。但是大神们依旧给我们解决了,那就是反向传播算法。

反向传播算法

神经元的误差

在介绍反向传播算法之前,首先明确几个小概念,

第一个就是下图

机器学习之神经网络

理解了wjkl,有助于我们下面的公式推导。

第二个就是神经元的**值ajl,如下图所示

机器学习之神经网络

其中,lth层的第jth个神经元的**值ajl就和(l1)th 层的**值通过下面的方程可以关联起来了

ajl=σ(kwjklakl1+bjl)

第三,我们还要引入一个重要的概念:
即第lth层的第jth个神经元上的误差δjl

定义δjl=Czjl

其中zjl=kwjklakl1+bjl

为何要引入这个误差呢?请看下图:

机器学习之神经网络

假设在lth 层的第jth个神经元上有输入进来时,有个扰动,他会增加很小的变化Δzjl 在神经元的带权输入上,使得神经元输出由σ(zjl)变成σ(zjl+Δzjl),
这个变化会向网络后面的层进行传播,最终导致整个代价产生CzjlΔzjl 的改变,因此Czjl是神经元误差的一种度量。

有了神经元的误差的概念,我们就可以逐步推导出反向传播算法的四个方程,进而能够逐步求得神经网络的权重和阈值的偏导,解决权重和阈值的更新问题。

反向传播的四个方程

我们首先列出反向传播的四个方程,然后在逐一证明这四个方程

机器学习之神经网络

首先对于(BP1),首先通过定义

δjl=Czjl

由链式求导法则,可以得到:

δjL=kCakLakLzjL

求和是在输出层的所有k 个神经元上运行的, 但是我们可以注意到第kth 个神经元的**值akL只跟k=j j^{th} z^{L}{j} , k \neq j \frac{\partial a^{L}{k}}{\partial z^{L}_{j}} $ 为0,因此可以得到下面的方程:

δjL=CajLajLzjL

ajl=σ(zjL)
,所以可以得到下面的方程:

δjL=CajLσ(zjL)

输出成向量的格式,即为:

δL=aCσ(zL)

对于(BP2),通过链式求导法则,可得到:

δjl=Czjl=kCzkl+1zkl+1zjl=kzkl+1zjlδkl+1

zkl+1=jwkjl+1ajl+bkl+1=jwkjl+1σ(zjl)+bkl+1

所以

zkl+1zjl=wkjl+1σ(zjl)

所以可以得到:

δjl=kwkjl+1δkl+1σ(zjl)

转换为向量表示即为:

δl=(wl+1(δl+1)T)σ(zl)

对于(BP3)

δjl=Czjl=Cbjlbjlzjl

zjl=jwkjlajl1+bkl

所以

zjlbjl=1

因此方程成立

对于(BP4),通过链式求导法则

δjl=Czjl=Cwjklwjklzjl

zjl=jwkjlajl1+bkl

所以

zjlwjkl=akl1

所以可以得到:

Cwjkl=akl1δjl

自此,四个方程证明完毕。

有个上面的四个方程作为支撑,我们就可以得出反向传播算法了,如下所示:

机器学习之神经网络

反向传播算法从最后一层开始计算误差,然后根据误差不断向前反馈优化每一层的权重,进而调整整个网络的权重。其实这和自动控制里面的反馈有着同样的哲学原理。

神经网络权重的更新算法

有了上面的梯度下降算法以及反向传播算法,我们就可以得到神经网络的权重的更新算法,具体算法如下所示:

机器学习之神经网络
算法中有一点需要注意的是:
这里的梯度下降,我们用的是随机梯度下降算法。思想就是随机选取小批量的训练样本来计算梯度,因为如果针对全部的训练数据进行梯度下降的话,会比较耗时,随机梯度下降能够加速学习,本质上讲,就是用部分随机选取的数据替代全量数据。

拓展

关于神经元的选择

本文中我们选用了sigmoid函数,也就是S型神经元,实际上还有很多种神经元可以选择,不同的神经元对于不同的问题可能会有更好的效果,因此具体问题需要具体分析。本质上讲sigmoid函数并不是很好,因为我们可以看到sigmoid函数的值域是[0,1],这也就意味着对于同一神经元的所有权重要么同时增加,要么同时减少,这样会造成一定的偏置。

关于代价函数

本文中我们用到的的二次代价函数,实际上也是有很多的代价函数可供选择的,一样的需要具体问题具体分析选用那种代价函数,二次代价函数是比较简单的一种,也是比较有效的一种。但是坦率的讲,选用不同的代价函数会对学习效率有较大的影响,这个后面我们会进行详细的分析。

关于过拟合问题

本文没有涉及过拟合问题,实际上这是机器学习面对的一个大问题,如果发生了过拟合,那么会导致网络的泛化能力变差,也就是在训练数据集上效果非常好,在测试数据集上表现糟糕。后面博客会详细分析这一问题。

深度神经网络

我们知道上古时代就已经发明了神经网络,在远古时代,反向传播算法也已经被发明出来了,那么为何直到近几年深度网络才火起来呢?这是一个问题。后续的博文会讲到为何中古时代大家都没有用到深度神经网络,他们遇到了什么样的问题,这些问题又是怎样解决的。