共计 1700 个字符,预计需要花费 5 分钟才能阅读完成。
1. BP 神经网络结构图解
先来看一个典型的三层 BP 网络结构(输入层 - 隐藏层 - 输出层):

输入层 隐藏层 输出层
(x1)─────► (h1)─────► (y1)
\ / \ /
\ / \ /
(x2) (h2)
- 输入层:2 个神经元(对应二维特征)
- 隐藏层:2 个神经元(带 Sigmoid 激活)
- 输出层:1 个神经元(回归任务)
权重矩阵维度关系:
- W1: 2×2 矩阵(输入层→隐藏层)
- W2: 2×1 矩阵(隐藏层→输出层)
2. 数学推导核心步骤
2.1 前向传播公式
隐藏层输出:
$$h = \sigma(W_1^T X + b_1)$$
最终输出:
$$\hat{y} = \sigma(W_2^T h + b_2)$$
2.2 反向传播推导(以 MSE 损失为例)
-
输出层梯度:
$$\frac{\partial L}{\partial W_2} = (\hat{y} – y) \cdot \sigma'(z_2) \cdot h$$ -
隐藏层梯度(链式法则应用):
$$\frac{\partial L}{\partial W_1} = \left[(\hat{y}-y) \cdot \sigma'(z_2) \cdot W_2\right] \odot \sigma'(z_1) \cdot X$$
符号说明:$\odot$ 表示逐元素乘法,$\sigma’$ 是 Sigmoid 导数
3. Python 实现关键代码
3.1 激活函数实现
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
return x * (1 - x) # 适用于已激活的值
3.2 前向传播
hidden_input = np.dot(X, W1) + b1
hidden_output = sigmoid(hidden_input)
final_input = np.dot(hidden_output, W2) + b2
prediction = sigmoid(final_input)
3.3 反向传播核心
# 输出层误差
delta_output = (y - prediction) * sigmoid_derivative(prediction)
# 隐藏层误差
delta_hidden = delta_output.dot(W2.T) * sigmoid_derivative(hidden_output)
# 权重更新
W2 += hidden_output.T.dot(delta_output) * lr
W1 += X.T.dot(delta_hidden) * lr
4. 性能优化实践
4.1 批量训练 vs 在线训练
- 批量训练:每轮 epoch 更新一次权重,收敛稳定但内存占用高
- 在线训练:每个样本更新权重,收敛快但波动大
推荐折中方案:mini-batch(批量大小 32-256)
4.2 隐藏层神经元数量经验公式
$$N_h = \frac{N_i + N_o}{2} + \sqrt{N_{samples}}}$$
其中:
– $N_i$: 输入神经元数
– $N_o$: 输出神经元数
4.3 梯度检查实现
def gradient_check(W, f, epsilon=1e-7):
grad_approx = (f(W + epsilon) - f(W - epsilon)) / (2 * epsilon)
return np.linalg.norm(grad_approx - compute_gradient(W))
5. 实战避坑指南
5.1 数据标准化
- 输入特征建议缩放到 [0,1] 或[-1,1]
- 异常值会导致梯度爆炸
5.2 权重初始化
- Xavier 初始化:$W \sim U(-\sqrt{6/n_{in}+n_{out}}, \sqrt{6/n_{in}+n_{out}}})$
- 避免全零初始化(会导致对称性问题)
5.3 学习率调参
- 典型初始值:0.01-0.1
- 损失曲线震荡 → 学习率过大
- 收敛过慢 → 学习率过小
6. 拓展思考
- 多分类改造:
- 输出层改用 softmax 激活
-
损失函数换成交叉熵
-
ReLU vs Sigmoid:
- ReLU 导数恒为 1(正区间),缓解梯度消失
- Sigmoid 导数最大仅 0.25,多层时梯度指数衰减
完整代码示例见 GitHub 仓库(链接需补充)
通过这个从结构图到代码实现的完整流程,相信大家对 BP 神经网络的核心机制有了直观认识。建议动手修改隐藏层数量和激活函数,观察模型表现的变化。
正文完
