文章

37 前向传播与反向传播

37 前向传播与反向传播

一、整体目标

  • 实现一个 L 层深度神经网络 的前向传播和反向传播。
  • 前向传播用于计算预测值 $\hat{y}$;
  • 反向传播用于计算损失函数对各参数的梯度($\frac{\partial \mathcal{L}}{\partial W^{[l]}}$, $\frac{\partial \mathcal{L}}{\partial b^{[l]}}$),用于参数更新。

二、前向传播(Forward Propagation)

1. 输入与输出

  • 第 $l$ 层的输入:$A^{[l-1]}$(即上一层的激活值)
  • 第 $l$ 层的输出:$A^{[l]}$
  • 缓存(cache):通常保存 $Z^{[l]}$,有时也包括 $W^{[l]}, b^{[l]}$

2. 核心公式(单样本或向量化)

  对于第 $l$ 层:

\[Z^{[l]} = W^{[l]} A^{[l-1]} + b^{[l]}\] \[A^{[l]} = g^{[l]}(Z^{[l]})\]

  其中:

  • $g^{[l]}(\cdot)$ 是第 $l$ 层的激活函数(如 ReLU、Sigmoid 等)
  • 若处理整个训练集(m 个样本),则 $A^{[0]} = X \in \mathbb{R}^{n_x \times m}$

初始化:$A^{[0]} = X$

3. 流程

  从第 1 层到第 L 层依次计算 $Z^{[l]}$ 和 $A^{[l]}$,最终得到预测值 $\hat{Y} = A^{[L]}$。


三、反向传播(Backward Propagation)

1. 目标

  • 输入:损失对当前层激活值的导数 $dA^{[l]} = \frac{\partial \mathcal{L}}{\partial A^{[l]}}$
  • 输出:

    • $dA^{[l-1]} = \frac{\partial \mathcal{L}}{\partial A^{[l-1]}}$
    • $dW^{[l]} = \frac{\partial \mathcal{L}}{\partial W^{[l]}}$
    • $db^{[l]} = \frac{\partial \mathcal{L}}{\partial b^{[l]}}$

2. 单样本反向传播公式(逐层)

\[dZ^{[l]} = dA^{[l]} \odot g^{[l]'}(Z^{[l]})\] \[dW^{[l]} = dZ^{[l]} (A^{[l-1]})^\top\] \[db^{[l]} = dZ^{[l]}\] \[dA^{[l-1]} = (W^{[l]})^\top dZ^{[l]}\]

其中 $\odot$ 表示 逐元素乘积(Hadamard product)

3. 向量化版本(处理 m 个样本)

\[dZ^{[l]} = dA^{[l]} \odot g^{[l]'}(Z^{[l]})\] \[dW^{[l]} = \frac{1}{m} dZ^{[l]} (A^{[l-1]})^\top\] \[db^{[l]} = \frac{1}{m} \sum_{i=1}^{m} dZ^{[l](i)} = \frac{1}{m} \text{np.sum}(dZ^{[l]}, \text{axis}=1, \text{keepdims=True})\] \[dA^{[l-1]} = (W^{[l]})^\top dZ^{[l]}\]

💡 注意:$dW^{[l]}$ 和 $db^{[l]}$ 需要对 m 个样本求平均(即除以 $m$)

4. 反向传播的初始化(最后一层)

  若使用 二分类交叉熵损失函数

\[\mathcal{L} = -\frac{1}{m} \sum_{i=1}^m \left[ y^{(i)} \log \hat{y}^{(i)} + (1 - y^{(i)}) \log (1 - \hat{y}^{(i)}) \right]\]

  则最后一层(第 L 层)的初始梯度为:

\[dA^{[L]} = \frac{\partial \mathcal{L}}{\partial A^{[L]}} = -\frac{Y}{A^{[L]}} + \frac{1 - Y}{1 - A^{[L]}}\]

这是反向传播的起点!


四、完整流程(以 3 层网络为例)

前向传播:

  1. $A^{[0]} = X$
  2. $Z^{[1]} = W^{[1]}X + b^{[1]}$, $A^{[1]} = \text{ReLU}(Z^{[1]})$
  3. $Z^{[2]} = W^{[2]}A^{[1]} + b^{[2]}$, $A^{[2]} = \text{ReLU}(Z^{[2]})$
  4. $Z^{[3]} = W^{[3]}A^{[2]} + b^{[3]}$, $A^{[3]} = \sigma(Z^{[3]}) = \hat{Y}$

反向传播:

  1. 计算 $dA^{[3]} = -\frac{Y}{A^{[3]}} + \frac{1 - Y}{1 - A^{[3]}}$
  2. 逐层反向计算:

    • $dZ^{[3]} = dA^{[3]} \odot \sigma’(Z^{[3]})$
    • $dW^{[3]} = \frac{1}{m} dZ^{[3]} (A^{[2]})^\top$, $db^{[3]} = \frac{1}{m} \sum dZ^{[3]}$
    • $dA^{[2]} = (W^{[3]})^\top dZ^{[3]}$
    • …… 依此类推至第 1 层

⚠️ 注意:通常不需要 $dA^{[0]}$,可丢弃。


五、关键要点总结

模块关键点
前向传播从输入 $X$ 开始,逐层计算 $Z^{[l]}$ 和 $A^{[l]}$,缓存 $Z^{[l]}$ 供反向使用
反向传播从损失函数出发,利用链式法则逐层回传梯度,计算 $dW^{[l]}, db^{[l]}$
激活函数导数必须知道 $g^{[l]’}(Z^{[l]})$,例如:
- ReLU: $g’(z) = \mathbb{1}_{z > 0}$
- Sigmoid: $\sigma’(z) = \sigma(z)(1 - \sigma(z))$
向量化所有操作均支持批量处理(m 个样本),效率更高
缓存设计前向时需缓存 $Z^{[l]}$(有时也包括 $A^{[l-1]}$),反向时直接调用

六、学习建议(来自吴恩达)

“如果你觉得这些公式很抽象,不要担心。当你动手完成编程作业时,一切会变得清晰。反向传播的数学推导确实复杂,但你只需要记住那 四个核心方程 就能正确实现。”

  • 动手实践比死记硬背更重要。
  • 深度学习的“魔法”往往来自 数据 而非代码长度。
  • 即使专家也会对模型成功感到惊讶——因为数据蕴含了巨大信息量。

附:常用激活函数及其导数(供参考)

激活函数 $g(z)$导数 $g’(z)$
Sigmoid: $\sigma(z) = \frac{1}{1 + e^{-z}}$$\sigma(z)(1 - \sigma(z))$
ReLU: $g(z) = \max(0, z)$$\mathbb{1}_{z > 0}$
Tanh: $g(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}$$1 - g(z)^2$
本文由作者按照 CC BY 4.0 进行授权