共计 2152 个字符,预计需要花费 6 分钟才能阅读完成。
背景介绍
反向传播算法是神经网络训练的基石,而批量梯度下降(BGD)是最基础但重要的优化方法之一。BGD 的核心思想是使用整个训练集计算梯度,然后更新权重。虽然计算成本较高,但梯度方向稳定,适合理解反向传播的本质。

对于初学者来说,BGD 反向传播提供了一个清晰的学习路径:
- 完整展示梯度如何从输出层反向传播到输入层
- 帮助建立对损失函数、参数更新的直观理解
- 为学习更复杂的优化方法奠定基础
数学原理
前向传播
对于一个简单的 3 层神经网络(输入层、隐藏层、输出层),前向传播过程可以表示为:
- 隐藏层激活值:
$$h = \sigma(W_1x + b_1)$$ - 输出层预测值:
$$\hat{y} = \sigma(W_2h + b_2)$$
其中 $\sigma$ 是激活函数(如 sigmoid),$W$ 是权重矩阵,$b$ 是偏置项。
损失计算
使用均方误差(MSE)作为损失函数:
$$L = \frac{1}{2N}\sum_{i=1}^N(y_i – \hat{y}_i)^2$$
反向传播
关键是通过链式法则计算各层参数的梯度:
- 输出层梯度:
$$\frac{\partial L}{\partial W_2} = (\hat{y} – y) \cdot \sigma'(z_2) \cdot h^T$$ - 隐藏层梯度:
$$\frac{\partial L}{\partial W_1} = W_2^T \cdot [(\hat{y} – y) \cdot \sigma'(z_2)] \cdot \sigma'(z_1) \cdot x^T$$
其中 $z$ 表示激活函数的输入。
Python 实现
import numpy as np
# 定义 sigmoid 激活函数及其导数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
return x * (1 - x)
# 初始化参数
input_size = 2
hidden_size = 3
output_size = 1
lr = 0.1
epochs = 1000
# 随机初始化权重
W1 = np.random.randn(input_size, hidden_size)
W2 = np.random.randn(hidden_size, output_size)
# 模拟训练数据
X = np.array([[0,0], [0,1], [1,0], [1,1]]) # 输入
Y = np.array([[0], [1], [1], [0]]) # 输出(XOR 问题)
# BGD 训练过程
for epoch in range(epochs):
# 前向传播
hidden_input = np.dot(X, W1)
hidden_output = sigmoid(hidden_input)
final_input = np.dot(hidden_output, W2)
final_output = sigmoid(final_input)
# 计算损失
loss = np.mean(0.5 * (Y - final_output) ** 2)
# 反向传播
# 输出层误差
output_error = Y - final_output
output_delta = output_error * sigmoid_derivative(final_output)
# 隐藏层误差
hidden_error = output_delta.dot(W2.T)
hidden_delta = hidden_error * sigmoid_derivative(hidden_output)
# 更新权重
W2 += hidden_output.T.dot(output_delta) * lr
W1 += X.T.dot(hidden_delta) * lr
if epoch % 100 == 0:
print(f'Epoch {epoch}, Loss: {loss:.4f}')
print("Training complete")
print("Final predictions:", final_output)
参数调优
学习率 (lr) 是 BGD 中最重要的超参数:
- 学习率太小:收敛速度慢,需要更多 epoch
- 学习率太大:可能导致震荡甚至发散
调参建议:
- 初始尝试 0.1,观察训练曲线
- 如果损失波动大,尝试降低学习率
- 使用学习率衰减策略,如每 100 个 epoch 减半
- 结合验证集监控模型性能
对比分析
| 方法 | 批量大小 | 稳定性 | 计算效率 | 适用场景 |
|---|---|---|---|---|
| BGD | 全部样本 | 高 | 低 | 小型数据集 |
| SGD | 1 个样本 | 低 | 高 | 在线学习 |
| Mini-batch | 小批量 | 中等 | 中等 | 大多数场景 |
避坑指南
- 梯度消失:使用 ReLU 等激活函数替代 sigmoid
- 初始化问题:避免全零初始化,使用 Xavier/Glorot 初始化
- 学习率选择:建议从 0.01-0.1 开始尝试
- 特征缩放:确保输入特征在相似范围
- 梯度检查:实现后建议用数值梯度验证
实践建议
- 在 MNIST 等标准数据集上练习实现
- 尝试可视化权重和梯度的变化
- 扩展实现不同的激活函数和损失函数
- 参考资源:
- 《深度学习》Ian Goodfellow
- CS231n 课程笔记
- PyTorch/TensorFlow 官方教程
思考题
- 如何修改代码实现学习率衰减?衰减策略如何影响训练?
- 当隐藏层增加到 3 层时,反向传播的公式会如何变化?尝试推导并实现。
通过这篇教程,希望你能掌握 BGD 反向传播的核心思想。虽然现代深度学习框架已经封装了这些细节,但理解底层原理对于调试模型和解决实际问题至关重要。建议动手实现几次,直到能够不参考代码独立完成。
正文完
