现在我们已经介绍了损失函数、梯度下降和反向传播算法的理念,接下来通过手动计算一个非常小的神经网络的梯度来巩固这些认识。这个练习有助于直观了解链式法则如何运作,以弄清每个参数如何影响总误差。考虑一个简单的网络,它有一个输入、一个隐藏神经元(使用Sigmoid激活函数)和一个输出神经元(也使用Sigmoid)。我们的目标是计算权重($w_1$, $w_2$)和偏置($b_1$, $b_2$)的变化如何影响单个训练样本的最终损失。digraph G { rankdir=TB; node [shape=circle, style=filled, color="#a5d8ff", fontname="helvetica"]; edge [fontname="helvetica"]; x [label="x"]; h [label="h", color="#96f2d7"]; o [label="o", color="#ffc9c9"]; b1 [label="b1", shape=plaintext]; b2 [label="b2", shape=plaintext]; x -> h [label="w1"]; b1 -> h [style=dashed]; h -> o [label="w2"]; b2 -> o [style=dashed]; subgraph cluster_0 { style=filled; color="#e9ecef"; node [style=filled,color=white]; x; label = "输入层"; } subgraph cluster_1 { style=filled; color="#e9ecef"; node [style=filled,color=white]; h; b1; label = "隐藏层 (Sigmoid)"; } subgraph cluster_2 { style=filled; color="#e9ecef"; node [style=filled,color=white]; o; b2; label = "输出层 (Sigmoid)"; } }一个包含一个输入、一个隐藏神经元和一个输出神经元的简单前馈网络。网络设置我们来定义组件和初始值:输入:$x = 0.5$目标输出:$y = 0.8$权重:$w_1 = 0.2$, $w_2 = 0.9$偏置:$b_1 = 0.1$, $b_2 = -0.3$激活函数:Sigmoid,$\sigma(z) = \frac{1}{1 + e^{-z}}$。其导数为$\sigma'(z) = \sigma(z)(1 - \sigma(z))$。损失函数:均方误差 (MSE),$L = \frac{1}{2}(y - o)^2$。其对输出 $o$ 的导数为$\frac{\partial L}{\partial o} = o - y$。1. 前向传播首先,我们计算给定输入($x$)和参数下网络的输出($o$)。隐藏层预激活值 ($z_1$): $$ z_1 = w_1 x + b_1 = (0.2 \times 0.5) + 0.1 = 0.1 + 0.1 = 0.2 $$隐藏层激活值 ($h$): $$ h = \sigma(z_1) = \sigma(0.2) = \frac{1}{1 + e^{-0.2}} \approx \frac{1}{1 + 0.8187} \approx 0.5498 $$输出层预激活值 ($z_2$): $$ z_2 = w_2 h + b_2 = (0.9 \times 0.5498) + (-0.3) \approx 0.4948 - 0.3 = 0.1948 $$输出层激活值 ($o$): $$ o = \sigma(z_2) = \sigma(0.1948) = \frac{1}{1 + e^{-0.1948}} \approx \frac{1}{1 + 0.8230} \approx 0.5486 $$因此,网络的预测值为 $o \approx 0.5486$。2. 损失计算现在,使用MSE损失函数计算误差:$$ L = \frac{1}{2}(y - o)^2 = \frac{1}{2}(0.8 - 0.5486)^2 = \frac{1}{2}(0.2514)^2 \approx \frac{1}{2}(0.0632) \approx 0.0316 $$ 此样本的损失约为 $0.0316$。3. 反向传播 (梯度计算)我们的目标是求出梯度:$\frac{\partial L}{\partial w_2}$、$\frac{\partial L}{\partial b_2}$、$\frac{\partial L}{\partial w_1}$ 和 $\frac{\partial L}{\partial b_1}$。我们使用链式法则,从损失反向推导。损失对网络输出 ($o$) 的导数: $$ \frac{\partial L}{\partial o} = o - y \approx 0.5486 - 0.8 = -0.2514 $$输出层梯度 ($w_2, b_2$): 我们需要输出激活值 $o$ 对其预激活值 $z_2$ 的导数。 $$ \frac{\partial o}{\partial z_2} = \sigma'(z_2) = o (1 - o) \approx 0.5486 \times (1 - 0.5486) \approx 0.5486 \times 0.4514 \approx 0.2476 $$ 现在,应用链式法则求出损失对 $z_2$ 的梯度: $$ \frac{\partial L}{\partial z_2} = \frac{\partial L}{\partial o} \frac{\partial o}{\partial z_2} \approx (-0.2514) \times (0.2476) \approx -0.0622 $$ $w_2$ 和 $b_2$ 的梯度取决于 $z_2$ 相对于它们的变化方式: $$ \frac{\partial z_2}{\partial w_2} = h \approx 0.5498 $$ $$ \frac{\partial z_2}{\partial b_2} = 1 $$ 再次使用链式法则: $$ \frac{\partial L}{\partial w_2} = \frac{\partial L}{\partial z_2} \frac{\partial z_2}{\partial w_2} \approx (-0.0622) \times (0.5498) \approx -0.0342 $$ $$ \frac{\partial L}{\partial b_2} = \frac{\partial L}{\partial z_2} \frac{\partial z_2}{\partial b_2} \approx (-0.0622) \times 1 = -0.0622 $$隐藏层梯度 ($w_1, b_1$): 我们需要将梯度进一步反向传播。首先,求出损失对隐藏激活值 $h$ 的梯度: $$ \frac{\partial L}{\partial h} = \frac{\partial L}{\partial z_2} \frac{\partial z_2}{\partial h} $$ 我们需要$\frac{\partial z_2}{\partial h}$: $$ \frac{\partial z_2}{\partial h} = w_2 = 0.9 $$ 所以, $$ \frac{\partial L}{\partial h} \approx (-0.0622) \times 0.9 = -0.0560 $$ 接下来,我们需要隐藏激活值 $h$ 对其预激活值 $z_1$ 的导数: $$ \frac{\partial h}{\partial z_1} = \sigma'(z_1) = h (1 - h) \approx 0.5498 \times (1 - 0.5498) \approx 0.5498 \times 0.4502 \approx 0.2475 $$ 现在,应用链式法则求出损失对 $z_1$ 的梯度: $$ \frac{\partial L}{\partial z_1} = \frac{\partial L}{\partial h} \frac{\partial h}{\partial z_1} \approx (-0.0560) \times (0.2475) \approx -0.0139 $$ 最后,$w_1$ 和 $b_1$ 的梯度取决于 $z_1$ 相对于它们的变化方式: $$ \frac{\partial z_1}{\partial w_1} = x = 0.5 $$ $$ \frac{\partial z_1}{\partial b_1} = 1 $$ 最后一次使用链式法则: $$ \frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial z_1} \frac{\partial z_1}{\partial w_1} \approx (-0.0139) \times 0.5 = -0.0070 $$ $$ \frac{\partial L}{\partial b_1} = \frac{\partial L}{\partial z_1} \frac{\partial z_1}{\partial b_1} \approx (-0.0139) \times 1 = -0.0139 $$梯度总结我们手动计算了损失函数相对于每个参数的梯度:$\frac{\partial L}{\partial w_2} \approx -0.0342$$\frac{\partial L}{\partial b_2} \approx -0.0622$$\frac{\partial L}{\partial w_1} \approx -0.0070$$\frac{\partial L}{\partial b_1} \approx -0.0139$这些梯度表明每个参数需要改变的方向和大小,以减小损失。例如,像 $\frac{\partial L}{\partial w_2} \approx -0.0342$ 这样的负梯度表明,略微增加 $w_2$ 会减小损失(因为更新规则涉及减去梯度)。下一步在实际训练场景中,这些梯度将与选定的学习率($\eta$)一起使用,通过梯度下降来更新参数:$$ w_{new} = w_{old} - \eta \frac{\partial L}{\partial w_{old}} $$ $$ b_{new} = b_{old} - \eta \frac{\partial L}{\partial b_{old}} $$这种手动计算,虽然对于更大的网络会很繁琐,但清楚地展示了反向传播的机制,以及误差信号如何通过网络反向流动来指导参数更新。TensorFlow和PyTorch等框架自动化此过程,但理解其底层计算对于有效地构建模型和调试具有重要意义。