人工神经网络

概要:

人工神经网络是一种模拟大脑神经元的计算机结构。人们用神经网络来建立模型,使用模型来训练数据,最后可以使得模型具备某种人们想要的预测分类的能力。

 

 

应用场景:

    分类。

 

优点:

  1. 可以充分逼近任意复杂的非线性关系。
  2. 所有定量或定性的信息都等势分布贮存于网络内的各神经元,故有很强的鲁棒性和容错性。
  3. 采用并行分布处理方法,使得快速进行大量运算成为可能。
  4. 可学习和自适应不知道或不确定的系统。

 

缺点:

  1. 神经网络很难解释,目前还没有能对神经网络做出显而易见解释的方法学。
  2. 神经网络会学习过度,即过拟合。
  3. 网络训练失败的可能性较大。因为BP算法得出的是局部极值容易陷入局部极值。而且,网络结构的选择没有统一而完整的理论指导。
  4. 训练时间较长。

 

 

 

人工神经网络的算法过程:

  1. 初始化所有神经元连接的权重、偏置。
  2. 输入前向传递。通过样本输入、连接的权重和偏置,从隐藏层到输出层递进式地计算出每一个神经元的输出。
  3. 输出层输出该组训练数据的类别。将此类别和训练数据的期望输出比较,如果误差不符合预设的阈值,则启动后向传播算法过程;如果误差符合预设的阈值,则神经网络的算法终止。
  4. 如果启动后向传播算法,则使用输出层的误差计算前一层神经元的误差,并以这种方式从后向前递进式地计算所有隐藏层、输入层的神经元上的误差。
  5. 从输入层到输出层,逐层更新连接的权重和神经元的偏置。

 

 

 

 

 

超参数的确定

 

我们首先需要确定网络的层数和每层的节点数。关于第一个问题,实际上并没有什么理论化的方法,大家都是根据经验来拍,如果没有经验的话就随便拍一个。然后,你可以多试几个值,训练不同层数的神经网络,看看哪个效果最好就用哪个。嗯,现在你可能明白为什么说深度学习是个手艺活了,有些手艺很让人无语,而有些手艺还是很有技术含量的。

 

不过,有些基本道理我们还是明白的,我们知道网络层数越多越好,也知道层数越多训练难度越大。对于全连接网络,隐藏层最好不要超过三层。那么,我们可以先试试仅有一个隐藏层的神经网络效果怎么样。毕竟模型小的话,训练起来也快些(刚开始玩模型的时候,都希望快点看到结果)。

 

输入层节点数是确定的。因为MNIST数据集每个训练数据是28*28的图片,共784个像素,因此,输入层节点数应该是784,每个像素对应一个输入节点。

 

输出层节点数也是确定的。因为是10分类,我们可以用10个节点,每个节点对应一个分类。输出层10个节点中,输出最大值的那个节点对应的分类,就是模型的预测结果。

 

隐藏层节点数量是不好确定的,从1到100万都可以。下面有几个经验公式:

 


 

因此,我们可以先根据上面的公式设置一个隐藏层节点数。如果有时间,我们可以设置不同的节点数,分别训练,看看哪个效果最好就用哪个。我们先拍一个,设隐藏层节点数为300吧。

 

对于3层784*300*10的全连接网络,总共有300*(784+1)+10*(300+1)=238510个参数!神经网络之所以强大,是它提供了一种非常简单的方法去实现大量的参数。目前百亿参数、千亿样本的超大规模神经网络也是有的。因为MNIST只有6万个训练样本,参数太多了很容易过拟合,效果反而不好。

 

模型的训练和评估

 

MNIST数据集包含10000个测试样本。我们先用60000个训练样本训练我们的网络,然后再用测试样本对网络进行测试,计算识别错误率:

 


 

我们每训练10轮,评估一次准确率。当准确率开始下降时(出现了过拟合)终止训练。


神经网络数学推导过程


神经元和感知器本质上是一样的,只不过我们说感知器的时候,它的激活函数是阶跃函数;而当我们说神经元时,激活函数往往选择为sigmoid函数或tanh函数。如下图所示:

 


 


 



sigmoid函数的定义如下:

 


 

将其带入前面的式子,得到

 


 

sigmoid函数是一个非线性函数,值域是(0,1)。函数图像如下图所示

 


 

sigmoid函数的导数是:

 


 

可以看到,sigmoid函数的导数非常有趣,它可以用sigmoid函数自身来表示。

这样,一旦计算出sigmoid函数的值,计算它的导数的值就非常方便。

 

神经网络是啥

 


 

神经网络其实就是按照一定规则连接起来的多个神经元。上图展示了一个全连接(full connected,FC)神经网络,通过观察上面的图,我们可以发现它的规则包括:

 

神经元按照层来布局。最左边的层叫做输入层,负责接收输入数据;最右边的层叫输出层,我们可以从这层获取神经网络输出数据。输入层和输出层之间的层叫做隐藏层,因为它们对于外部来说是不可见的。

同一层的神经元之间没有连接。

第N层的每个神经元和第N-1层的所有神经元相连(这就是fullconnected的含义),第N-1层神经元的输出就是第N层神经元的输入。

每个连接都有一个权值。

 

上面这些规则定义了全连接神经网络的结构。事实上还存在很多其它结构的神经网络,比如卷积神经网络(CNN)、循环神经网络(RNN),他们都具有不同的连接规则。

 

 计算神经网络的输出

 

神经网络实际上就是一个输入向量到输出向量的函数,即:

 


 

根据输入计算神经网络的输出,需要首先将输入向量的每个元素的值赋给神经网络的输入层的对应神经元,然后根据式1依次向前计算每一层的每个神经元的值,直到最后一层输出层的所有神经元的值计算完毕。最后,将输出层每个神经元的值串在一起就得到了输出向量。

 

接下来举一个例子来说明这个过程,我们先给神经网络的每个单元写上编号。

 


 

如上图,输入层有三个节点,我们将其依次编号为1、2、3;隐藏层的4个节点,编号依次为4、5、6、7;最后输出层的两个节点编号为8、9。因为我们这个神经网络是全连接网络,所以可以看到每个节点都和上一层的所有节点有连接。比如,我们可以看到隐藏层的节点4,它和输入层的三个节点1、2、3之间都有连接,其连接上的权重分别为W41,W42,W43。那么,我们怎样计算节点4的输出值a4呢?

 

为了计算节点4的输出值,我们必须先得到其所有上游节点(也就是节点1、2、3)的输出值。节点1、2、3是输入层的节点,所以,他们的输出值就是输入向量本身。按照上图画出的对应关系,可以看到节点1、2、3的输出值分别是X1,X2,X3。我们要求输入向量的维度和输入层神经元个数相同,而输入向量的某个元素对应到哪个输入节点是可以自由决定的,你偏非要把赋值给节点2也是完全没有问题的,但这样除了把自己弄晕之外,并没有什么价值。

 

一旦我们有了节点1、2、3的输出值,我们就可以根据式1计算节点4的输出值a4:

 


 

上式的W4b是节点4的偏置项,图中没有画出来。而W41,W42,W43分别为节点1、2、3到节点4连接的权重,在给权重Wji编号时,我们把目标节点的编号j放在前面,把源节点的编号放在后面。

 

同样,我们可以继续计算出节点5、6、7的输出值a5,a6,a7。这样,隐藏层的4个节点的输出值就计算完成了,我们就可以接着计算输出层的节点8的输出值y1:

 


 

同理,我们还可以计算出y2的值。这样输出层所有节点的输出值计算完毕,我们就得到了在输入向量


时,神经网络的输出向量


。这里我们也看到,输出向量的维度和输出层神经元个数相同。

 

 神经网络的矩阵表示

 

神经网络的计算如果用矩阵来表示会很方便(当然逼格也更高),我们先来看看隐藏层的矩阵表示。

 

首先我们把隐藏层4个节点的计算依次排列出来:

 


 

接着,定义网络的输入向量和隐藏层每个节点的权重向量。令

 


 

代入到前面的一组式子,得到:

 


 

现在,我们把上述计算的四个式子写到一个矩阵里面,每个式子作为矩阵的一行,就可以利用矩阵来表示它们的计算了。令

 


 

带入前面的一组式子,得到:

 


 

在式2中,是激活函数,在本例中是sigmoid函数;W是某一层的权重矩阵;x是某层的输入向量;a是某层的输出向量。式2说明神经网络的每一层的作用实际上就是先将输入向量左乘一个数组进行线性变换,得到一个新的向量,

然后再对这个向量逐元素应用一个激活函数。

 

每一层的算法都是一样的。比如,对于包含一个输入层,一个输出层和三个隐藏层的神经网络,

我们假设其权重矩阵分别为W1,W2,W3,W4,每个隐藏层的输出分别是a1,a2,a3,神经网络的输入为x,

神经网络的输入为y,如下图所示:

 


 

则每一层的输出向量的计算可以表示为:

 


 

这就是神经网络输出值的计算方法。

 

 神经网络的训练

 

现在,我们需要知道一个神经网络的每个连接上的权值是如何得到的。我们可以说神经网络是一个模型,

那么这些权值就是模型的参数,也就是模型要学习的东西。然而,一个神经网络的连接方式、网络的层数、

每层的节点数这些参数,则不是学习出来的,而是人为事先设置的。对于这些人为设置的参数,

我们称之为超参数(Hyper-Parameters)。

 

接下来,我们将要介绍神经网络的训练算法:反向传播算法。

 

反向传播算法(Back Propagation)

 

我们首先直观的介绍反向传播算法,最后再来介绍这个算法的推导。当然读者也可以完全跳过推导部分,因为即使不知道如何推导,也不影响你写出来一个神经网络的训练代码。事实上,现在神经网络成熟的开源实现多如牛毛,除了练手之外,你可能都没有机会需要去写一个神经网络。

 

我们假设每个训练样本为(x,t),其中向量x是训练样本的特征,而t是样本的目标值。

 


 

首先,我们根据上一节介绍的算法,用样本的特征x,计算出神经网络中每个隐藏层节点的输出ai,

以及输出层每个节点的输出yi。

 

然后,我们按照下面的方法计算出每个节点的误差项:

 

对于输出层节点,

 


 

其中,等号左边是节点的误差项,Yi是节点i的输出值,ti是样本对应于节点i的目标值。举个例子,

根据上图,对于输出层节点8来说,它的输出值是y1,而样本的目标值是t1,带入上面的公式得到

节点8的误差项应该是:

 


 

对于隐藏层节点,

 


 

其中,ai是节点i的输出值,Wki是节点到它的下一层节点k的连接的权重,是节点i的下一层节点

k的误差项。例如,对于隐藏层节点4来说,计算方法如下:

 


 

最后,更新每个连接上的权值:

 


 


 


 

类似的,权重的更新方法如下:

 


 

偏置项的输入值永远为1。例如,节点4的偏置项应该按照下面的方法计算:

 


 

我们已经介绍了神经网络每个节点误差项的计算和权重更新方法。显然,计算一个节点的误差项,需要先计算每个与其相连的下一层节点的误差项。这就要求误差项的计算顺序必须是从输出层开始,然后反向依次计算每个隐藏层的误差项,直到与输入层相连的那个隐藏层。这就是反向传播算法的名字的含义。当所有节点的误差项计算完毕后,我们就可以根据式5来更新所有的权重。

 

 

 

反向传播算法的推导

 

反向传播算法其实就是链式求导法则的应用。然而,这个如此简单且显而易见的方法,却是在Roseblatt提出感知器算法将近30年之后才被发明和普及的。对此,Bengio这样回应道:

 

很多看似显而易见的想法只有在事后才变得显而易见。


 

接下来,我们用链式求导法则来推导反向传播算法,也就是上一小节的式3、式4、式5。

 

前方高能预警——接下来是数学公式重灾区,读者可以酌情阅读,不必强求。

 

按照机器学习的通用套路,我们先确定神经网络的目标函数,然后用随机梯度下降优化算法去求目标函数最小值时的参数值。

 

我们取网络所有输出层节点的误差平方和作为目标函数:

 


 

其中,表示是样本的误差。

 

然后,我们用随机梯度下降算法对目标函数进行优化:

 


 

随机梯度下降算法也就是需要求出误差Ed对于每个权重Wji的偏导数(也就是梯度),怎么求呢?

 


 

观察上图,我们发现权重Wji仅能通过影响节点j的输入值影响网络的其它部分,设netj是节点j的加权输入,即

 


 

Ed是netj的函数,而netj是Wji的函数。根据链式求导法则,可以得到:


上式中,Xji是节点i传递给节点j的输入值,也就是节点的输出值。

 

对于的推导,需要区分输出层和隐藏层两种情况。

 

 

输出层权值训练

 


 

考虑上式第一项:

 


 

考虑上式第二项:

 


 

将第一项和第二项带入,得到:

 


 

如果令,也就是一个节点的误差项是网络误差对这个节点输入的偏导数的相反数。带入上式,到:

 


上式就是式3。

 

将上述推导带入随机梯度下降公式,得到:

 


 

上式就是式5。

 

隐藏层权值训练

 


 

上式就是式4。


 

至此,我们已经推导出了反向传播算法。需要注意的是,我们刚刚推导出的训练规则是根据激活函数是sigmoid函数、平方和误差、全连接网络、随机梯度下降优化算法。如果激活函数不同、误差计算方式不同、网络连接结构不同、优化算法不同,则具体的训练规则也会不一样。但是无论怎样,训练规则的推导方式都是一样的,应用链式求导法则进行推导即可。


怎么保证自己写的神经网络没有BUG呢?事实上这是一个非常重要的问题。一方面,千辛万苦想到一个算法,结果效果不理想,那么是算法本身错了还是代码实现错了呢?定位这种问题肯定要花费大量的时间和精力。另一方面,由于神经网络的复杂性,我们几乎无法事先知道神经网络的输入和输出,因此类似TDD(测试驱动开发)这样的开发方法似乎也不可行。

 

办法还是有滴,就是利用梯度检查来确认程序是否正确。梯度检查的思路如下:


 

对于梯度下降算法:

 


 




图解多层前馈人工神经网络的算法过程


 


 

 

 

 


 

 

 


 

 


 

 


 

 


 

 


 

 


 

 


 

 


 

 


 

 


 

 


 

 


 

 


 

 

 


 

 


 

 

 


 

 

 


 


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值