共计 1968 个字符,预计需要花费 5 分钟才能阅读完成。
1. 认识 BP 神经网络基础结构
先看最简单的三层网络示意图(输入层 - 隐藏层 - 输出层):

输入层(x) 隐藏层(h) 输出层(y)
○---w1--->○---w2--->○
○---w1--->○---w2--->○
○---w1--->○---w2--->○
- 维度关系:若输入 3 个特征,隐藏层 2 个神经元,输出 1 个值,则:
- w1.shape = (3,2)
- w2.shape = (2,1)
- 前向传播公式:
$$h = \sigma(x \cdot w1 + b1)$$
$$y = \sigma(h \cdot w2 + b2)$$
2. 数学推导:误差是如何反向传播的?
以均方误差损失函数为例:
$$L = \frac{1}{2}(y_{true} – y_{pred})^2$$
关键推导步骤:
1. 输出层权重梯度:
$$\frac{\partial L}{\partial w2} = \underbrace{-(y_{true}-y)}{\text{误差项}} \cdot \underbrace{\sigma'(z2)}$$}} \cdot \underbrace{h}_{\text{前一层的输出}
- 隐藏层权重梯度(链式法则典型应用):
$$\frac{\partial L}{\partial w1} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial h} \cdot \frac{\partial h}{\partial w1}$$
3. Python 实现核心代码
import numpy as np
# 激活函数与导数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
return x * (1 - x)
# 网络初始化
input_size = 3
hidden_size = 2
output_size = 1
w1 = np.random.randn(input_size, hidden_size) * 0.01
w2 = np.random.randn(hidden_size, output_size) * 0.01
# 前向传播
def forward(x):
h = sigmoid(np.dot(x, w1))
y = sigmoid(np.dot(h, w2))
return h, y
# 反向传播
def backward(x, y_true, h, y, lr=0.1):
# 输出层误差
dy = (y - y_true) * sigmoid_derivative(y)
grad_w2 = np.dot(h.T, dy)
# 隐藏层误差
dh = np.dot(dy, w2.T) * sigmoid_derivative(h)
grad_w1 = np.dot(x.T, dh)
# 更新权重
w2 -= lr * grad_w2
w1 -= lr * grad_w1
4. 性能优化实战技巧
训练策略选择
- 批量训练:更稳定的梯度方向,适合 GPU 并行
- 在线训练:更快响应数据变化,适合流式数据
超参数设置经验
- 隐藏层神经元数量参考公式:
$$N_{hidden} = \sqrt{N_{input} \cdot N_{output}} + \alpha$$
(α 通常取 10-20)
梯度检查实现(调试必备)
def gradient_check(x, y_true, eps=1e-7):
_, y = forward(x)
original_loss = 0.5 * (y_true - y)**2
# 检查 w2 的梯度
numeric_grad = np.zeros_like(w2)
for i in range(w2.shape[0]):
for j in range(w2.shape[1]):
w2[i,j] += eps
_, y_perturb = forward(x)
perturb_loss = 0.5 * (y_true - y_perturb)**2
numeric_grad[i,j] = (perturb_loss - original_loss) / eps
w2[i,j] -= eps # 恢复
# 与反向传播结果对比
print("数值梯度:", numeric_grad)
print("解析梯度:", grad_w2)
5. 新手避坑指南
数据预处理
- 标准化 :将输入缩放到[-1,1] 或[0,1]范围
X = (X - np.mean(X, axis=0)) / np.std(X, axis=0)
权重初始化
- Xavier 初始化(适合 Sigmoid):
$$W \sim U(-\sqrt{6/(n_{in}+n_{out})}, \sqrt{6/(n_{in}+n_{out})})$$
学习率调参
- 损失曲线震荡 → 学习率过大
- 收敛速度过慢 → 学习率过小
- 推荐初始值:0.01-0.1
6. 拓展思考
- 多分类改造:
- 输出层改用 Softmax
-
损失函数换成交叉熵
-
激活函数对比:
- ReLU 在反向传播时梯度为 1 或 0,缓解梯度消失
- Sigmoid 容易饱和导致梯度消失
建议尝试:用相同的网络结构,仅替换激活函数,观察训练收敛速度差异
正文完
