BP神经网络反向传播计算例题详解:从数学推导到Python实现

1次阅读
没有评论

共计 1840 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

从单层感知机到多层网络

在理解反向传播之前,我们先回顾单层感知机的梯度计算。假设有一个简单的线性模型:$y = w^Tx + b$,采用均方误差损失函数 $L = \frac{1}{2}(y – t)^2$(t 为真实值),其梯度计算为:

BP 神经网络反向传播计算例题详解:从数学推导到 Python 实现

$$
\frac{\partial L}{\partial w} = (y – t)x
$$

这个简单的求导过程是理解反向传播的基础。当我们扩展到多层神经网络时,需要通过链式法则将误差从输出层逐层反向传播。

三层网络计算例题

我们构建一个 3 层网络结构(输入层 2 节点,隐藏层 2 节点,输出层 1 节点),使用 Sigmoid 激活函数,并假设:

  • 输入 $x = [0.5, 0.1]$
  • 真实输出 $t = 0.7$
  • 初始权重(为演示随机设定):
  • $W_1 = [[0.1, 0.2], [0.3, 0.4]]$
  • $W_2 = [0.5, 0.6]$
  • 偏置全设为 0

前向传播步骤

  1. 计算隐藏层输入:
    $h_{in} = W_1^T x = [0.10.5 + 0.30.1, 0.20.5 + 0.40.1] = [0.08, 0.14]$

  2. 应用 Sigmoid 激活:
    $h_{out} = \sigma(h_{in}) = [\frac{1}{1+e^{-0.08}}, \frac{1}{1+e^{-0.14}}] \approx [0.52, 0.535]$

  3. 计算输出层结果:
    $y = W_2^T h_{out} = 0.50.52 + 0.60.535 \approx 0.571$

反向传播步骤

  1. 计算输出层误差:
    $\delta_y = (y – t) = 0.571 – 0.7 = -0.129$

  2. 隐藏层误差(注意 Sigmoid 导数 $\sigma'(z) = \sigma(z)(1-\sigma(z))$):

$$
\delta_h = W_2 \cdot \delta_y \cdot \sigma'(h_{in})
= [0.5-0.1290.52(1-0.52), 0.6-0.1290.535(1-0.535)]
\approx [-0.016, -0.02]
$$

  1. 权重更新(设学习率 $\eta=0.1$):

  2. $\Delta W_2 = -\eta \cdot \delta_y \cdot h_{out} \approx -0.1-0.129[0.52, 0.535] \approx [0.0067, 0.0069]$

  3. $\Delta W_1 = -\eta \cdot \delta_h \cdot x \approx -0.1*[-0.016, -0.02] * [0.5, 0.1]$

Python 实现

import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 初始化参数
x = np.array([0.5, 0.1])
t = 0.7
W1 = np.array([[0.1, 0.2], [0.3, 0.4]])
W2 = np.array([0.5, 0.6])
lr = 0.1

# 前向传播
h_in = np.dot(W1.T, x)
h_out = sigmoid(h_in)
y = np.dot(W2.T, h_out)

# 反向传播
delta_y = y - t
delta_h = W2 * delta_y * h_out * (1 - h_out)

# 权重更新
dW2 = -lr * delta_y * h_out
dW1 = -lr * np.outer(x, delta_h)

print(f"预测值: {y:.3f}")
print(f"W1 梯度: \n{dW1}")
print(f"W2 梯度: {dW2}")

常见问题

梯度消失问题

当使用 Sigmoid 激活函数时,其导数最大值为 0.25(当输入为 0 时),这意味着在深层网络中梯度会指数级缩小,导致底层权重几乎不更新。解决方案包括:

  • 使用 ReLU 等激活函数
  • 采用残差连接
  • 使用批量归一化

学习率选择

学习率过大会导致震荡无法收敛,过小则收敛缓慢。实践中可以:

  1. 从 0.01 或 0.001 开始尝试
  2. 观察损失曲线,如果剧烈波动则调小
  3. 采用学习率衰减策略

激活函数选择

  • ReLU:计算简单,缓解梯度消失,但可能导致神经元 ” 死亡 ”
  • LeakyReLU:解决 ReLU 的死亡问题
  • Sigmoid:适合二分类输出层
  • Tanh:输出中心化,但仍有梯度消失

延伸思考

  1. 验证实现正确性
  2. 对比数值梯度(通过微小扰动计算)与反向传播梯度
  3. 使用已知输入输出的小型测试案例

  4. 批量训练 vs 在线训练

  5. 批量训练:梯度估计更准确,但内存要求高
  6. 在线训练:更快收敛到局部最优,但梯度噪声大
  7. 折中方案:小批量梯度下降(mini-batch)

通过这个完整的例题,相信你对反向传播的数学原理和实现有了更直观的理解。建议尝试修改网络结构参数,观察不同情况下梯度的变化规律,这对理解神经网络训练过程大有裨益。

正文完
 0
评论(没有评论)