(GPT 为共同创作者)
想象一个多层神经网络:输入 → 隐藏层 → 输出。训练的目标是 调整每个权重,使得网络输出更接近目标(标签)。反向传播的核心想法是:
先做一次 前向传播,计算每层的输出和最终损失(loss)。
然后把损失 从输出层向输入层传播回去,用链式法则计算每个参数对损失的偏导数(梯度)。
最后用梯度下降类方法更新参数(如:$w \leftarrow w − \eta \cdot \frac{\partial E}{\partial w}$)。
反向传播本质上是把链式求导(chain rule)系统化、按层计算偏导,从而高效得到每个权重的梯度。
链式法则(单变量形式): 如果 $z = f(y)$ 且 $y = g(x)$,那么
\[\frac{dz}{dx} = \frac{dz}{dy} \cdot \frac{dy}{dx}.\]神经网络时,输出是很多嵌套函数的组合(激活、加权和、激活……),链式法则把整体导数拆成许多层的局部导数的乘积。
单个神经元:
输入向量 $x = (x_1, \dots, x_n)$
权重 $w = (w_1, \dots, w_n)$,偏置 $b$
线性组合 $z = w \cdot x + b$
激活 $a = \sigma(z)$ (常见的 $\sigma$:sigmoid、ReLU 等)
损失 $E$(例如二次损失 $E = \frac{1}{2} (y-a)^2$)
对权重的梯度:
\[\frac{\partial E}{\partial w_i} = \frac{\partial E}{\partial a} \cdot \frac{\partial a}{\partial z} \cdot \frac{\partial z}{\partial w_i} = \delta \cdot x_i,\]其中 $\delta \triangleq \frac{\partial E}{\partial z} = \frac{\partial E}{\partial a} \cdot \sigma’(z)$。
偏置的梯度是 $\frac{\partial E}{\partial b} = \delta$(因为 $z$ 对 $b$ 的导数是 1)。
输出层:直接根据损失函数对输出的导数计算 $\delta^{(L)}$(输出层的误差项)。
隐藏层:使用上层的 $\delta$ 和上层到本层的权重,通过矩阵乘和本层激活导数计算本层 $\delta$。
向量化形式(简写)—— 对第 $l$ 层:
前向: $z^{(l)} = W^{(l)} a^{(l-1)} + b^{(l)}$, $a^{(l)} = \sigma(z^{(l)})$
反向: 若损失 $E$ 关于输出层 $a^{(L)}$ 已有 $\delta^{(L)}$,则
\[\delta^{(l)} = \big[ (W^{(l+1)})^\top \delta^{(l+1)} \big] \odot \sigma'(z^{(l)})\]($\odot$ 表示逐元素乘,$\sigma’$ 表示激活函数的导数按元素)
权重梯度: $\frac{\partial E}{\partial W^{(l)}} = \delta^{(l)} (a^{(l-1)})^\top$
偏置梯度: $\frac{\partial E}{\partial b^{(l)}} = \delta^{(l)}$(按样本求和 / 平均)
这是反向传播的 “矩阵/向量化” 版本,用于实际实现(速度快,易于并行)。
下面给出一个 简单 2-2-1 网络 的单样本向前与反向过程(使用 sigmoid 激活和均方误差),并 逐步计算每个中间值与梯度。
网络结构与初始参数(示例):
输入 $x_1 = 0.05 , x_2 = 0.10$
隐藏层两个神经元(都用相同偏置)
权重到隐藏层:
$w^{(1)} \cdot {11} = 0.15 , w^{(1)} \cdot {12} = 0.20$ (第一隐藏神经元对应 $x_1$ 的权重与 $x_2$ 的权重)
$w^{(1)} \cdot {21} = 0.25 , w^{(1)} \cdot {22} = 0.30$ (第二隐藏神经元对应 $x_1$、$x_2$)
隐藏层偏置: $b^{(1)}_1 = b^{(1)}_2 = 0.35$
输出层(1 个神经元)
权重: $w^{(2)}_1 = 0.40$(连到 h1), $w^{(2)}_2 = 0.45$(连到 h2)
偏置: $b^{(2)} = 0.60$
目标输出(标签): $t = 0.01$
激活函数:sigmoid $\sigma(z) = 1/(1+e^{-z})$
损失:均方误差 $E = \frac{1}{2} (t - o)^2$
隐藏单元 1 的净输入:
\[z^{(1)} \cdot 1 = w^{(1)} \cdot {11}x_1 + w^{(1)}_{21}x_2 + b^{(1)}_1 = 0.15 \times 0.05 + 0.25 \times 0.10 + 0.35.\]逐项计算:
0.15 × 0.05 = 0.0075.
0.25 × 0.10 = 0.025.
相加:0.0075 + 0.025 = 0.0325。再加偏置 0.35:
$z^{(1)}_1 = 0.32 + 0.0125$? 小心 —— 实际合计是 $0.0075 + 0.025 = 0.0325$,$0.0325+0.35 = 0.3825$。(确切值)
隐藏单元 1 的激活(sigmoid):
\[h_1 = \sigma(0.3825) = \frac{1}{1+e^{-0.3825}}.\]计算近似: $e^{-0.3825} \approx 0.682$,因此 $h_1 \approx \frac{1}{1 + 0.682} \approx 0.594$. (记为 $h_1 \approx 0.594$)
隐藏单元 2 的净输入:
\[z^{(1)}_2 = 0.20 \times 0.05 + 0.30 \times 0.10 + 0.35.\]逐项:
$0.20 \times 0.05 = 0.01$
$0.30 \times 0.10 = 0.03$
相加 $0.01 + 0.03 = 0.04,0.04 + 0.35 = 0.39$
激活:
\[h_2 = \sigma(0.39) \approx 1/(1+e^{-0.39}) \approx 0.598.\]输出单元的净输入:
\[z^{(2)} = w^{(2)}_1 h_1 + w^{(2)}_2 h_2 + b^{(2)} = 0.40 \times 0.594 + 0.45 \times 0.598 + 0.60.\]逐项:
$0.40×0.594 = 0.2376.$
$0.45×0.598 = 0.2691.$
相加:$0.2376 + 0.2691 = 0.5067$。再加偏置 $0.60$:
$z^{(2)} = 0.5067 + 0.60 = 1.1067.$
输出激活(网络输出):
\[o = \sigma(1.1067) \approx 1/(1+e^{-1.1067}).\]计算: $e^{-1.1067} \approx 0.331$,所以 $o \approx \frac {1}{1 + 0.331} \approx 0.751$.
损失(单样本):
\[E = \frac{1}{2} (t - o)^2 = \frac{1}{2} (0.01 - 0.751)^2.\]先差值: $0.01 - 0.751 = -0.741$.
平方: $(-0.741)^2 = 0.549081$.
乘 $\frac{1}{2}$: $E \approx 0.27454$.
目标:计算每个权重的 $\frac{\partial E}{\partial w}$。
定义 $\delta^{(2)} = \frac{\partial E}{\partial z^{(2)}}$.
用链式: $\frac{\partial E}{\partial o} = o - t$(因为 $E=\frac12(t-o)^2$),又 $o = \sigma(z)$,所以:
\[\delta^{(2)} = (o-t)\cdot \sigma'(z^{(2)}).\]sigmoid 导数 $\sigma’(z)=\sigma(z)(1-\sigma(z))$。
计算:
$o - t = 0.751 - 0.01 = 0.741.$
$\sigma’(z^{(2)}) = o(1-o) = 0.751\times(1-0.751) = 0.751\times0.249 \approx 0.187$.
因此
\[\delta^{(2)} \approx 0.741 \times 0.187 = 0.138567 \approx 0.1386.\]把数值代入:
\[\frac{\partial E}{\partial w^{(2)}_1} \approx 0.1386 \times 0.594 \approx 0.0823.\]类似地:
\[\frac{\partial E}{\partial w^{(2)}_2} \approx 0.1386 \times 0.598 \approx 0.0829.\]偏置的梯度:
\[\frac{\partial E}{\partial b^{(2)}} = \delta^{(2)} \approx 0.1386.\]隐藏单元 $j$ 的误差项:
\[\delta^{(1)}_j = \big(w^{(2)}_j \cdot \delta^{(2)}\big) \cdot \sigma'(z^{(1)}_j).\]先计算 $\sigma’(z^{(1)}_1) = h_1(1-h_1) \approx 0.594 \times 0.406 \approx 0.241$
$w^{(2)}_1 \cdot \delta^{(2)} = 0.40 \times 0.1386 = 0.05544.$
所以 $\delta^{(1)}_1 \approx 0.05544 \times 0.241 = 0.01336.$
第二个隐藏单元:
$\sigma’(z^{(1)}_2) = h_2(1-h_2) \approx 0.598 \times 0.402 = 0.240.$
$w^{(2)}_2 \cdot \delta^{(2)} = 0.45 \times 0.1386 = 0.06237.$
$\delta^{(1)}_2 \approx 0.06237 \times 0.240 = 0.01497.$
对权重 $w^{(1)} \cdot {11}$(从 $x_1$ 到隐藏单位 $1$):
\[\frac{\partial E}{\partial w^{(1)} \cdot {11}} = \delta^{(1)} \cdot 1 \cdot x_1 \approx 0.01336 \times 0.05 = 0.000668.\]对 $w^{(1)} \cdot {21}$(从 $x_2$ 到隐藏单位 $1$):
\[\frac{\partial E}{\partial w^{(1)} \cdot {21}} \approx 0.01336 \times 0.10 = 0.001336.\]对隐藏单元 $2$ 的权重:
\[\frac{\partial E}{\partial w^{(1)} \cdot {12}} \approx 0.01497 \times 0.05 = 0.000749.\] \[\frac{\partial E}{\partial w^{(1)}_{22}} \approx 0.01497 \times 0.10 = 0.001497.\]偏置梯度分别为 $\delta^{(1)}_1 \approx 0.01336$,$\delta^{(1)}_2\approx 0.01497$。
按梯度下降:
\[w \leftarrow w - \eta \frac{\partial E}{\partial w}\]举几个更新后的值(近似):
$w^{(2)} \cdot 1 \cdot {\text{new}} = 0.40 - 0.5 \times 0.0823 \approx 0.40 - 0.04115 = 0.35885.$
$w^{(2)} \cdot 2 \cdot {\text{new}} = 0.45 - 0.5 \times 0.0829 \approx 0.45 - 0.04145 = 0.40855.$
$b^{(2)}_{\text{new}} = 0.60 - 0.5 \times 0.1386 \approx 0.60 - 0.0693 = 0.5307.$
隐藏层权重:
$w^{(1)}_{11,\text{new}} = 0.15 - 0.5 \times 0.000668 \approx 0.15 - 0.000334 = 0.149666.$
$w^{(1)}_{21,\text{new}} = 0.25 - 0.5 \times 0.001336 \approx 0.249332.$
(其余按相同方法更新)
做一次这样的前向 + 反向并更新,损失会下降(通常如此),重复多次、使用多样本 / 小批量就能训练网络。
批处理(Batch / Mini-batch / Stochastic):通常使用 mini-batch(比如 32 或 128)来估计梯度更稳定、更高效。
学习率选择:太大会发散,太小收敛慢。常用自适应优化器:Adam、RMSprop、Adagrad;或者 SGD + momentum。
初始化权重:不应全部为零,常用 Xavier/He 初始化来防止信号在初始阶段消失或爆炸。
激活函数:sigmoid 会在深层网络导致梯度消失;ReLU 与其变种(Leaky ReLU、ELU)常用在隐藏层;输出层激活应与任务匹配(回归线性,二分类 sigmoid,多分类 softmax)。
正则化:L2(权重衰减)、dropout、批归一化(BatchNorm)等用于防止过拟合并稳定训练。
梯度裁剪(clipping):防止梯度爆炸(尤其在 RNN 中常用)。
数值稳定性:计算 softmax、log 等时要用稳定的数值技巧(减最大值等)。
反向传播不是“学习算法本身”,它只是 计算梯度 的有效方法。
反向传播依赖链式法则和每层局部导数 —— 如果激活函数不可导(如 ReLU 在 0 处不可导),在实现上通常对不可导点取次梯度(subgradient),实践中效果很好。
在深层网络中,梯度可能 衰减(vanishing) 或 爆炸(exploding),这需要用好初始化、归一化、残差连接等技巧来缓解。