共计 1948 个字符,预计需要花费 5 分钟才能阅读完成。
BP 算法在深度学习中的地位
BP 反向传播算法是神经网络的训练基石,它通过误差反向传播高效计算梯度。没有 BP 算法,深度学习模型的参数更新将变得极其低效。可以说,现代深度学习的繁荣很大程度上得益于 BP 算法的广泛应用。

单隐层网络的前向传播
考虑一个具有 1 个隐层的简单神经网络结构:
- 输入层:(x_1, x_2)
- 隐层:2 个神经元,激活函数为 sigmoid
- 输出层:1 个神经元,激活函数为 sigmoid
前向传播过程可以用以下公式表示:
- 隐层输入:(z_h = W_h X + b_h)
- 隐层输出:(a_h = \sigma(z_h))
- 输出层输入:(z_o = W_o a_h + b_o)
- 最终输出:(a_o = \sigma(z_o))
其中 (\sigma) 表示 sigmoid 函数,损失函数采用均方误差:
(L = \frac{1}{2}(y – a_o)^2)
反向传播的 4 个关键步骤
1. 输出层梯度计算
首先计算损失对输出层输入的梯度:
(\frac{\partial L}{\partial z_o} = (a_o – y) \cdot \sigma'(z_o))
2. 隐层梯度计算
然后计算损失对隐层输入的梯度:
(\frac{\partial L}{\partial z_h} = (W_o^T \cdot \frac{\partial L}{\partial z_o}) \odot \sigma'(z_h))
3. 权重更新
计算权重梯度并更新:
(\frac{\partial L}{\partial W_o} = \frac{\partial L}{\partial z_o} \cdot a_h^T)
(\frac{\partial L}{\partial W_h} = \frac{\partial L}{\partial z_h} \cdot X^T)
4. 偏置更新
计算偏置梯度并更新:
(\frac{\partial L}{\partial b_o} = \frac{\partial L}{\partial z_o})
(\frac{\partial L}{\partial b_h} = \frac{\partial L}{\partial z_h})
Python 实现代码
import numpy as np
# 激活函数及其导数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 - s)
# 网络参数
input_size = 2
hidden_size = 2
output_size = 1
learning_rate = 0.1
# 初始化权重
W_h = np.random.randn(hidden_size, input_size)
W_o = np.random.randn(output_size, hidden_size)
b_h = np.zeros((hidden_size, 1))
b_o = np.zeros((output_size, 1))
# 前向传播
def forward(X):
z_h = np.dot(W_h, X) + b_h
a_h = sigmoid(z_h)
z_o = np.dot(W_o, a_h) + b_o
a_o = sigmoid(z_o)
return z_h, a_h, z_o, a_o
# 反向传播
def backward(X, y, z_h, a_h, z_o, a_o):
# 输出层梯度
dL_dzo = (a_o - y) * sigmoid_derivative(z_o)
# 隐层梯度
dL_dzh = np.dot(W_o.T, dL_dzo) * sigmoid_derivative(z_h)
# 权重更新
dL_dWo = np.dot(dL_dzo, a_h.T)
dL_dWh = np.dot(dL_dzh, X.T)
# 偏置更新
dL_dbo = dL_dzo
dL_dbh = dL_dzh
return dL_dWh, dL_dWo, dL_dbh, dL_dbo
# 训练循环
for epoch in range(1000):
# 这里应该添加数据输入和训练循环
pass
避坑指南
梯度消失问题
当网络层数较深时,梯度可能会变得非常小,导致训练停滞。可以通过以下方法识别:
- 检查各层权重的更新幅度
- 观察损失函数下降速度
- 使用梯度裁剪或更好的激活函数(如 ReLU)
学习率设置
学习率太大可能导致震荡,太小则收敛缓慢。建议:
- 从 0.01 开始尝试
- 使用学习率衰减策略
- 考虑自适应优化器(如 Adam)
权重初始化
不当的初始化会导致训练困难:
- 避免全零初始化
- 考虑 Xavier 或 He 初始化
- 小随机数通常效果不错
思考题
- 如何将当前实现扩展为多层网络?
- 如果将 sigmoid 改为 ReLU,反向传播需要做哪些调整?
- 批量训练与在线训练的梯度计算有何不同?
总结
通过本文的学习,我们深入理解了 BP 算法的数学原理和实现细节。虽然看起来有些复杂,但只要一步步拆解,其实并不难掌握。建议读者动手实现代码,通过实践来加深理解。
