共计 1062 个字符,预计需要花费 3 分钟才能阅读完成。
反向传播算法是神经网络训练的基石,通过误差的逆向传递高效计算梯度,实现了多层网络的参数优化。本文将以一个二分类问题为例,带你从数学推导到代码实现完整走一遍 BP 算法的流程。

网络结构与计算图
我们构建包含 1 个隐藏层的网络(2-3- 1 结构),计算图如下:
输入层 (x1,x2) → 隐藏层 (h1,h2,h3) → 输出层 (y)
数学推导分步解析
1. 前向传播过程
-
隐藏层计算:
$$h_j = \sigma(\sum_{i=1}^2 w_{ij}x_i + b_j)$$
其中 $\sigma$ 为 sigmoid 激活函数 -
输出层计算:
$$y = \sigma(\sum_{j=1}^3 v_j h_j + c)$$
2. 损失函数与输出层梯度
使用交叉熵损失函数:
$$L = -[t\ln y + (1-t)\ln(1-y)]$$
对输出层权重 $v_j$ 求偏导:
$$\frac{\partial L}{\partial v_j} = (y-t)h_j$$
3. 隐藏层梯度计算(链式法则)
-
误差项计算:
$$\delta_h = (y-t)v_j \cdot h_j(1-h_j)$$ -
权重梯度:
$$\frac{\partial L}{\partial w_{ij}} = \delta_h x_i$$
Python 实现核心代码
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
# 前向传播
def forward(x, w, v):
h = sigmoid(w.T @ x) # 隐藏层输出
y = sigmoid(v.T @ h) # 最终输出
return h, y
# 反向传播
def backward(x, h, y, t, v):
# 输出层梯度
dL_dv = (y - t) * h
# 隐藏层梯度
dL_dh = (y - t) * v
dL_dw = dL_dh * h*(1-h) * x
return dL_dw, dL_dv
避坑指南
- 梯度消失处理 :
- 使用 ReLU 代替 sigmoid
-
加入梯度裁剪:
grad = np.clip(grad, -1, 1) -
权重初始化 :
-
He 初始化:
w = np.random.randn(n,m) * np.sqrt(2/n) -
学习率设置 :
- 初始值建议 0.01-0.1
- 加入衰减:
lr *= 0.95每 10 个 epoch
思考题
- 如何修改代码实现批量梯度下降?
-
提示:将输入 x 改为矩阵形式,求平均梯度
-
ReLU 激活函数对梯度计算的影响?
- 提示:导数在正区间为 1,缓解梯度消失
完整的可运行代码已放在 GitHub 仓库(伪代码,实际需补充完整实现)。通过这个例子,相信你对反向传播的数学本质和实现细节有了更清晰的认识。建议动手修改网络结构,观察不同激活函数的表现差异,这是掌握神经网络的最佳方式。
