共计 1995 个字符,预计需要花费 5 分钟才能阅读完成。
为什么学习 BP 神经网络?
BP 神经网络(Backpropagation Neural Network)是深度学习的基础。比如:

- 手写数字识别 :银行支票自动识别系统通过 BP 网络学习数字特征,准确率可达 98%
- 销量预测 :电商平台用历史销售数据训练网络,预测下周商品销量,误差小于传统统计方法
数学原理拆解
1. 前向传播的矩阵表示
假设网络有 3 层(输入层 L1、隐藏层 L2、输出层 L3),前向传播公式为:
Z2 = W1 · X + b1 # 隐藏层加权输入
A2 = σ(Z2) # Sigmoid 激活函数
Z3 = W2 · A2 + b2
A3 = σ(Z3) # 最终输出
2. 损失函数选择
对于分类问题常用交叉熵损失(Cross-Entropy):
L = -Σ[y·log(a3) + (1-y)·log(1-a3)]
3. 反向传播推导(核心!)
通过链式法则计算梯度:
- 输出层误差:δ3 = (A3 – Y) * σ'(Z3)
- 隐藏层误差:δ2 = (W2.T · δ3) * σ'(Z2)
- 权重更新:
W2 -= η · δ3 · A2.T b2 -= η · δ3 W1 -= η · δ2 · X.T b1 -= η · δ2(η 为学习率)
Python 实现(NumPy 版)
import numpy as np
class NeuralNetwork:
def __init__(self, input_size, hidden_size, output_size):
self.W1 = np.random.randn(hidden_size, input_size) * 0.01
self.b1 = np.zeros((hidden_size, 1))
self.W2 = np.random.randn(output_size, hidden_size) * 0.01
self.b2 = np.zeros((output_size, 1))
def sigmoid(self, z):
return 1 / (1 + np.exp(-z))
def forward(self, X):
self.Z2 = np.dot(self.W1, X) + self.b1
self.A2 = self.sigmoid(self.Z2)
self.Z3 = np.dot(self.W2, self.A2) + self.b2
self.A3 = self.sigmoid(self.Z3)
return self.A3
def backward(self, X, Y, learning_rate):
m = X.shape[1] # 样本数量
# 输出层误差
dZ3 = self.A3 - Y
dW2 = np.dot(dZ3, self.A2.T) / m
db2 = np.sum(dZ3, axis=1, keepdims=True) / m
# 隐藏层误差
dZ2 = np.dot(self.W2.T, dZ3) * (self.A2 * (1 - self.A2))
dW1 = np.dot(dZ2, X.T) / m
db1 = np.sum(dZ2, axis=1, keepdims=True) / m
# 更新参数
self.W2 -= learning_rate * dW2
self.b2 -= learning_rate * db2
self.W1 -= learning_rate * dW1
self.b1 -= learning_rate * db1
MNIST 实验测试
from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784', version=1)
X = mnist.data.T / 255.0 # 归一化
Y = np.eye(10)[mnist.target.astype(int)].T # one-hot 编码
nn = NeuralNetwork(784, 128, 10)
for i in range(1000):
nn.forward(X)
nn.backward(X, Y, 0.1)
if i % 100 == 0:
print(f"Epoch {i}, Loss: {np.mean((nn.A3 - Y)**2)}")
常见问题解决方案
梯度消失问题
- 现象 :隐藏层梯度接近 0,参数无法更新
- 解决 :
- 使用 ReLU 激活函数替代 Sigmoid
- 采用 Batch Normalization
过拟合对策
- Early Stopping:验证集准确率下降时停止训练
- L2 正则化:在损失函数中加入权重平方项
进阶思考
- 与 CNN/RNN 对比 :
- CNN 擅长处理网格数据(如图像)
-
RNN 适合序列数据(如文本)
-
Mini-Batch 优化 :
def train_batch(X, Y, batch_size=32): for i in range(0, X.shape[1], batch_size): X_batch = X[:, i:i+batch_size] Y_batch = Y[:, i:i+batch_size] nn.forward(X_batch) nn.backward(X_batch, Y_batch, 0.1)
通过这个完整案例,你应该已经掌握了 BP 网络的核心要义。建议尝试调整隐藏层节点数、更换激活函数,观察对模型性能的影响。
正文完
