BP神经网络教程:从结构到训练实践
本教程将带你全面了解反向传播神经网络(Backpropagation,简称BP)的核心原理、训练流程以及实际应用中的经验技巧。无论你是初学者还是有一定基础的开发者,都能从中获得清晰、可操作的指导。
一、BP神经网络的结构
神经网络模拟了大脑神经单元的工作方式,但做了极大简化。它由多个神经网络层构成,每一层又由许多单元(结点)组成。第一层称为输入层,最后一层称为输出层,中间的层称为隐藏层。在BP神经网络中,只有相邻层之间的单元才有连接,且除输出层外,每一层都有一个偏置结点。

传统经验认为一层隐藏层就足够,但深度学习则不这么认为。偏置结点用于描述训练数据中未出现的特征,通过不同权重对下一层每个结点产生不同偏置,可视为每个结点(除输入层外)的属性。下图省略了偏置结点:

二、神经层与结点的核心属性
在理解训练过程前,先明确各层和结点的属性:
- 每个神经单元拥有一定能量,定义为该结点j的输出值Oj。
- 相邻层之间的连接有一个权重Wij,取值范围在[-1,1]之间。
- 除输入层外,每个结点都有一个输入值,等于上一层所有结点按权重传递的能量之和加上偏置。
- 除输入层外,每个结点都有一个偏置值,取值范围在[0,1]之间。
- 除输入层外,每个结点的输出值等于该结点的输入值经过非线性变换得到。
- 输入层没有输入值,其输出值直接等于训练数据的属性。例如,记录X=(1,2,3)表示输入层三个结点的输出值分别为1,2,3。因此,输入层的结点个数一般等于训练数据的属性个数。
三、训练BP神经网络的核心流程
训练BP神经网络就是调整权重和偏置这两个参数,整个过程分为两个阶段:
- 前向传播(Feed-Forward):逐层波浪式传递输出值。
- 反向传播(Backpropagation):反向逐层调整权重和偏置。
3.1 前向传播(Feed-Forward)
训练开始前,需要随机初始化权重和偏置:每个权重取[-1,1]的随机实数,每个偏置取[0,1]的随机实数。之后进行前向传播。
整个训练由多轮迭代完成,每轮迭代使用训练集的所有记录,但每次只处理一条记录。伪代码如下:
while 终止条件未满足:
for record in 训练集:
trainModel(record)
具体步骤:
- 设置输入层输出值:假设属性个数为100,则输入层神经单元个数为100,结点Ni的输出值等于记录第i维的属性值xi。
- 计算后续各层:除输入层外,每个结点的输入值 = 上一层所有结点输出值按权重累加 + 偏置值。每个结点的输出值 = 对该输入值进行非线性变换(如Sigmoid函数)。

前向传播的输出层计算过程公式如下:

对隐藏层和输出层的每个结点都按此方式计算输出值,即完成前向传播。
3.2 反向传播(Backpropagation)
反向传播从最后一层(输出层)开始。训练BP神经网络做分类时,我们希望输出层能描述数据记录的类别。例如,二分类问题常用两个输出单元,若第一个输出值大于第二个,则判为第一类,否则为第二类。
由于初始权重和偏置是随机的,输出结果必然与真实类别有差异。我们需要调整参数来缩小这个差异,这就是优化目标。
输出层误差计算:
其中Ej表示第j个结点的误差值,Oj表示第j个结点的输出值,Tj是真实记录输出值。例如,二分类用01表示类别1,10表示类别2,若记录属于类别1,则T1=0,T2=1。
隐藏层误差计算:隐藏层不直接与类别打交道,而是通过下一层所有结点的误差按权重累加得到:
其中Wjk表示当前层结点j到下一层结点k的权重,Ek是下一层结点k的误差率。
更新权重:

其中λ表示学习速率,取值0到1。学习速率大,训练收敛快但易陷入局部最优;学习速率小,收敛慢但能逐步逼近全局最优。
更新偏置:

至此,完成一次神经网络的训练过程。通过不断使用所有数据记录重复该过程,最终得到一个分类模型。
四、训练终止条件
训练不能无限进行,常用两种终止条件:
- 设置最大迭代次数:例如,使用数据集迭代100次后停止。
- 达到预定准确率:计算训练集在网络上的预测准确率,达到一定门限后停止。
五、实战案例:手写数字识别
作者用C++实现了一个BP神经网络,在MNIST手写数字数据集上测试。MNIST包含12000张训练图片和20000张测试图片,每张28×28的灰度图像,经过二值化处理。参数设置如下:
- 输入层:28×28 = 784个单元。
- 输出层:10个单元,对应10个数字类别。
- 学习速率:0.05。
- 经过约50次迭代,训练集准确率达99%,测试集准确率90.03%。
单纯BP神经网络提升空间有限,而卷积神经网络在相同测试集上可达99.3%准确率。
六、训练BP神经网络的经验总结
以下是作者在训练过程中的宝贵经验:
- 学习速率不宜过大:一般小于0.1。初始设为0.85时准确率一直上不去,明显陷入局部最优。
- 输入数据应归一化:使用0-255灰度值效果不佳,转为01二值后效果显著提升。
- 尽量使数据记录随机分布:不要按类别排序。若按类别顺序训练,模型会逐渐只记得最近训练的类别而遗忘之前类别。
- 多分类问题可对输出编码:例如汉字识别有7000个类别,若输出层设7000个结点,计算量巨大且不易收敛。此时可对类别进行二进制编码,7000个汉字仅需13个二进制位,输出层只需13个结点。
七、常见问题(FAQ)
Q1:为什么我的BP神经网络训练时准确率始终不提升?
可能原因:学习速率过大导致陷入局部最优,或学习速率过小导致收敛极慢。建议先尝试0.1以下的学习速率,并观察准确率变化曲线。同时检查输入数据是否归一化,以及是否对数据进行了随机打乱。
Q2:隐藏层神经元数量如何确定?
没有固定公式,通常通过经验或实验确定。常见的做法是取输入层和输出层神经元数量的平均值,或者使用2/3的输入层大小加上输出层大小。对于复杂问题,可尝试多个隐藏层(如深度学习思路),但层数增加会带来过拟合风险。
Q3:为什么我的测试集准确率远低于训练集?
这是典型的过拟合现象。解决方案:增加训练数据量、减少隐藏层神经元数量、添加正则化(如L2正则化)、或使用早停法(当验证集准确率不再提升时停止训练)。
Q4:如何选择非线性变换函数?
常见的有Sigmoid、tanh、ReLU。对于BP神经网络,早期的Sigmoid和tanh使用较多,但存在梯度消失问题。现代深度学习更常用ReLU及其变体。若做二分类,输出层通常用Sigmoid;多分类则用Softmax。
