神经网络主要是由三个部分组成的,分别是:1) 网络架构 2) 激活函数 3) 找出最优权重值的参数学习算法.
BP(back propagation)神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络。
既然我们无法直接得到隐层的权值,能否先通过输出层得到输出结果和期望输出的误差来间接调整隐层的权值呢?BP算法就是采用这样的思想设计出来的算法,它的基本思想:学习过程由信号的正向传播(求损失)与误差的反向传播(误差回传)两个过程组成。如图所示为BP算法模型示意图
BP算法的一般流程:
正向传播FP(求损失).在这个过程中,我们根据输入的样本,给定的初始化权重值W和偏置项的值b, 计算最终输出值以及输出值与实际值之间的损失值.如果损失值不在给定的范围内则进行反向传播的过程; 否则停止W,b的更新.
反向传播BP(回传误差).将输出以某种形式通过隐层向输入层逐层反传,并将误差分摊给各层的所有单元,从而获得各层单元的误差信号,此误差信号即作为修正各单元权值的依据。
下面我们将以下图所示的神经网络,该图所示是一个三层神经网络,两层隐藏层和一层输出层,输入层有两个神经元,接收输入样本,为网络的输出
为了理解神经网络的运算过程,我们需要先搞清楚前馈计算,即数据沿着神经网络前向传播的计算过程,以上图所示的网络为例,输入的样本为:
三层网络的参数定义为:
第一层隐藏层的计算
第一层隐藏层有三个神经元:neu₁、neu₂和。neu₃该层的输入为:
以单个神经元为例,则其输入为:
假设我们选择函数f(x)作为该层的激活函数(图中的激活函数都标了一个下标,一般情况下,同一层的激活函数都是一样的,不同层可以选择不同的激活函数),那么该层的输出为:f1(z1)、f2(z2)、f3(z3)。
第二层隐藏层的计算:
第二层隐藏层有两个神经元:neu₄和neu₅。该层的输入为:
即第二层的输入是第一层的输出乘以第二层的权重,再加上第二层的偏置。因此得到z4和z5的输入分别为:
该层的输出分别为:f4(z4)和f5(z5)。
输出层的计算:
输出层只有一个神经元:neu₆。该层的输入为:
因为该网络要解决的是一个二分类问题,所以输出层的激活函数也可以使用一个Sigmoid型函数,神经网络最后的输出为f6(z6)。
解了数据沿着神经网络前向传播的过程,这一节我们来介绍更重要的反向传播的计算过程。假设我们使用随机梯度下降的方式来学习神经网络的参数,损失函数定义为 L ( y , y ^ ) L(y,{\hat{y}}) L(y,y^),其中y是该样本的真实类标。使用梯度下降进行参数的学习,我们必须计算出损失函数关于神经网络中各层参数(权重w和偏置b)的偏导数。
假设我们要对第k层隐藏层的参数W(k)和求偏导数b(k)。假设z(k)代表第k层神经元的输入,即
其中n(k-1)为前一层神经元的输出,则根据链式法则有:
计算偏导数1:
前面说过,第k层神经元的输入为:
可以得到:
上式中,W_m (k)代表第k层神经元的权重矩阵的第m行,W_mn (k)代表第k层神经元的权重矩阵的第m行中的第n列。
假设我们要计算第一层隐藏层的神经元关于权重矩阵的导数,则有:
计算偏导数2:
偏导数 ∂ L ( y , y ^ ) ∂ z ( k ) \frac{\partial L(y,\hat{y})}{\partial z^{(k)}} ∂z(k)∂L(y,y^),又称为误差项( 也称为"灵敏度"),其值的大小代表了第一层神经元对于最终总误差的影响大小。根据第一节的前向计算,我们知道第k + 1层的输入与第k层的输出之间的关系为:
其中: n ( k ) = f k ( z k ) n^{(k)}=f_{k}(z_{k}) n(k)=fk(zk),根据链式法则,我们可以得到:
由上式我们可以看到,
第 k 层 神 经 元 的 误 差 项 δ ( k ) 是 由 第 k + 1 层 的 误 差 项 乘 以 第 k + 1 层 的 权 重 , 再 乘 以 第 k 层 激 活 函 数 的 导 数 ( 梯 度 ) 得 到 的 。 这 就 是 误 差 的 反 向 传 播 。 \color{red} {第k层神经元的误差项\delta^{(k)}是由第k + 1层的误差项乘以第k + 1层的权重,再乘以第k层激活函数的导数(梯度)得到的。这就是误差的反向传播。} 第k层神经元的误差项δ(k)是由第k+1层的误差项乘以第k+1层的权重,再乘以第k层激活函数的导数(梯度)得到的。这就是误差的反向传播。
现在我们已经计算出了偏导数,则分别表示为:
假设每一层网络激活后的输出为 f i ( x ) f_{i}(x) fi(x),其中i 为第i 层, x代表第i层的输入,也就是第i−1层的输出,f是激活函数,那么得出 f i + 1 ( x ) = f ( f i + 1 ∗ w i + 1 + b i + 1 ) f_{i+1}(x) = f(f_{i+1} * w_{i+1} + b_{i+1}) fi+1(x)=f(fi+1∗wi+1+bi+1):,记为 f i + 1 = f ( f i ∗ w i + 1 ) f_{i+1} = f(f_{i } * w_{i+1}) fi+1=f(fi∗wi+1)
可以看出,这是一个类似迭代的公式,前一层的参数更新,有赖于后一层的损失。
五. BP神经网络的工作流程
输入:训练集 D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x m , y m ) } D=\left \{ (\boldsymbol{x}_{1},\boldsymbol{y}_{1}),(\boldsymbol{x}_{2},\boldsymbol{y}_{2}),\cdots,(\boldsymbol{x}_{m},\boldsymbol{y}_{m}) \right \} D={(x1,y1),(x2,y2),⋯,(xm,ym)}
学习率: η \small \eta η
① 在(0,1)范围内随机初始化网络中所有的参数(连接权重和偏置);
② 选取一个样本,计算网络前向传播过程的输出,用反向传播过程来更新网络参数;
③ 重复②,直至将训练集中所有样本遍历一遍;
④ 重复②③,直至达到停止条件:训练集上的累积误差降低到可接受范围之内;
输出:参数确定的BP神经网络。
tips:
① 上面介绍并推导的BP算法也被称为“标准BP算法”,它每次更新只针对单个样例,所以参数更新得非常频繁。
② 还有一种“累积BP算法”,它在遍历整个数据集一遍后,才会根据所有训练样本的累积误差对参数进行一次更新。
③ 为了达到同样的累积误差极小点,标准BP算法往往需要比累积BP算法进行更多次数的迭代,但是在数据集非常大时,标准BP算法往往能够更快获得较好的解。
④ 隐藏层的层数并不是多多益善,已有学者证明,只需一个包含足够多神经元的隐藏层,多层前馈神经网络就能以任意精度逼近任意复杂度的连续函数。所以我们在设计BP神经网络时,往往优先考虑增加神经元的数目,而不是增加隐藏层的层数。