BP神经网络

1. 背景

人工神经网络(ANN)的研究是由试图模拟生物神经系统而激发的。人类的大脑主要由称为神经元(neuron)的神经细胞组成,神经元通过叫作轴突(axon)的纤维连在一起。当神经元受到刺激时,神经脉冲通过轴突从一个神经元传到另一个神经元。一个神经元通过树突(dendrite)连接到其他神经元的轴突,树突是神经元细胞体的延伸物。树突和轴突的连接点叫做神经键(synapse)。神经学家发现,人的大脑通过在同一个脉冲反复刺激下改变神经元之间的神经键连接强度来进行学习。

在对人脑神经网络的基本认识上,用数学和物理方法以及从信息处理的角度对人脑神经网络进行抽象,并建立某种简化模型,称之为人工神经网络(Artificial Neural Network, ANN)。因此,人工神经网络不是人脑神经网络的真实写照,而只是对它的简化、抽象与模拟。

2. 感知器模型

类似于人脑的结构,ANN由一组相互连接的结点和有向链构成。感知器(perceptron)是一种最简单的模型。1958年,美国神经学家Rosenblatt发表了一篇跟感知器有关的研究论文《The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain》。Rosenblatt的感知器(perceptron)模型实际是一种最简单的前馈式神经网络,它只有两层,即输入层输出层,感知器的网络拓扑结构如图所示。


perceptron

如图所示,该网络结构包含了两层:输入层(也称为感知层)和输出层(也称为处理层)。输入层有$n$个神经元节点,每个节点负责接收一个输入信号$x_i(i=1,2,\cdots,n)$,它们不具有数据处理能力;输出层是数据处理层,有$m$个神经元节点,每个节点都具有数据处理能力;输入层和输出层之间的连接权值用$w_j$表示。

现在我们对输出层进行分析。设

$$
\left \{
\begin{split}
X &=(x_1,x_2,\cdots,x_i,\cdots,x_n)^T \\
O &=(o_1,o_2,\cdots,o_j,\cdots,o_m)^T \\
W_j &= (w_{1j},w_{2j},\cdots,w_{ij},\cdots,w_{nj})^T, j=1,2,\cdots,m \\
\end{split}
\right.
$$

对处理层的某个神经元节点$j$,其净输入$net_j’$为输入层各节点的输入加权和,用公式表示如下:

$$
net_j’ = \sum_{i=1}^n w_{ij}x_i
$$

其输出$o_j$由该节点的转移函数决定,这里采用符号函数$sgn$(也可以采用sigmoid函数等),则有:

$$
\begin{split}
o_j &= sgn(net_j’) \\
&= sgn(\sum_{i=0}^n w_{ij}x_i) \\
&= sgn(net_j) \\
&= sgn(W_j^T X)
\end{split}
$$

其中,$net_j = {W}_j^T {X}$。

也就是

$$
o_j=\left \{
\begin{split}
1, ~ & W_j^T X >0 \\
-1, ~ & W_j^T X<0
\end{split}
\right.
$$

从而,感知器(perceptron)的数学模型可简洁地表示成:

$$
O = sgn(W^T X)
$$

其中,$W = (W_1, W_2, \cdots,W_j,\cdots,W_m)$。

3. BP神经网络

3.1 BP神经网络结构

BP(Back Propagation)神经网络是一种多层前馈神经网络,实际应用中的BP神经网络一般只有一个或两个隐层,这里我们只讨论只有一个隐层的神经网络,如图所示。


bp

上图的神经网络有三层:输入层、隐含层和输出层。其中,
输入层向量为$${X}=(x_1,x_2,\cdots,x_i,\cdots,x_n)^T$$图中$x_0=-1$是为隐含层神经元引入阈值而设置的;

隐含层输出向量为$${Y}=(y_1,y_2,\cdots,y_j,\cdots,y_m)^T$$图中$y_0=-1$是为输出层神经元引入阈值而设置的;

输出层输出向量为$${O}=(o_1,o_2,\cdots,o_k,\cdots,o_l)^T$$

期望输出向量为$${d}=(d_1,d_2,\cdots,d_k,\cdots,d_l)^T$$

输入层到隐层之间的权值矩阵用${V}$表示 $${V}=({V}_1,{V}_2,\cdots,{V}_j,\cdots,{V}_m)$$其中列向量${V}_j$表示隐含层第$j$个神经元对应的权值向量;

隐含层到输出层之间的权值矩阵用${W}$表示,$${W}=({W}_1,{W}_2,\cdots,{W}_j,\cdots,{W}_l)$$其中列向量${W}_k$表示输出层第$k$个神经元对应的权向量。

因此,BP神经网络可以看成一个非线性函数${O}=f({X})$,输入层向量${X}$是函数的自变量,输出层向量${O}$是函数的因变量,当输入层为$n$个节点,输出层为$l$个节点时,BP神经网络就相当于从$n$个自变量到$l$个因变量的函数映射关系。

3.2 BP神经网络训练算法

BP(Back Propagation)算法的基本思想是:训练过程由信号的正向传递误差的反向传播两个过程组成。

  • [正向传递]:输入信号从输入层传入,经隐含层逐层处理,传向输出层。每一层的神经元状态只影响下一层神经元状态,如果输出层的实际输出跟期望输出不符,则转入误差的反向传播阶段;

  • [反向传播]:误差的反向传播是指将预测误差(即实际输出跟期望输出之间的误差)通过某种形式经隐层向输入层逐层反传,根据预测误差调整每层的网络权值和阈值,权值和阈值的不断调整更新的过程,也就是网络的训练学习过程,最终使BP神经网络的预测输出不断逼近期望输出,或达到预先设定的误差和训练次数等目标。

下面以上图的BP神经网络为例介绍BP学习算法。

在正向传递阶段
对于隐含层,我们有:
\begin{equation}
\label{eq:forward1}
\left \{
\begin{split}
y_j &= f(net_j) , ~ j=1,2,\cdots,m \\
net_j &= \sum_{i=0}^n v_{ij}x_i , ~ j=1,2,\cdots,m
\end{split}
\right.
\end{equation}

对于输出层,我们有:
\begin{equation}
\label{eq:forward2}
\left \{
\begin{split}
o_k &= f(net_k), ~ k=1,2,\cdots,l \\
net_k &= \sum_{j=0}^m w_{jk}y_j, ~, k=1,2,\cdots,l
\end{split}
\right.
\end{equation}

以上两式中,$f(x)$是神经元激活函数,一般可取$f(x)$为单极性Sigmoid函数:
\begin{equation}
\label{eq:sigmoid1}
f(x) = \frac{1}{1+e^{-x}}
\end{equation}
也可取$f(x)$为双极性Sigmoid函数:
\begin{equation}
\label{eq:sigmoid2}
f(x) = \frac{1-e^{-x}}{1+e^{-x}}
\end{equation}

在误差的反向传播阶段
当网络预测输出与期望输出不相等时,存在输出误差$E$,定义如下:
\begin{equation}
\label{backward}
\begin{split}
E &= \frac{1}{2}({d}-{O})^2 \\
&= \frac{1}{2}\sum_{k=1}^l (d_k - o_k)^2
\end{split}
\end{equation}

将以上误差展开至隐含层,即将式(2)代入式(5),可得:

\begin{equation}
\label{eq:errhidden}
\begin{split}
E &= \frac{1}{2}\sum_{k=1}^l [d_k - f(net_k)]^2 \\
&= \frac{1}{2}\sum_{k=1}^l \left[d_k - f\left(\sum_{j=0}^m w_{jk}y_j\right)\right]^2
\end{split}
\end{equation}

进一步展开至输入层,将式(1)代入式(6),可得:

\begin{equation}
\label{eq:errinput}
\begin{split}
E &= \frac{1}{2}\sum_{k=1}^l \left\{d_k - f \left[\sum_{j=0}^m w_{jk}f(net_j)\right]\right\}^2 \\
&= \frac{1}{2}\sum_{k=1}^l \left\{d_k - f \left[\sum_{j=0}^m w_{jk}f \left(\sum_{i=0}^n v_{ij}x_i \right)\right]\right\}^2 \\
\end{split}
\end{equation}

由式(7)可知,网络的预测误差是各层权值(包含阈值)$v_{ij}$和$w_{jk}$的非线性函数,因此调整权值可改变误差$E$。为了使误差不断地减小,我们应该使权值的调整量与误差的梯度下降成正比,即:

\begin{equation}
\label{eq:adjust}
\left \{
\begin{split}
\Delta v_{ij} &= -\eta \frac{\partial E}{\partial v_{ij}}, ~ i=0,1,2,\cdots,n; ~ j=1,2,\cdots,m \\
\Delta w_{jk} &= -\eta \frac{\partial E}{\partial w_{jk}}, ~ j=0,1,2,\cdots,m; ~ k=1,2,\cdots,l
\end{split}
\right.
\end{equation}

其中,$\Delta v_{ij}$和$\Delta w_{jk}$表示权值的调整量;$\frac{\partial E}{\partial v_{ij}}$和$\frac{\partial E}{\partial w_{jk}}$表示误差函数关于权值的偏导数;$\eta \in (0,1)$是一个比例系数,表示学习速率,负号表示梯度下降。

上述就是BP神经网络的数学原理,下面是更加详细的数学推导过程,如果不想深入的话,可以直接跳到下一部分

由式(8)可进一步得到:
\begin{equation}
\label{eq:adjust2}
\left \{
\begin{split}
\Delta v_{ij} &= -\eta \frac{\partial E}{\partial v_{ij}} = -\eta \frac{\partial E}{\partial net_j} \frac{\partial net_j}{\partial v_{ij}} \\
\Delta w_{jk} &= -\eta \frac{\partial E}{\partial w_{jk}} = -\eta \frac{\partial E}{\partial net_k} \frac{\partial net_k}
{\partial w_{jk}}
\end{split}
\right.
\end{equation}

我们令:

\begin{equation}
\label{eq:adjust3}
\left \{
\begin{split}
\delta_j^y &= -\frac{\partial E}{\partial net_j} \\
\delta_k^o &= -\frac{\partial E}{\partial net_k}
\end{split}
\right.
\end{equation}

另外,由式(1)和式(2)可得:
\begin{equation}
\label{eq:adjust4}
\left \{
\begin{split}
\frac{\partial net_j}{\partial v_{ij}} &= x_i \\
\frac{\partial net_k}{\partial w_{jk}} &= y_j
\end{split}
\right.
\end{equation}

将式(10)和式(11)代入式(9)可得:
\begin{equation}
\label{eq:adjust5}
\left \{
\begin{split}
\Delta v_{ij} &= \eta \delta_j^y x_i \\
\Delta w_{jk} &= \eta \delta_k^o y_j
\end{split}
\right.
\end{equation}

因此,我们只需要求出$\delta_j^y$和$\delta_k^o$,便可推导出权值的调整量。

对于$\delta_j^y$,我们有

\begin{equation}
\label{eq:adjust6}
\begin{split}
\delta_j^y &= -\frac{\partial E}{\partial net_j} \\
&= -\frac{\partial E}{\partial y_j} \frac{\partial y_j}{\partial net_j} \\
&= -\frac{\partial E}{\partial y_j} f’(net_j) \\
&= \left[ \sum_{k=1}^l (d_k - o_k) f’(net_k) w_{jk} \right] f’(net_j)
\end{split}
\end{equation}

同理,对于$\delta_k^o$,可得:
\begin{equation}
\label{eq:adjust7}
\delta_k^o = (d_k - o_k) o_k (1-o_k)
\end{equation}

由于$f’(net_j) = y_j(1-y_j)$,$f’(net_k)=o_k(1-o_k)$,因此,有
\begin{equation}
\label{eq:adjust8}
\delta_j^y = \left( \sum_{k=1}^l \delta_k^o w_{jk}\right) y_j (1-y_j)
\end{equation}

将式(14)和式(15)代入式(12),可得到权值调整公式:

\begin{equation}
\label{eq:weightadjust}
\left \{
\begin{split}
\Delta v_{ij} &= \eta \left( \sum_{k=1}^l \delta_k^o w_{jk} \right) y_j (1-y_j) x_i \\
\Delta w_{jk} &= \eta (d_k - o_k) o_k (1-o_k) y_j
\end{split}
\right.
\end{equation}

对于输入层,设${X}=(x_0,x_1,\cdots,x_i,\cdots,x_n)^T$,${\delta}^y=(\delta_1^y,\delta_2^y,\cdots,\delta_j^y,\cdots,\delta_m^y)^T$,
对于隐含层,设${Y}=(y_0,y_1,\cdots,y_j,\cdots,y_m)^T$,${\delta}^o=(\delta_1^o,\delta_2^o,\cdots,\delta_k^o,\cdots,\delta_l^o)^T$,
则有:

\begin{equation}
\label{eq:weightadjust2}
\left \{
\begin{split}
\Delta {V} &= \eta ({\delta}^y {X}^T)^T \\
\Delta {W} &= \eta ({\delta}^o {Y}^T)^T
\end{split}
\right.
\end{equation}

式(17)即为式(16)的向量形式,由式(17)我们可以看到,BP算法的权值调整公式包含3个影响因子:学习率$\eta$,本层的误差信号${\delta}$和本层的输入信号${Y}$(或${X}$)。

由上面BP算法的推导过程,我们可以总结出BP神经网络的训练过程,步骤如下所示

(a) 网络初始化。根据系统输入输出向量$({X},{O})$确定网络输入层节点数$n$、隐含层节点数$m$和输出层节点数$l$;初始化输入层、隐含层和输出层神经元之间的连接权值(包含阈值)$v_{ij},w_{jk}$,设置学习速率$\eta$和神经元激活函数。

(b) 计算隐含层输出。由输入变量${X}$,输入层和隐含层之间的权值矩阵${V}$,根据式(1)计算隐含层输出${Y}$。
(c) 计算输出层输出。由隐含层输出${Y}$,隐含层和输出层之间的权值矩阵${W}$,根据式(2)计算网络的预测输出${O}$。
(d) 计算误差。由网络的预测输出${O}$和期望输出${d}$,根据式(5)计算网络的预测误差$E$。
(e) 更新权值。根据式(17)更新网络节点的权值和阈值。
(f) 判断算法迭代是否结束。若没有结束,则返回步骤(b)。

4. BP神经网络优缺点

BP神经网络是目前应用比较广泛的神经网络,它有以下的一些优点:

  • 非线性映射能力。BP神经网络可以学习输入$\sim$输出的非线性映射关系,而无需给出这种映射关系的数学方程。通过给出大量的输入输出数据,我们可以通过BP神经网络来学习这些数据间的关系,发现输入数据跟输出之间的规律,从本质上来说,这也是对非线性函数的一种拟合。
  • 泛化能力。BP神经网络的泛化能力是指当向网络输入一些训练时未曾遇到的样本时,它可以正确地将未知样本进行分类和预测等,也就是完成由输入空间到输出空间的正确映射,泛化能力也是衡量一个模型性能优劣的重要因素。
  • 容错能力。BP神经网络的容错能力是指允许输入样本带有个别误差,因为神经网络的训练过程也是一个提取统计特征的过程,个别的误差不会影响到整个网络的训练。

BP神经网络在实际的应用中也存在着以下的缺点:

  • 容易陷入局部极小而得不到全局最优。在实际的计算中,我们希望BP网络可以找到全局最优点,但往往它会陷入局部最优点,这也表明问题的主要特征没有被网络所提取出来。在这种情况下,我们通常会初始化权值再重新训练一遍,也有可能要改网络的其他参数。
  • 收敛速度慢。由于BP神经网络的优化方法是梯度下降法,它所要优化的目标函数是一个复杂的非线性函数,因此训练次数多,而且由于误差曲面上有平坦区域,在这些区域中,误差的梯度变化不大,这也使得收敛速度变慢。
  • 缺乏理论指导。目前BP神经网络的建模一般都是根据以有的经验设置网络参数,比如隐层的层数,隐层的节点个数等,我们一般采取多试验几次再择优的方法进行建模,这也给实际的应用带来了困难。

5. BP神经网络实例

这里将BP神经网络应用于手写数字图像识别,使用的数据集是MNIST库。MNIST库是一个手写数字数据集,含有数字0-9的训练图片集和0-9的测试图片集,共有60000个训练样本和10000个测试样本,所有的图片都经过了尺寸标准化和中心化,图片的大小为$28 \times 28$,MNIST库的一些样本可参考这里,这里提供一份matlab格式的数据,点击下载

将BP神经网络模型应用于MNIST库的流程为:

  1. 构建神经网络结构:每张图片的大小为$28 \times 28$,共784个像素,因此我们考虑用一个大小为784的向量来表示每张图片,所以神经网络的输入层有784个节点;而图片的内容是数字0-9,因此有10类图片,所以神经网络的输出层有10个节点;将神经网络的隐藏层数设置为1,即单隐层,且隐层节点数为100。因此,构建好的神经网络结构为784-100-10。

  2. 训练神经网络:我们使用BP算法进行训练。

  3. 预测:将训练好的神经网络模型对待识别的测试样本进行分类。

这里我们使用rasmusbergpalm的MATLAB深度学习工具箱,里面实现了多种神经网络算法,比如BP,DBN,CNN等,关于该工具箱的介绍可以参考这里

MATLAB代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
%% 加载数据
load mnist_uint8;
%% 归一化
train_x = double(train_x) / 255;
test_x = double(test_x) / 255;
train_y = double(train_y);
test_y = double(test_y);
[train_x, mu, sigma] = zscore(train_x);
test_x = normalize(test_x, mu, sigma);
%% 构建及训练网络
nn = nnsetup([784 100 10]);
opts.numepochs = 1;
opts.batchsize = 20;
[nn, L] = nntrain(nn, train_x, train_y, opts);
%% 预测
labels = nnpredict(nn, test_x);
[dummy, expected] = max(test_y,[],2);
[er, bad] = nntest(nn, test_x, test_y);

运行代码,可以得到分类错误率为0.0958。

6. 参考资料