深度学习入门:2.1.5前向传播与反向传播算法原理与实现详解

1次阅读
没有评论

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

image.webp

神经网络基础回顾

神经网络由多层神经元组成,每一层通过权重矩阵 $W$ 和偏置向量 $b$ 连接到下一层。一个典型的全连接网络(FCN)中,第 $l$ 层的输出 $a^l$ 通过激活函数 $\sigma$ 处理:

深度学习入门:2.1.5 前向传播与反向传播算法原理与实现详解

$$
a^l = \sigma(W^l a^{l-1} + b^l)
$$

其中输入层 $a^0=X$ 为原始数据,输出层 $a^L$ 为预测结果。训练目标是找到最优参数 $\theta={W,b}$ 使得损失函数 $J(\theta)$ 最小化。


前向传播算法详解

前向传播是数据从输入层流向输出层的过程,核心步骤:

  1. 线性变换:$z^l = W^l a^{l-1} + b^l$
  2. 激活计算:$a^l = \sigma(z^l)$

以 Sigmoid 激活函数为例:

$$
\sigma(z) = \frac{1}{1+e^{-z}}
$$

前向传播最终输出预测值 $\hat{y}=a^L$,并与真实值 $y$ 比较计算损失(如交叉熵损失):

$$
J(\theta) = -\frac{1}{m}\sum_{i=1}^m [y^{(i)}\log\hat{y}^{(i)} + (1-y^{(i)})\log(1-\hat{y}^{(i)})]
$$


反向传播算法推导

反向传播通过链式法则计算损失对各参数的梯度:

  1. 输出层误差:$\delta^L = \nabla_a J \odot \sigma'(z^L)$
  2. 隐藏层误差:$\delta^l = (W^{l+1})^T \delta^{l+1} \odot \sigma'(z^l)$
  3. 参数梯度
  4. $\frac{\partial J}{\partial W^l} = \delta^l (a^{l-1})^T$
  5. $\frac{\partial J}{\partial b^l} = \delta^l$

其中 $\odot$ 表示逐元素乘法。推导时需注意 Sigmoid 的导数为 $\sigma'(z)=\sigma(z)(1-\sigma(z))$。


Python 实现与代码解析

import numpy as np

class NeuralNetwork:
    def __init__(self, layers):
        # 初始化权重和偏置
        self.W = [np.random.randn(y, x)*0.01 for x,y in zip(layers[:-1], layers[1:])]
        self.b = [np.zeros((y,1)) for y in layers[1:]]

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

    def forward(self, X):
        # 前向传播
        self.a = [X]
        for W, b in zip(self.W, self.b):
            z = np.dot(W, self.a[-1]) + b
            self.a.append(self.sigmoid(z))
        return self.a[-1]

    def backward(self, X, y, learning_rate):
        # 反向传播
        m = X.shape[1]
        delta = (self.a[-1] - y) * self.a[-1] * (1-self.a[-1])  # 输出层误差

        for l in range(len(self.W)-1, -1, -1):
            dW = np.dot(delta, self.a[l].T)/m
            db = np.sum(delta, axis=1, keepdims=True)/m

            # 参数更新
            self.W[l] -= learning_rate * dW
            self.b[l] -= learning_rate * db

            if l > 0:  # 计算下一层误差
                delta = np.dot(self.W[l].T, delta) * self.a[l] * (1-self.a[l])

关键实现说明:
1. 权重初始化采用小随机数(乘以 0.01),避免初始激活值饱和
2. 批量处理时梯度需除以样本数 m(/m
3. 反向传播时需倒序处理各层参数


常见问题与优化方案

梯度消失 / 爆炸

  • 现象:深层网络中梯度指数级减小或增大
  • 解决方案
  • 使用 ReLU 等非饱和激活函数
  • 权重初始化改进(如 He 初始化)
  • 残差连接(ResNet)

训练振荡

  • 现象:损失值波动大
  • 解决方案
  • 学习率衰减(如 lr *= 0.95 每 epoch)
  • 动量优化(Momentum/RMSprop)
  • 梯度裁剪(np.clip(grad, -1, 1)

过拟合

  • 方案
  • Dropout(训练时随机断开神经元)
  • L2 正则化(损失函数中添加 $\frac{\lambda}{2}||W||^2$)

实践任务与思考题

任务:修改上述代码实现以下实验:
1. 将网络结构改为[2,4,3,1],观察训练效果变化
2. 尝试用 ReLU 替换 Sigmoid,需调整反向传播的导数计算
3. 添加学习率衰减策略(如每 100 步降低 10%)

思考
– 为什么深层网络更容易出现梯度消失?
– 批量归一化(BatchNorm)如何帮助解决梯度问题?
– 如何验证反向传播计算的正确性?(提示:梯度检查)


通过这篇教程,你应该已经掌握了前向传播与反向传播的核心原理和实现方法。建议动手实践时配合 TensorBoard 等工具可视化训练过程,这将帮助你更直观地理解神经网络的运作机制。

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