本文是关于周志华老师编写的机器学习书籍『西瓜书』的第五章神经网络.
主要的内容有: M-P神经元模型的构成、简单感知机和多层网络、以及著名BP算法的推导过程(激活函数是Sigmoid).
这里所说的神经网络是指: 由具有适应性的简单单元
组成的广泛并行互联的网络, 能够模拟生物神经对现实世界做出的交互反映.
5.1 神经元模型
在神经网络中, 最基本的组成成分就是神经元(neuron)模型, 即上述的简单单元
.
工作过程
首先介绍以下最简单的神经元的工作过程:
- 首先神经元通过接收来自n个其他神经元传输来的
输入
信号\(x_i\); - 并通过带
权重
\(w_i\)的连接(connection)进行传递; - 然后, 神经元收到的总输入值将与神经元的
阈值
\(\theta\)(threshold))进行比较; - 再通过
激活函数
\(f\)(activation function)处理以产生神经元的输出
\(y\).

这就是非常经典的M-P神经元模型, 模拟生物的神经元的连接与激活过程.
激活函数
其中最理想的激活函数是阶跃函数, 直接表示神经元是否激活, 但是阶跃函数并不光滑连续, 数学性质并不好. 所以实际上常用的是sigmoid
函数\(f(z) = \frac{1}{1+e^{-z}}\), 这在对数几率模型中也使用过.

激活函数是对
总输入与阈值的比较
进行处理! (我之前错误的以为是激活函数对输入进行处理后再与阈值比较);激活函数本质上是在加入非线性因素, 使得神经网络来解决非线性问题.
5.2 感知机与多层网络
感知机
感知机(Perceptron)由两层神经元组成, 其中输入层
接收外界传输的输入信号, 并传递给输出层, 输出层
即为上述所说的M-P神经元
, 亦称阈值逻辑单元
(threshold logic unit). 所以实际上具有处理能力的功能神经元只有一层输出层, 学习能力有限.
在感知机中, 输入的数据集和输出的激活函数都是给定的, 感知机需要学习的就是未知的权重\(w_i\)和阈值\(\theta\)来使其有效的工作.
但是从输出\(y = f(\sum_{i=1}^n{w_ix_i-\theta})\)中来看, 阈值可以被看作第n+1项
输入, 值为-1
, 这样就可以将阈值和权重统一为权重学习即可!
学习规则:
\[ w_i \leftarrow w_i + \Delta w_i \\ \Delta w_i = \eta(y-\hat{y})x_i \]
其中\(\hat{y}\)是感知机的输出, \(\eta\in(0, 1)\)称为学习率(learning rate), 若预测正确, 则感知机不变, 若预测错误, 则根据错误程度调整权重.
多层网络
若两类模式是线性可分的, 即存在一个线性超平面能将它们分开, 那么感知机的学习过程一定会收敛(converge), 从而求得合适的权值; 反之, 感知机的学习过程将会振荡(fluctuation), 难以求得合适的解.
若要解决非线性可分的问题, 就需要考虑使用多层功能神经元, 一般称输入层和输出层之间的一层神经元层为隐层或隐含层(hidden layer).
常见的神经元是层级结构的, 每层神经元与下一层的神经元全互连, 神经元之间不存在同层连接, 也不存在跨层连接, 这样的神经网络结构通常称为"多层前馈神经网络"(multi-layer feedforward neural networks). 其中输入层仅接收输入, 隐层与输出层使用功能神经元进行函数处理.
"前馈"并不是信号不能向后传播, 而是指网络拓扑结构中不存在环或回路.

(a)图可以称为"单隐层网络"或"两层网络". 我们的学习过程就是通过训练数据来调整神经元之间的连接权值(connection weight), 以及每个功能神经元的阈值, 看依旧是这权值和阈值.
5.3 误差逆传播算法
对于多层的网络结构, 简单的感知机学习算法就不够使用了. 而误差逆传播(error BackPropagation, BP)算法是迄今为止最成功的神经网络学习算法.
为了说明BP算法, 先规定一些变量符号:
- 训练集: \(D = \{(\boldsymbol{x}_1, \boldsymbol{y}_1), (\boldsymbol{x}_2, \boldsymbol{y}_2), \dots, (\boldsymbol{x}_m, \boldsymbol{y}_m)\}, \boldsymbol{x}_i \in \mathbb{R}^d, \boldsymbol{y}_i \in \mathbb{R}^l\).
- 输入层: 输入示例\(x\)由\(d\)个属性描述. 则输入层有\(d\)个输入神经元.
- 输出层: 输出\(y\)是\(l\)维向量. 则输出层有\(l\)个输出神经元. 第\(j\)个神经元的阈值用\(\theta_j\)表示.
- 隐层: 隐层\(b\)假设使用\(q\)个隐层神经元. 第\(h\)个神经元的阈值使用\(\gamma_h\)表示.
- 输入层--隐层: 输入层第\(i\)个神经元与隐层第\(h\)个神经元的权值使用\(v_{ih}\)表示, 那么第\(h\)个隐层神经元的总输入为\(\alpha_h = \sum\limits_{i=1}^d{(v_{ih}x_i)}\).
- 隐层--输出层: 隐层第\(h\)个神经元与输出层第\(j\)个神经元的权值使用\(w_{hj}\)表示, 那么第\(j\)个输出神经元的总输入为\(\beta_j = \sum\limits_{h=1}^q{(w_{hj}b_h)}\).
- 激活函数: 此处依旧使用sigmoid函数.
示意图如下:

5.3 参数学习过程
其中需要确定的权值有\((dq+ql)\)个, 阈值有\((q+l)\)个.
同样假设输出为\(\hat{\boldsymbol{y}} = \{\hat{y}_1, \hat{y}_2, \dots, \hat{y}_l\}\), 其中\(\hat{y}_j = f(\beta_j-\theta_j)\).
其中对于第K例输入样本可以求出网络的均方误差为:
\[ E_k = \frac{1}{2} \sum^l_{j=1}(\hat{y}_j-y_j)^2 \]
将均方误差作为我们的损失函数, 与感知机的更新方法类似, 对任意参数\(\omega\), 更新估计式为
\[ \omega \leftarrow \omega + \Delta \omega \]
也同样将阈值加入其中一起计算, 那么只需要估计两个参数即可, 即输入层神经元与隐层神经元的权值\(v_{ih}\), 以及隐层神经元与输出层神经元的权值\(w_{hj}\).
梯度下降法求解
BP算法基于梯度下降法(gradient descent), 以目标的负梯度方向对参数进行调整.
以隐层到输出层的权值\(w_{hj}\)为例进行推导, 对于给定的学习率\(\eta\), 有
\[ \Delta w_{hj} = -\eta \frac{\partial E_k}{\partial w_{hj}} \]
而我们注意到, 权值\(w_{hj}\)先影响到输入总值\(\beta\), 然后影响到输出值\(\hat{y}_j\), 最后影响到误差\(E\), 由此展开有:
\[ \frac{\partial E_k}{\partial w_{hj}} = \frac{\partial E_k}{\partial \hat{y}_j} \cdot \frac{\partial \hat{y}_j}{\partial \beta_j} \cdot \frac{\partial \beta_j}{\partial w_{hj}} \]
根据\(\beta_j\)的定义, 显然有\(\frac{\partial \beta_j}{\partial w_{hj}} = b_h\).
又根据Sigmoid函数的性质, 有:
\[ \begin{aligned} g_j &= - \frac{\partial E_k}{\partial \hat{y}_j} \cdot \frac{\partial \hat{y}_j}{\partial \beta_j} \\ &= -(\hat{y}_j-y_j)f'(\beta_j-\theta_j) \\ &= (y_j-\hat{y}_j)\hat{y}_j(1-\hat{y}_j) \end{aligned} \]
由此可得权值\(w_{hj}\)的更新公式
\[ \Delta w_{hj} = \eta g_j b_h; \]
同理其他三个参数的更新公式, 此处不再赘述.
算法伪代码如下:

其中停止条件根据缓解BP的过拟合策略有关.
过拟合策略
由于表达效果往往非常好, 所以经常会遭遇过拟合的问题. 通常有两种策略来解决:
第一种是早停(early stopping): 将数据集分为训练集和验证集, 当训练集误差降低但验证集误差升高时停止训练, 并返回具有最小验证集误差的连接权值和阈值.
第二种是正则化(regularization), 在误差函数中增加一个用于描述网络复杂度的部分, 使得训练过程中偏好较小的参数, 降低网络复杂度. 例如使用连接权值与阈值的平方和:
\[ E = \lambda \frac{1}{m}\sum_{k=1}^m {E_k} + (1-\lambda) \sum_i{w_i^2} \]
其中的\(\lambda\)是对经验误差和网络复杂度的折中, 通常用交叉验证来估计值.
不同的BP算法
可以发现, 上述过程中我们是对每个训练样例来更新连接权值和阈值, 更新参数非常频繁, 不同样例的训练可能会对之前更新的效果进行抵消, 最终得到我们需要的积累误差:
\[ E = \frac{1}{m}\sum_{k=1}^m {E_k} \]
所以为了积累误差达到极小值点, 往往需要更多次数的迭代, 这个方法称为『标准BP算法』.
类似的, 基于累积误差最小化的更新规则也可以推导出『累积BP算法』, 该方法直接针对累积误差最小化, 在读取整个训练集后才对参数进行更新, 更新参数频率低得多, 而且在很多任务中, 积累误差下降到一定之后,下一步下降会非常缓慢, 而此时的标准BP算法则可以更快的获得较好的解.
区别类似于随机梯度下降算法(stochastic gradient descent, SGD)和标准梯度下降算法之间的区别.
虽然两者都很常用, 但是在大数据集中, 标准BP算法的速度会更快.
隐层神经元个数
有证明称, 只需要一个包含足够多神经元的隐层, 多层前馈网络就能以任意精度逼近任意复杂的连续函数.
但是如何设置神经元个数依旧没有定论, 一般使用『试错法』(trial-by-error)进行调整.
个人收获
关于神经网络的学习, 之前在初步了解的时候被公式劝退, 这次再认真学习之后终于有些明朗了.
感知机中起作用的功能神经层只有输出层, 包括单隐层网络中输入层的结点仅起到输入作用, 所以这也是为什么明明画了三层网络,但是却叫双层网络的原因.
在学习公式推导之前一定要将符号弄清楚, 清楚符号的含义之后再推公式就清清楚楚了.
待更新: 关于全局最小和局部最小放在另外要写的梯度下降法模块中再进一步阐述. 其他神经网络也有待进一步的学习, 最后向深度学习迈进.