BP神经网络反向传播算法:从数学原理到Python实现

1次阅读
没有评论

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

image.webp

为什么说 BP 算法是深度学习的基石?

BP 算法是神经网络训练的引擎,通过误差反向传播调整权重;它解决了多层网络参数优化的核心难题;现代深度学习框架(如 PyTorch/TensorFlow)的自动微分机制本质仍是 BP 思想的延伸。

BP 神经网络反向传播算法:从数学原理到 Python 实现

数学原理拆解

链式法则:误差传播的放大器

想象瀑布的多级落差,每层神经元误差信号如同水流:
$$\frac{\partial E}{\partial w_{ij}} = \frac{\partial E}{\partial o_j} \cdot \frac{\partial o_j}{\partial net_j} \cdot \frac{\partial net_j}{\partial w_{ij}}$$
其中 $net_j$ 是加权输入,$o_j$ 是激活输出,$E$ 是损失函数。

梯度下降的矩阵之美

对于全连接层,权重更新可向量化表示为:
$$W_{new} = W – \eta \cdot \frac{1}{m} (\delta^{l+1} \cdot (a^l)^T)$$
其中 $\eta$ 是学习率,$m$ 是样本数,$\delta$ 是误差项,$a$ 是激活值。

激活函数导数对比

  • Sigmoid:$\sigma'(x) = \sigma(x)(1-\sigma(x))$(易梯度消失)
  • tanh:$1 – \tanh^2(x)$(梯度略大于 Sigmoid)
  • ReLU:$\text{max}(0,x)$ 的导数为阶跃函数(缓解梯度消失但可能神经元死亡)

Python 实现(NumPy 版)

import numpy as np

class ThreeLayerBP:
    def __init__(self, input_size, hidden_size, output_size):
        self.W1 = np.random.randn(input_size, hidden_size) * 0.01
        self.b1 = np.zeros(hidden_size)
        self.W2 = np.random.randn(hidden_size, output_size) * 0.01
        self.b2 = np.zeros(output_size)

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

    def forward(self, X):
        self.z1 = np.dot(X, self.W1) + self.b1  # 隐藏层加权输入
        self.a1 = self.sigmoid(self.z1)          # 激活输出
        self.z2 = np.dot(self.a1, self.W2) + self.b2
        return self.sigmoid(self.z2)

    def backward(self, X, y, lr=0.1):
        m = X.shape[0]
        # 输出层误差
        delta2 = (self.a2 - y) * self.a2 * (1 - self.a2)  # ∂E/∂z2
        # 隐藏层误差(关键反向传播步骤)delta1 = np.dot(delta2, self.W2.T) * self.a1 * (1 - self.a1)

        # 参数更新(注意矩阵转置顺序)self.W2 -= lr * np.dot(self.a1.T, delta2) / m
        self.b2 -= lr * np.mean(delta2, axis=0)
        self.W1 -= lr * np.dot(X.T, delta1) / m
        self.b1 -= lr * np.mean(delta1, axis=0)

五大避坑实践

梯度裁剪:防止梯度爆炸

grad_norm = np.linalg.norm(gradients)
if grad_norm > threshold:
    gradients = gradients * threshold / grad_norm

Batch Normalization 集成

推荐在隐藏层后添加:

from torch.nn import BatchNorm1d  # 即使使用 NumPy 也可参考此逻辑
bn = BatchNorm1d(hidden_size)
normalized = bn(torch.from_numpy(a1)).numpy()

学习率衰减策略

initial_lr = 0.1
for epoch in range(epochs):
    lr = initial_lr * (0.95 ** epoch)  # 指数衰减
    model.backward(X_batch, y_batch, lr)

思考题

  1. 如何用 PyTorch 的 autograd 重构权重更新逻辑?提示:requires_grad=Trueoptimizer.step()
  2. 对比发现:当使用 Adam 优化器时,初始学习率设为多少时效果优于 SGD?为什么?
正文完
 0
评论(没有评论)