共计 2205 个字符,预计需要花费 6 分钟才能阅读完成。
核心概念
在开始具体的计算之前,我们先简单回顾几个关键概念:

- 神经网络:由输入层、隐藏层和输出层组成的网络结构,通过权重连接各层神经元
- 损失函数 :衡量网络预测值与真实值差异的函数,常见的有均方误差(MSE) 和交叉熵损失
- 反向传播:通过链式法则从输出层向输入层逐层计算梯度,用于更新权重
问题描述
假设我们有一个简单的 2 层神经网络:
- 输入层:2 个节点,值分别为 x1=0.5,x2=0.3
- 隐藏层:2 个节点
- 输出层:1 个节点
- 真实输出:y=0.7
- 当前权重:
- w1=0.1, w2=0.2 (输入到隐藏层 1)
- w3=0.3, w4=0.4 (输入到隐藏层 2)
- w5=0.5, w6=0.6 (隐藏层到输出)
- 激活函数:Sigmoid
- 损失函数:均方误差(MSE)
技术实现
1. 前向传播与损失计算
首先计算隐藏层和输出层的值:
-
隐藏层 1 的输入:
$$ h1_{in} = w1x1 + w2x2 = 0.10.5 + 0.20.3 = 0.11 $$
$$ h1_{out} = \sigma(0.11) = \frac{1}{1+e^{-0.11}} \approx 0.5275 $$ -
隐藏层 2 的输入:
$$ h2_{in} = w3x1 + w4x2 = 0.30.5 + 0.40.3 = 0.27 $$
$$ h2_{out} = \sigma(0.27) \approx 0.5671 $$ -
输出层的计算:
$$ o_{in} = w5h1_{out} + w6h2_{out} = 0.50.5275 + 0.60.5671 \approx 0.6135 $$
$$ o_{out} = \sigma(0.6135) \approx 0.6488 $$ -
计算损失(MSE):
$$ L = \frac{1}{2}(o_{out} – y)^2 = \frac{1}{2}(0.6488 – 0.7)^2 \approx 0.001312 $$
2. 反向传播梯度计算
我们需要计算损失对各权重的偏导数。以 w5 为例:
-
$$ \frac{\partial L}{\partial w5} = \frac{\partial L}{\partial o_{out}} * \frac{\partial o_{out}}{\partial o_{in}} * \frac{\partial o_{in}}{\partial w5} $$
-
计算各部分:
- $$ \frac{\partial L}{\partial o_{out}} = o_{out} – y = 0.6488 – 0.7 = -0.0512 $$
- $$ \frac{\partial o_{out}}{\partial o_{in}} = o_{out}(1-o_{out}) = 0.6488(1-0.6488) \approx 0.2278 $$
-
$$ \frac{\partial o_{in}}{\partial w5} = h1_{out} = 0.5275 $$
-
组合起来:
$$ \frac{\partial L}{\partial w5} = -0.0512 * 0.2278 * 0.5275 \approx -0.00615 $$
类似地可以计算其他权重的梯度。
3. 权重更新
假设学习率 η =0.1,更新 w5:
$$ w5_{new} = w5 – η * \frac{\partial L}{\partial w5} = 0.5 – 0.1*(-0.00615) \approx 0.500615 $$
其他权重的更新方式相同。
代码示例
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 输入和参数
x1, x2 = 0.5, 0.3
y_true = 0.7
w1, w2, w3, w4, w5, w6 = 0.1, 0.2, 0.3, 0.4, 0.5, 0.6
lr = 0.1
# 前向传播
h1_in = w1*x1 + w2*x2
h1_out = sigmoid(h1_in)
h2_in = w3*x1 + w4*x2
h2_out = sigmoid(h2_in)
o_in = w5*h1_out + w6*h2_out
o_out = sigmoid(o_in)
# 计算损失
loss = 0.5 * (o_out - y_true)**2
print(f"Current loss: {loss:.6f}")
# 反向传播
dL_do_out = o_out - y_true
do_out_do_in = o_out * (1 - o_out)
dL_do_in = dL_do_out * do_out_do_in
dL_dw5 = dL_do_in * h1_out
dL_dw6 = dL_do_in * h2_out
# 更新权重
w5 -= lr * dL_dw5
w6 -= lr * dL_dw6
print(f"Updated w5: {w5:.6f}, w6: {w6:.6f}")
注意事项
- 学习率选择:
- 太大可能导致震荡甚至发散
- 太小会导致收敛速度过慢
-
建议从 0.01 或 0.001 开始尝试
-
常见错误:
- 忘记对中间结果进行缓存,导致重复计算
- 梯度计算时链式法则应用错误
-
权重更新方向错误(应该是减而不是加)
-
调试技巧:
- 打印中间变量的值和形状
- 使用小规模数据验证
- 对比数值梯度和解析梯度
总结与延伸
通过这个简单的例子,我们完整走了一遍神经网络权重更新的流程。关键步骤包括:
- 前向传播计算预测值和损失
- 反向传播计算各权重的梯度
- 根据梯度更新权重
为了加深理解,可以尝试:
- 手动计算其他权重的更新值
- 修改网络结构(如增加隐藏层)
- 尝试不同的激活函数和损失函数
- 实现完整的训练循环,观察损失下降曲线
这个过程虽然看起来复杂,但只要掌握了链式法则的基本原理,就能逐步推导出所有需要的梯度。在实践中,深度学习框架会自动帮我们完成这些计算,但理解背后的原理对于调试和改进模型至关重要。
