数据挖掘入门系列教程(七点五)之神经网络介绍

数据挖掘入门系列教程(七点五)之神经网络介绍

这篇博客是是为了下一篇博客“使用神经网络破解验证码”做准备。主要是对神经网络的原理做介绍。同时这篇博客主要是参考了西瓜书,如果身边有西瓜书的同学,强烈建议直接去看西瓜书,至于我这篇博客,你就当个乐子好了(因为你会发现内容与西瓜书很相似)。

简介

什么是神经网络(Neural Network,NN)【亦可称之为人工神经网络(Artificial Neural Network,ANN)】,首先它是一门重要的机器学习技术,也是深度学习的基础,是一种模拟生物神经网络结构和功能的数学模型或者计算机模型。

在神经网络中,最基本的成分是神经元(neuron)模型。在生物模型中,每一个神经元与其他神经元相连,当他“兴奋”时,他会向其他的神经元发送化学物质,从而改变其他神经元的电位,如果其他神经元的电位超过了某些"阈值""(threshold),那么其他神经元也会“激活“兴奋,继续向其所连接的神经元发送化学物质。

下面是生物中神经元的模型(感觉又回到了高中时代):

沃伦·麦卡洛克(生物学)和沃尔特·皮茨(逻辑学)在1943年基于数学和一种称为阈值逻辑的算法创造了一种神经网络的计算模型(也就是神经元MP模型)。这种模型使得神经网络的研究分裂为两种不同研究思路。一种主要关注大脑中的生物学过程,另一种主要关注神经网络在人工智能里的应用。

依照生物的模型,两位科学家对其工作原理和机构进行简化和抽象构建了M-P模型,下面来介绍一下M-P模型。

M-P 模型

M-P,emm,就是上面两位科学家的命名(McCulloch-Pitts)。M-P模型如下:

上面的模型能够很容易的理解:在这个模型中,神经元接收到来自(n)个其他神经元传递过来的输入信号(x_i),这些输入信号通过带权重((w_i))的连接( connection)进行传递,神经元接收到的总输入值将与神经元的阀值进行比较,然后通过"激活函数" (activation function) 处理以产生神经元的输出。前面的都能够很简单的理解,那么,问题来了,”激活函数“是什么?

一种是如下图的阶跃函数,它将输入值映射为输出值”0“,”1“。0对应神经元抑制,1对应神经元兴奋,这个和生物中很相似,但是它具有不连续,不光滑等性质。

因此,实际上常用Sigmoid函数作为激活函数,Sigmoid函数如下图所示:它把输入值压缩在(0,1)的输出范围内。因此也被称之为“挤压函数”。

然后我们将这样的神经元按照一定的层次结构连接起来,就得到了神经网络。

感知机(两层神经网络)

感知机模型如下所示,输入层接受外部输入信号然后传递给输出层,输出层则就是M-P模型。其中(y_k=fleft(sum_{i} w_{(k,i)} x_{i}-theta_iright))。感知机能够很容易的实现“与,或,非”运算。

也就是说给定一定的数据集((x_i,y_k)),如果我们知道权重(w_i)和阈值(theta),那么我们就可以得到(x)(y)之间的关系(比如说在分类中,对于物体的属性(x_1,x_2…x_i),我们可以的到物体的类别(y_i))。对于阈值来说,我们可以把它看成由一个“哑节点(值为-1.0)”乘以权重(w_{n+1})得到。因此,权重和阈值的学习可以统一为权重的学习。那么,怎样进行学习呢(也就是得到合适的权重值)?

权重学习

假设我们给定样例为((x,y)),当前感知机的输出为(hat{y}),则权重的调整如下:

[begin{aligned} &w_{i} leftarrow w_{i}+Delta w_{i}\ &Delta w_{i}=eta(y-hat{y}) x_{i} end{aligned} ]

其中(eta in(0,1))称之为学习率。若(hat{y}=y)则感知机不发生变化。

通过上面的部分我们知道,感知机只有输出层的神经元进行激活函数处理,即只有一层功能神经元,其学习能力很有限。当我们通过学习得到合适的权重时候,假如不考虑激活函数,则(y)的表达式可以写成下面的表达式:

[begin{aligned} y_k = sum_{i}^{n+1}(w_ix_i) \ n+1是因为其中里面有一个阈值theta end{aligned} ]

也就是说对于感知机,它只能够处理线性可分问题。可以证明若两类模式是线性可分的,即存在一个线性超平面能将它们分开,如下图所示,则感知机在学习过程一定会收敛 (converge) 而求得适当的权向量(boldsymbol{w}=left(w_{1} ; w_{2} ; ldots ; w_{n+1}right))

否则感知机学习过程将会发生震荡 (fluctuation) ,(w)难以稳定下来,不能求得合适解。例如对于下图中的异或问题就没办法求解。

多层神经网络(多层感知机)

要解决非线性可分问题,就需要使用多层神经网络。如下图所示,我们在中间添加了一层神经元,称之为隐层或者隐含层(hidden layer),该网络可称之为”单隐层网络“。隐含层与输出层的功能相似(都是功能神经元),都拥有激活函数。输入层接受数据的输入,隐层和输出层对数据进行函数处理。因此也可称之为”两层神经网络“,

因此,上面的异或问题便可以得到解决:

一般来说,神经网络是如下的结构,每一层神经元与下一层神经元全互联,同层之间不存在连接,也不存在跨层连接。称之为”多层前馈神经网络“(这里的前馈代表的是指网络拓扑结构中不存在环或者回路,不代表信号不能向后传播)。

在M-P模型中我们说过,对于神经网络的学习,我们可以看成是连接权(connection weight)(也就是神经元之间连接的权重)和阈值的学习。那么在多层神经网络中,又怎样得到合适的阈值和连接权呢?

连接权学习——BP算法

对于多层神经网络的连接权的学习,前面B-P模型的学习算法肯定是不行的。因此需要新的算法,而误差逆传播(error BackPropagation,简称BP)算法便是一个很有效(迄今为止最成功)的算法。

假设我们的多层前馈神经网络如下所示,其中隐层第(h)个神经元的阈值使用(gamma_h)表示,输出层第(j)个神经元的阈值使用(theta_j)表示,(b_h)表示隐层第(h)个神经元的输出。其中激活函数都使用(Sigmoid)函数。

在下图中,我们可以很容易的得出一共有(qtimes d + q + q times l + l = qtimes(d + l + 1) +l)个参数需要确定。

给定训练例子(left(boldsymbol{x}_{k}, boldsymbol{y}_{k}right)),假设神经网络的输出为(hat{boldsymbol{y}}_{k}=left(hat{y}_{1}^{k}, hat{y}_{2}^{k}, ldots, hat{y}_{l}^{k}right)),即

[hat{y}_{j}^{k}=fleft(beta_{j}-theta_{j}right) ]

则网络在(hat{boldsymbol{y}}_{k}=left(hat{y}_{1}^{k}, hat{y}_{2}^{k}, ldots, hat{y}_{l}^{k}right))的均方误差(也就是损失函数loss function)是:

[E_{k}=frac{1}{2} sum_{j=1}^{l}left(hat{y}_{j}^{k}-y_{j}^{k}right)^{2} ]

设任意参数(v)的更新估计式如下:

[v leftarrow v+Delta v ]

BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整。对于均方误差,给定学习率(eta),有:

[begin{equation}Delta w_{h j}=-eta frac{partial E_{k}}{partial w_{h j}}end{equation} ]

对于(w_{hj}),它先影响第(j)个输出层神经元的输入(beta_{j}),然后再影响输出值(hat{y}_{j}^{k}),最后影响(E_k),根据导数的规律,有:

[begin{equation} frac{partial E_{k}}{partial w_{h j}}=frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} cdot frac{partial beta_{j}}{partial w_{h j}} \ end{equation} ]

然后对于(beta_{j})有:

[frac{partial beta_{j}}{partial w_{h j}}=b_{h} ]

对于对于(Sigmoid)函数有:

[f^{prime}(x)=f(x)(1-f(x)) ]

[begin{equation}begin{aligned} &because hat{y}_{j}^{k}=fleft(beta_{j}-theta_{j}right)\ &because E_{k}=frac{1}{2} sum_{j=1}^{l}left(hat{y}_{j}^{k}-y_{j}^{k}right)^{2} \ therefore g_{j} &=-frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} \ &=-left(hat{y}_{j}^{k}-y_{j}^{k}right) f^{prime}left(beta_{j}-theta_{j}right) \ &=(y_{j}^{k}-hat{y}_{j}^{k})hat{y}_{j}^{k}(1-hat{y}_{j}^{k}) end{aligned}end{equation} ]

所以对于(Delta w_{h j}),有:

[begin{equation}Delta w_{h j}=eta g_{j} b_{h}end{equation} ]

同理对于(Delta theta_{j}),有:

[begin{equation}Delta theta_{j}=-eta frac{partial E_{k}}{partial theta_{j}}end{equation} ]

又:

[begin{equation}begin{aligned} frac{partial E_{k}}{partial theta_{j}} &=frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial theta_{j}} \ &=frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partialleft[fleft(beta_{j}-theta_{j}right)right]}{partial theta_{j}} \ &=frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot f^{prime}left(beta_{j}-theta_{j}right) times(-1) \ &=frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot fleft(beta_{j}-theta_{j}right) timesleft[1-fleft(beta_{j}-theta_{j}right)right] times(-1) \ &=frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot hat{y}_{j}^{k}left(1-hat{y}_{j}^{k}right) times(-1) \ &=frac{partialleft[frac{1}{2} sum_{j=1}^{l}left(hat{y}_{j}^{k}-y_{j}^{k}right)^{2}right]}{partial hat{y}_{j}^{k}} cdot hat{y}_{j}^{k}left(1-hat{y}_{j}^{k}right) times(-1) \ &=frac{1}{2} times 2left(hat{y}_{j}^{k}-y_{j}^{k}right) times 1 cdot hat{y}_{j}^{k}left(1-hat{y}_{j}^{k}right) times(-1) \ &=left(y_{j}^{k}-hat{y}_{j}^{k}right) hat{y}_{j}^{k}left(1-hat{y}_{j}^{k}right) \ &=g_{j} end{aligned}end{equation} ]

所以:

[begin{equation}Delta theta_{j}=-eta frac{partial E_{k}}{partial theta_{j}}=-eta g_{j}end{equation} ]

对于(Delta v_{i h}),因为:

[begin{equation}Delta v_{i h}=-eta frac{partial E_{k}}{partial v_{i h}}end{equation} ]

所以:

[begin{equation}begin{aligned} frac{partial E_{k}}{partial v_{i h}} &=sum_{j=1}^{l} frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} cdot frac{partial beta_{j}}{partial b_{h}} cdot frac{partial b_{h}}{partial alpha_{h}} cdot frac{partial alpha_{h}}{partial v_{i h}} \ &=sum_{j=1}^{l} frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} cdot frac{partial beta_{j}}{partial b_{h}} cdot frac{partial b_{h}}{partial alpha_{h}} cdot x_{i} \ &=sum_{j=1}^{l} frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} cdot frac{partial beta_{j}}{partial b_{h}} cdot f^{prime}left(alpha_{h}-gamma_{h}right) cdot x_{i} \ &=sum_{j=1}^{l} frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} cdot w_{h j} cdot f^{prime}left(alpha_{h}-gamma_{h}right) cdot x_{i} \ &=sum_{j=1}^{l}left(-g_{j}right) cdot w_{h j} cdot f^{prime}left(alpha_{h}-gamma_{h}right) cdot x_{i} \ &=-f^{prime}left(alpha_{h}-gamma_{h}right) cdot sum_{j=1}^{l} g_{j} cdot w_{h j} cdot x_{i} \ &=-b_{h}left(1-b_{h}right) cdot sum_{j=1}^{l} g_{j} cdot w_{h j} cdot x_{i} \ &=-e_{h} cdot x_{i} end{aligned}end{equation} ]

所以:

[begin{equation}Delta v_{i h}=-eta frac{partial E_{k}}{partial v_{i h}}=eta e_{h} x_{i}end{equation} ]

对于(begin{equation}Delta gamma_{h}end{equation} = -eta frac{partial E_{k}}{partial gamma_{h}}),有:

[begin{equation}begin{aligned} frac{partial E_{k}}{partial gamma_{h}} &=sum_{j=1}^{l} frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} cdot frac{partial beta_{j}}{partial b_{h}} cdot frac{partial b_{h}}{partial gamma_{h}} \ &=sum_{j=1}^{l} frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} cdot frac{partial beta_{j}}{partial b_{h}} cdot f^{prime}left(alpha_{h}-gamma_{h}right) cdot(-1) \ &=-sum_{j=1}^{l} sum_{partial j}^{partial E_{k}} frac{partial hat{y}_{j}^{k}}{mathbb{G}_{j}} cdot w_{h j} cdot f^{prime}left(alpha_{h}-gamma_{h}right) \ &=-sum_{j=1}^{l} frac{partial E_{k}}{partial hat{y}_{j}^{k}} cdot frac{partial hat{y}_{j}^{k}}{partial beta_{j}} cdot w_{h j} cdot b_{h}left(1-b_{h}right) \ &=sum_{j=1}^{l} g_{j} cdot w_{h j} cdot b_{h}left(1-b_{h}right) \ &=e_{h} end{aligned}end{equation} ]

因此:

[begin{equation}Delta gamma_{h}=-eta frac{partial E_{k}}{partial gamma_{h}}=-eta e_{h}end{equation} ]

综上可得:

[begin{equation}begin{array}{l} Delta w_{h j}=eta g_{j} b_{h} \ Delta theta_{j}=-eta g_{j} \ Delta v_{i h}=eta e_{h} x_{i} \ Delta gamma_{h}=-eta e_{h} \ 学习率eta不一定相等 end{array}end{equation} ]

其中:

[begin{equation}begin{aligned} &g_{j}=left(y_{j}^{k}-hat{y}_{j}^{k}right) hat{y}_{j}^{k}left(1-hat{y}_{j}^{k}right)\ &e_{h}=sum_{j=1}^{l} g_{j} cdot w_{h j} cdot b_{h}left(1-b_{h}right)\ end{aligned}end{equation} ]

算法的流程如下:

需注意的是,BP算法的目标是要最小化训练集(D)上的累计误差(也就是误差目标函数,(m)代表样本的数量):

[begin{equation}E=frac{1}{m} sum_{k=1}^{m} E_{k} end{equation} ]

但是在上面的算法中,我们知道,”标准BP算法“只是针对某一个训练样例更新了连接权和阈值,只针对单个(E_k),也许它能够计算出合适的(w,v,theta,gamma)让某一个测试样例((x_k,y_k))(E_k)达到最小值,但是对于所有的样例,可能计算出来的(w,v,theta,gamma)并不能让(E)达到最小值。因此我们需要进行多次迭代频繁的更新参数才能够达到(E)的极小点。累积 BP算法直接针对累积误差最小化,它在读取整个训练集 (D)一遍后才对参数进行更新,其参数更新的频率低得多。但在很多任务中,累积误差下降到一定程度之后,进 一步下降会非常缓慢,这时标准BP往往会更快获得较好的解,尤其是在训练集(D)非常大时更明显。(西瓜书中的原话)。

可以证明,只需一个包含足够多神经元的隐层,多层前馈网络就能以任意精度逼近任意复杂度的连续函数(可以看一下参考4.)。但是如何设置何理的神经元数量,则就是靠炼丹了(”试错法“trial-by-error)。

防止过拟合

通过前面我们知道,多层反馈网络能够以任意精度逼近任意复杂度的连续函数,因此它很容易造成”过拟合“问题。训练集的误差可能降低,但是测试集合的误差就可能刚好相反。有2中策略解决该问题:

  • 早停(early stopping)

    将数据集分成训练机和测试集,训练集用来更新连接权和阈值,测试集用来验证累计误差。若训练集误差降低但是测试集误差升高,则停止训练。

  • 正则化(regularization)

    正则化的思想就是在误差目标函数中增加一个用于描述网络复杂度的部分。这里添加连接权和阈值的平方和。此时误差目标函数就变成了:

    [begin{equation} E=lambda frac{1}{m} sum_{k=1}^{m} E_{k}+(1-lambda) sum_{i} w_{i}^{2} \ lambda in(0,1) end{equation} ]

    增加连接权与闵值平方和这一项后,训练过程将会偏好比较小的连接权和阈值,使网络输出更加"光滑",从而对过拟合有所缓解.

局部最小和全局最小

通过前面的学习我们知道,训练的过程实际上就是寻找最优参数(连接权和阈值)使得(E)最小。 最优面临着两种情况:

  • 局部最优
  • 全局最优

如果从数学角度来说,局部最优就是极小值点,而全局最优则就是最小值点。(最小值一定是极小值,但是极小值不一定是最小值)。

在神经网络中,我们肯定是希望找到一个最小值(而非一个极小值)。但是当我们使用梯度下降算法的时候,我们很容易陷入到极小值中间(此时梯度为0,也就是说导数为0,参数停止更新)。那么我们如何来避免这种情况呢?

  • 以多组不同参数值初始化多个神经网络,按标准方法训练后,取其中误差最小的解作为最终参数。这相当于从多个不同的初始点开始搜索,这样就可能陷入不同的局部极小,从中进行选择有可能获得更接近全局最小的结果。简单点来说就是从多个较小值中取出一个最小值。
  • 使用“模拟退火”(simulated annealing)技术。模拟退火在每一步都以一定的概率接受比当前解更差的结果,从而有助于“跳出”局部极小。在每步迭代过程中,接受“次优解”的概率要随着时间的推移而逐渐降低,从而保证算法稳定。
  • 使用随机梯度下降.与标准梯度下降法精确计算梯度不同,随机梯度下降法在计算梯度时加入了随机因素。于是,即便陷入局部极小点,它计算出的梯度仍可能不为零,这样就有机会跳出局部极小继续搜索。
  • 遗传算法

这里来说一下模拟退火算法,为什么说着算法呢?因为这个算法简单,并且挺有意思的。算法的流程如下:

算法的流程很简单,假设我们需要求(int(omega))的最小值,首先我们先随机产生一个较大的解(omega)(称之为初始温度),然后再产生另外一个解(omega’)(omega’ = domega,0<d<1,d称之为退温系数)),如果(Delta int=intleft(omega^{prime}right)-int(omega) leq 0),那毋庸置疑,肯定接受这个解。如果(Delta int=intleft(omega^{prime}right)-int(omega) > 0),则按照一定的概率(P)接受这个解(从(0,1)中随机选择一个数(rand),若(P>rand)则接受这个解),当(omega < omega_k)时退出算法((omega_k)称之为终止温度)。那么(P)是多少呢?

[begin{equation}p=e^{-frac{Delta int}{k omega}}end{equation},k为一个常数 ]

总结

OK,神经网络就暂时介绍到这里,至于深度学习这些内容,以后再做介绍,毕竟代码不是一天写成的。这一篇博客主要是为下一篇博客的使用神经网络识别验证码做铺垫。因为在《Python数据挖掘入门与实践》中并没有对神经网络做介绍。

参考

上面博客中的一些图片和一些公式来自下面的参考,并在某些图上进行了修改。为了排版就没有一个一个进行说明了,在这里统一说明下。

  1. 《西瓜书》——周志华
  2. 人工神经网络——维基百科
  3. 南瓜书
  4. 为什么神经网络能以任意精度拟合任意复杂度的函数?
  5. 模拟退火算法
  6. 神经网络浅讲:从神经元到深度学习