深度学习(二)——神经网络基础(多层感知器、反向传播算法)

ⅰ亾dé卋堺 提交于 2020-01-21 01:29:50

深度学习(二)——神经网络基础

神经网络的通用分类

人工神经网络模型可以理解为一组基本处理单元,它们紧密地相互连接,对输入进行类似的数学运算后生成期望的输出。基于信息在网络中传播的方式,可以将神经网络分为两个通用类别:

  1. 前馈神经网络
    前馈神经网络中信息的流动只能由前到后,也就是说,一层神经元的输出只能作为后一层神经元的输入。这些网络架构可以被称为有向无环图。典型的模型有多层感知器(MLP)卷积神经网络(CNN)
  2. 反馈神经网络
    反馈神经网络具有形成有向循环的连接,也就是说,后一层神经元也可以反过来作为前一层神经元的输入,这就使得神经网络可以处理序列数据。反馈网络还具有记忆能力,可以在其内部存储器中存储信息和序列关系。典型的模型有循环神经网络(RNN)长短期记忆网络(LSTM)

神经网络的基本结构

下面以多层感知器为例,介绍神经网络的基本结构。

基础架构

下图给出了MLP网络架构的一个例子:
在这里插入图片描述
这是一个五层感知器的例子,每一层分别含有3、4、2、3、3个人工神经元。我们用这个例子来介绍人工神经网络的一些特点:

分层架构:人工神经网络包含层次化的处理级别。每个级别被称为“网络层”,由许多人工神经元组成。网络层也可以细分为三种:

  • 第一层为输入层,用于接受数据输入。
  • 最后一层为输出层,用于产生输出数据并进行预测。
  • 其余层都被称为隐藏层或者隐含层,用于执行各种处理和运算。

人工神经元:每层中的基本处理单元被称为人工神经元。人工神经元存储了各个输入的权重和其特有的激活函数

密集连接:神经网络中的各个人工神经元是相互连接的,可以相互通信。前一层神经元的输出是后一层神经元的输入,这也是前馈神经网络的基本特征。并且,对于多层感知器,层中的每一个神经元都直接连接到前一个层的所有神经元。

人工神经元

下图给出了人工神经元的基本组成:
在这里插入图片描述
对于含有n个输入的人工神经元来说,它会进行如下的计算:

  1. 对n个输入加权求和,在必要的时候,我们会加入一个常数b作为偏置,这里计算得到的值称为激励值
  2. 对于加权求和后的结果,再通过激活函数运算后产生结果,再输出。

综合来说,单个人工神经元的输入是a1a_1-ana_n,输出为f(i=1nwiai+b)f(\sum_{i=1}^{n}w_i\cdot a_i+b),写成向量形式为:
Output=f(wa)Output=f(\vec{w}\cdot\vec{a})
其中w0=b,a0=1w_0=b,a_0=1。对于单个神经元来说,它的训练目标就是确定最优的wwbb使得输出与真实值的误差最小。

激活函数

激活函数指的是一组非线性函数。它能够将非线性的特性引入神经网络,使得神经网络具备拟合各种非线性分类数据的能力。常用的激活函数主要有以下几个:

Sigmoid函数
逻辑回归中,曾经介绍过Sigmoid函数,它的基本数学公式如下:
f(x)=11+exf(x)=\frac{1}{1+e^{-x}}
图像如下:
在这里插入图片描述
Tanh函数
Tanh函数是双曲函数的一种,它和Sigmoid函数具有类似的图像,只不过将值域扩展到了(-1,1)。
f(x)=exexex+exf(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}
图像如下:
在这里插入图片描述
ReLU函数
线性修正单元激活函数(ReLU函数)是一种改进的激活函数,可以解决Sigmoid函数的一些问题,在这篇博文的最后我们将会对其进行讨论。Relu函数的公式如下:
f(x)={x,x>00,x0f(x)=\left\{\begin{aligned} x,x>0\\ 0,x\leq0 \end{aligned}\right.
函数图像如下:
在这里插入图片描述


模型训练与反向传播算法

和机器学习相同,多层感知器的模型训练基本思想也是首先定义损失函数,然后利用梯度下降法及其变种算法进行迭代训练,直到参数不再变化或变化极小。一般可采用的损失函数有MSE、SVM铰链损失函数、交叉熵等。这里给出最常用的MSE的损失函数形式:
MSE:E=12n(yny^n)2MSE:E=\frac{1}{2}\sum_n(y_n-\hat{y}_n)^2
人工神经网络和一般的机器学习模型不同,人工神经网络是多层的,可以认为是很多个机器学习基本模型的连接,因此在求解梯度上存在一定的特殊性。因此,人工神经网络的训练方法被称为反向传播算法,在初始化权重后,反向传播算法分为两个步骤:

  1. 前向传播
  2. 反向传播

前向传播

所谓前向传播,实际上也是模型训练完成后的预测过程。数据从输入层输入,然后一层一层地进行运算,直到最后在输出层得到一个最终预测输出y^\hat{y}

举一个简单的例子说明这个过程,假设我们有一个含两个隐含层和一个输出层的多层感知器,并且每一层只含有一个神经元,输入层也只有一个神经元(即输入数据只有一维),连接情况及各层的权重如图所示:
在这里插入图片描述
接下来依次计算:

  • 第一层为输入层,输入输出都为A0A_0.
  • 第二层为隐含层,输入A0A_0,输出A1=f(w1A0)A_1=f(w_1A_0).
  • 第三层为隐含层,输入A1A_1,输出A2=f(w2A1)A_2=f(w_2A_1).
  • 第四层为输出层,输入A2A_2,输出A3=f(w3A2)A_3=f(w_3A_2).

就这样逐层进行计算,最终的计算结果A3A_3就是模型的输出y^\hat{y},可以用于预测和训练模型。含有多个神经元的网络也是如此。

反向传播

经过权重初始化和前向传播后,我们可以得到网络中的所有参数以及中间运算结果,接下来我们就要根据误差即损失函数的情况,更新模型中的权重,这个步骤被称为反向传播。前向传播和反向传播合起来称为模型的一轮训练过程。

在阐述具体过程前,让我们回顾一下梯度下降算法的参数迭代公式:
θn+1=θnηLθn\theta_{n+1}=\theta_n-\eta\frac{\partial L}{\partial\theta_n}
这个迭代公式对于单层的感知器和输出层也是适用的。但对于多层的感知器,我们需要从最后一层输出层开始,一层一层向前计算梯度、更新参数,这也是“反向传播”这个名称的由来。

接下来我们用一个简单的例子来推导反向传播算法的参数迭代公式。仍然使用上面用的这个例子:
在这里插入图片描述
假设使用MSE作为损失函数,只考虑一个样本(多个样本的情况只是对多个样本进行求和),并且神经元中不加入偏置(偏置实际上只是多一维输入)。损失函数如下:
L(w1,w2,w3)=12(y^y)2L(w_1,w_2,w_3)=\frac{1}{2}(\hat{y}-y)^2 Ly^=y^y\frac{\partial L}{\partial\hat{y}}=\hat{y}-y
我们必须要明确的一点是,我们的训练目标是找到最优的w1w_1,w2w_2,w3w_3使得误差最小,我们要更新的模型参数也是这三个,因此,根据梯度下降法的基本思想,我们需要求出损失函数对它们三者的偏导数,忽略输入层,由链式法则,从最后一层开始逐层计算如下:
Lw3=LA3A3D3D3w3=(y^y)f(D3)A3=δ3A2Lw2=LA2A2D2D2w2=δ3w3f(D2)A1=δ2A1Lw1=LA1A1D1D1w1=δ2w2f(D1)A0=δ1A0\begin{aligned} 第三层:\frac{\partial L}{\partial w_3}=\frac{\partial L}{\partial A_3}\frac{\partial A_3}{\partial D_3}\frac{\partial D_3}{\partial w_3}=(\hat{y}-y)f^{'}(D_3)A_3=\delta_3A_2\\ 第二层:\frac{\partial L}{\partial w_2}=\frac{\partial L}{\partial A_2}\frac{\partial A_2}{\partial D_2}\frac{\partial D_2}{\partial w_2}=\delta_3w_3\cdot f^{'}(D_2)A_1=\delta_2A_1\\ 第三层:\frac{\partial L}{\partial w_1}=\frac{\partial L}{\partial A_1}\frac{\partial A_1}{\partial D_1}\frac{\partial D_1}{\partial w_1}=\delta_2w_2\cdot f^{'}(D_1)A_0=\delta_1A_0 \end{aligned}
由上面的公式不难看出,对于Lwi\frac{\partial L}{\partial w_i}δi\delta_i之间存在一些递推关系:
Lwi=δiAi1δi=δi+1wi+1f(Di)\begin{aligned} \frac{\partial L}{\partial w_i}=\delta_iA_{i-1}\\ \delta_i=\delta_{i+1}w_{i+1}f^{'}(D_i)\\ \end{aligned}
有了上面这个重要结论,我们将它进行推广。考虑一层中含有多个神经元的情况,由于在单个神经元中,我们对多个输入的处理是进行加和,所以在求导时,正确的处理也是进行求和。另外要明确的是,一个神经元应当对应一个δ\delta。这样我们可以把反向传播算法的递推关系公式推广到普遍情况:

对于第ii层第jj个神经元,它的误差信号记作δji\delta_j^i,设它的激活函数为f(x)f(x),有mm个输入记作x1,...,xmx_1,...,x_m,权重分别为w1,...,wmw_1,...,w_m,它的激励值为aji=x1w1+...+xmwma_j^i=x_1w_1+...+x_mw_m。后一层有nn个神经元,第kk个神经元具有δki+1\delta^{i+1}_k,对于δji\delta_j^i神经元输入的权重为wkw^{'}_k。它的δji\delta_j^i有着这样的递推关系:
δji=f(aji)k=1nwkδki+1\delta_j^i=f^{'}(a_j^i)\sum_{k=1}^{n}w^{'}_k\delta^{i+1}_k
对于一个输入xkx_k和它对应的权重wkw_k,一次训练的参数更新公式如下:
wk:=wkηδjixkw_k:=w_k-\eta\delta_j^ix_k
其中:=:=为赋值符号,η\eta称为学习率。完整的学习过程将会包含很多次迭代,直到损失函数达到收敛。


梯度消失和梯度爆炸

反向传播算法成功地应用于各种神经的情况。但由于每一层之间使用链式法则即乘法进行传播,这就意味着每一层的梯度是指数级别增长的。当网络很深时,学习过程时可能会遭受梯度消失梯度爆炸的问题,这主要取决于激活函数的选择

当梯度较小时,可能会产生梯度消失问题。以sigmoid函数为例,sigmoid函数的导数最大值约为0.25。考虑一个5层的网络,传递到第一层时,梯度将会衰减为(0.25)5=0.0009(0.25)^5=0.0009,我们知道,当小数过小超出表示精度时,计算机会将它作为机器零来处理,因此就会导致初始几层的参数基本不会更新。这就是梯度消失问题。

同样的,当梯度较大时,可能会产生梯度爆炸问题。当输出层梯度大于1时,经过多层传递,很可能导致前几层的梯度非常巨大,每一次训练参数变化很大,使得模型训练困难,也很容易“走”出合理的区域。

梯度消失和梯度爆炸问题的一个解决方案是改进激活函数。一种改进的激活函数就是前面介绍的ReLU函数。它的一大特点是未激活时梯度为0,激活后梯度恒为1,由于0和1在指数运算时的不变性,就可以有效地防止梯度消失和梯度爆炸问题。

另外还有一种解决方案是梯度裁剪。简要地说就是设定一个阈值,如果求出来的梯度大于这个阈值,我们就将梯度强行缩减为等于阈值。这样也可以防止梯度爆炸问题。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!