深入解析bp反向传播网络:从数学原理到实现细节

1次阅读
没有评论

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

image.webp

从链式法则理解反向传播

反向传播 (BP) 算法的核心是链式法则的递归应用。考虑一个简单三层网络(输入层、隐藏层、输出层),前向传播时:

深入解析 bp 反向传播网络:从数学原理到实现细节

  1. 隐藏层输出:$h = \sigma(W_1x + b_1)$
  2. 最终输出:$y = W_2h + b_2$
  3. 损失函数:$L = \frac{1}{2}(y – t)^2$(MSE 损失)

反向传播时,我们需要计算损失对每个参数的梯度:

  • $\frac{\partial L}{\partial W_2} = (y-t) \cdot h^T$
  • $\frac{\partial L}{\partial b_2} = (y-t)$
  • $\frac{\partial L}{\partial W_1} = (W_2^T(y-t)) \odot \sigma'(z) \cdot x^T$
  • $\frac{\partial L}{\partial b_1} = (W_2^T(y-t)) \odot \sigma'(z)$

其中 $\odot$ 表示逐元素相乘,$\sigma’$ 是激活函数的导数。

Python 实现细节

1. 网络层实现

import numpy as np

class DenseLayer:
    def __init__(self, input_size, output_size):
        self.W = np.random.randn(output_size, input_size) * 0.01
        self.b = np.zeros((output_size, 1))

    def forward(self, x):
        self.x = x  # 缓存输入用于反向传播
        return np.dot(self.W, self.x) + self.b

    def backward(self, dout):
        self.dW = np.dot(dout, self.x.T)
        self.db = np.sum(dout, axis=1, keepdims=True)
        return np.dot(self.W.T, dout)

class ReLU:
    def forward(self, x):
        self.mask = (x <= 0)
        return np.maximum(0, x)

    def backward(self, dout):
        dout[self.mask] = 0
        return dout

2. 损失函数与训练循环

class MSE:
    def __call__(self, y_pred, y_true):
        self.y_pred, self.y_true = y_pred, y_true
        return 0.5 * np.mean((y_pred - y_true)**2)

    def backward(self):
        return (self.y_pred - self.y_true) / len(self.y_true)

# 训练示例
for epoch in range(epochs):
    # 前向传播
    h1 = relu1(dense1(x))
    y = dense2(h1)
    loss = mse(y, t)

    # 反向传播
    dy = mse.backward()
    dh1 = dense2.backward(dy)
    dx = relu1.backward(dh1)
    _ = dense1.backward(dx)

    # 参数更新
    dense1.W -= lr * dense1.dW
    dense2.W -= lr * dense2.dW

关键问题讨论

梯度消失 / 爆炸

  • 成因:当网络较深时,梯度在反向传播过程中会连乘多个权重矩阵。如果权重初始化不当(如值过大或过小),会导致梯度指数级变化
  • 解决方案
  • 使用 Xavier/He 初始化
  • 加入 BatchNorm 层
  • 使用 ResNet 中的跳跃连接

激活函数选择

函数 梯度特性 适用场景
Sigmoid 最大 0.25 二分类输出层
Tanh 最大 1.0 RNN 隐藏层
ReLU 0 或 1 大多数前馈网络
LeakyReLU 0 或 α 解决神经元死亡

学习率调优

  1. 初始值通常设在 0.001-0.1 之间
  2. 使用学习率衰减:lr = initial_lr * (1 + decay * epoch)^(-1)
  3. 高级优化器(Adam)自动调整学习率

延伸思考

  1. 扩展到 CNN:需要实现卷积层的局部连接和参数共享特性,主要改动在:
  2. 前向传播使用 im2col 技巧
  3. 反向传播计算卷积核的梯度时需考虑感受野

  4. BatchNorm 影响

  5. 在反向传播时需要额外计算对均值和方差的梯度
  6. 使得各层输入的分布稳定,缓解梯度问题
  7. 实际实现时需维护 running_mean/running_var

  8. 二阶优化

  9. 牛顿法等需要计算 Hessian 矩阵
  10. 实际中常使用拟牛顿法(如 L -BFGS)
  11. 适合小批量数据场景
正文完
 0
评论(没有评论)