共计 2000 个字符,预计需要花费 5 分钟才能阅读完成。
从单层感知机到多层网络的必然性
单层感知机(Perceptron)作为最早的神经网络模型,其核心局限在于无法解决非线性可分问题(如异或逻辑)。这直接导致了多层感知机(MLP)的诞生,但随之而来的关键挑战是:如何有效训练隐藏层的权重?反向传播算法(Backpropagation)通过链式法则实现了误差的逐层反向传递,成为深度学习发展的基石。

数学原理:链式法则的工程化应用
- 前向传播计算 :
- 隐藏层输出:$h = \sigma(W_1 x + b_1)$
- 输出层结果:$\hat{y} = \text{softmax}(W_2 h + b_2)$
-
其中 $\sigma$ 代表激活函数(如 Sigmoid)
-
损失函数(交叉熵):
$$ L = -\frac{1}{N}\sum_{i=1}^N y_i \log(\hat{y}_i) $$ -
反向传播关键步骤 :
- 输出层梯度:$\frac{\partial L}{\partial W_2} = (\hat{y} – y) \cdot h^T$
- 隐藏层梯度:$\frac{\partial L}{\partial W_1} = (W_2^T(\hat{y}-y)) \odot \sigma'(z_1) \cdot x^T$
- 符号说明:$\odot$ 表示逐元素乘法,$\sigma’$ 为激活函数导数
Python 实现(NumPy 版)
import numpy as np
from sklearn.datasets import fetch_openml
from sklearn.preprocessing import OneHotEncoder
# 数据加载与预处理
mnist = fetch_openml('mnist_784', version=1)
X = mnist.data / 255.0
y = OneHotEncoder().fit_transform(mnist.target.reshape(-1,1)).toarray()
# 网络参数
input_size = 784
hidden_size = 128
output_size = 10
learning_rate = 0.1
# 初始化权重
W1 = np.random.randn(input_size, hidden_size) * 0.01
b1 = np.zeros(hidden_size)
W2 = np.random.randn(hidden_size, output_size) * 0.01
b2 = np.zeros(output_size)
def sigmoid(x):
return 1/(1+np.exp(-x))
def sigmoid_derivative(x):
return x * (1-x)
# 训练循环
for epoch in range(100):
# 前向传播
z1 = np.dot(X, W1) + b1
a1 = sigmoid(z1)
z2 = np.dot(a1, W2) + b2
y_pred = np.exp(z2) / np.sum(np.exp(z2), axis=1, keepdims=True)
# 计算损失
loss = -np.mean(y * np.log(y_pred + 1e-10))
# 反向传播
dZ2 = y_pred - y
dW2 = np.dot(a1.T, dZ2)
db2 = np.sum(dZ2, axis=0)
dA1 = np.dot(dZ2, W2.T)
dZ1 = dA1 * sigmoid_derivative(a1)
dW1 = np.dot(X.T, dZ1)
db1 = np.sum(dZ1, axis=0)
# 参数更新
W1 -= learning_rate * dW1
b1 -= learning_rate * db1
W2 -= learning_rate * dW2
b2 -= learning_rate * db2
关键实践策略
- 学习率选择 :
- 初始建议值:0.01-0.1
-
自适应方法:可尝试学习率衰减(如每 10 轮减半)
-
批量训练对比 :
- 全批量:稳定但内存消耗大
- 小批量(128-256):实际最常用
-
随机梯度下降:噪声大但可能跳出局部最优
-
激活函数比较 :
- Sigmoid:易导致梯度消失,输出范围 (0,1)
- ReLU:缓解梯度消失,计算简单但可能有 ” 死亡神经元 ”
- LeakyReLU:解决 ReLU 的死亡问题,负区保留微小梯度
性能优化方向
- 迭代次数与早停 :
- 典型迭代:50-200 轮
-
早停策略:验证集准确率连续不提升时终止
-
网络结构实验 :
- 增加隐藏层:提升表达能力但需更多数据
- 宽度调整:128-512 神经元常见
- 添加 Dropout 层防止过拟合
延伸实验建议
-
可视化工具 :
import matplotlib.pyplot as plt plt.plot(loss_history) plt.xlabel('Epoch') plt.ylabel('Loss') -
改进方向 :
- 尝试不同的权重初始化方法(如 Xavier)
- 添加 L2 正则化项
- 实现动量(Momentum)优化
通过这个基础实现,读者可以深入理解 BP 算法的核心机制,后续可逐步扩展到更复杂的网络结构和优化策略。建议先确保基础版本稳定运行,再逐步添加高级特性。
正文完
