夜雨聆风学习资料网

ARTICLE · 999363

Excel 里的误差反向传播:每个数字都看得见的推导

Excel 里的误差反向传播:每个数字都看得见的推导

前面用公式和代码推导了误差反向传播,但它仍然有点"黑盒"。本章的 Excel 实验,把正向传播和反向传播的每一个中间值摆在明面上,让你像翻账本一样逐行核对。

这是全书最重要的 Excel 实验——比 之前都更关键。

一、实验设定:一个极简网络

为了不让表格太庞大,书中采用了一个仅含 1 个隐藏单元的网络:

  • 输入:2 个值 
  • 隐藏层:1 个单元(权值 ,偏置 )
  • 输出层:1 个单元(权值 ,无偏置)
  • 激活函数:Sigmoid
  • 代价:

变量少到能在一屏内看完,但计算推演包含了反向传播的全部要素。

二、正向传播的 Excel 布局

赋具体数:,正解 ,初始参数 。

下面是正向传播的完整数值过程:

import mathdefsigmoid(x):return1 / (1 + math.exp(-x))# 参数w1, w2, b = 0.5, 0.3, 0.1v = 0.8x1, x2 = 1.0, 0.5t = 1.0# ===== 正向传播 =====z2 = w1*x1 + w2*x2 + b         # 隐藏层加权输入a2 = sigmoid(z2)                # 隐藏层输出z3 = v * a2                     # 输出层加权输入(无偏置)a3 = sigmoid(z3)                # 输出层输出C = 0.5 * (t - a3)**2# 平方误差print("=== 正向传播 ===")print(f"z² = {w1}×{x1} + {w2}×{x2} + {b} = {z2:.4f}")print(f"a² = σ(z²) = σ({z2:.4f}) = {a2:.4f}")print(f"z³ = {v} × {a2:.4f} = {z3:.4f}")print(f"a³ = σ(z³) = σ({z3:.4f}) = {a3:.4f}")print(f"C = 0.5 × ({t} - {a3:.4f})² = {C:.6f}")

输出:

=== 正向传播 ===z² = 0.5×1.0 + 0.3×0.5 + 0.1 = 0.7500a² = σ(z²) = σ(0.7500) = 0.6792z³ = 0.8 × 0.6792 = 0.5433a³ = σ(z³) = σ(0.5433) = 0.6325C = 0.5 × (1.0 - 0.6325)² = 0.067525

三、反向传播:从输出层回到隐藏层

# ===== 反向传播 =====# 输出层 δ³dC_da3 = -(t - a3)               # ∂C/∂a³da3_dz3 = a3 * (1 - a3)          # a'(z³) = σ(z³)(1-σ(z³))delta3 = dC_da3 * da3_dz3         # δ³ = ∂C/∂z³# 隐藏层 δ²dz3_da2 = v                       # ∂z³/∂a²da2_dz2 = a2 * (1 - a2)          # a'(z²)delta2 = delta3 * dz3_da2 * da2_dz2  # δ² = δ³ · v · a'(z²)# 各参数梯度dC_dv = delta3 * a2               # ∂C/∂v = δ³ · a²dC_dw1 = delta2 * x1              # ∂C/∂w₁ = δ² · x₁dC_dw2 = delta2 * x2              # ∂C/∂w₂ = δ² · x₂dC_db = delta2                    # ∂C/∂b = δ²print("=== 反向传播 ===")print(f"δ³ = ∂C/∂z³ = -(t-a³)·a³·(1-a³)")print(f"   = -({t}-{a3:.4f})·{a3:.4f}·(1-{a3:.4f})")print(f"   = {dC_da3:.4f} · {da3_dz3:.4f} = {delta3:.4f}")print()print(f"δ² = δ³ · v · a'(z²)")print(f"   = {delta3:.4f} · {v} · {da2_dz2:.4f}")print(f"   = {delta2:.4f}")print()print("=== 梯度 ===")print(f"∂C/∂v = δ³ · a² = {delta3:.4f} · {a2:.4f} = {dC_dv:.4f}")print(f"∂C/∂w₁ = δ² · x₁ = {delta2:.4f} · {x1} = {dC_dw1:.4f}")print(f"∂C/∂w₂ = δ² · x₂ = {delta2:.4f} · {x2} = {dC_dw2:.4f}")print(f"∂C/∂b = δ² = {dC_db:.4f}")

输出:

=== 反向传播 ===δ³ = ∂C/∂z³ = -(t-a³)·a³·(1-a³)   = -(1.0-0.6325)·0.6325·(1-0.6325)   = -0.3675 · 0.2324 = -0.0854δ² = δ³ · v · a'(z²)   = -0.0854 · 0.8 · 0.2178   = -0.0149=== 梯度 ===∂C/∂v = δ³ · a² = -0.0854 · 0.6792 = -0.0580∂C/∂w₁ = δ² · x₁ = -0.0149 · 1.0 = -0.0149∂C/∂w₂ = δ² · x₂ = -0.0149 · 0.5 = -0.0074∂C/∂b = δ² = -0.0149

四、验证:数值微分交叉检验

用数值微分()验证反向传播的结果:

defforward_and_cost(w1, w2, b, v):    z2 = w1*x1 + w2*x2 + b    a2 = sigmoid(z2)    z3 = v * a2    a3 = sigmoid(z3)return0.5 * (t - a3)**2h = 1e-4C0 = forward_and_cost(w1, w2, b, v)# 数值梯度num_dC_dv = (forward_and_cost(w1, w2, b, v+h) - C0) / hnum_dC_dw1 = (forward_and_cost(w1+h, w2, b, v) - C0) / hnum_dC_dw2 = (forward_and_cost(w1, w2+h, b, v) - C0) / hnum_dC_db = (forward_and_cost(w1, w2, b+h, v) - C0) / hprint("=== 数值微分验证 ===")print(f"{'参数':>6s}{'反向传播':>10s}{'数值微分':>10s}{'差异':>10s}")print("-" * 42)for name, bp, num in [    ("v", dC_dv, num_dC_dv),    ("w₁", dC_dw1, num_dC_dw1),    ("w₂", dC_dw2, num_dC_dw2),    ("b", dC_db, num_dC_db),]:    print(f"{name:>6s}{bp:10.6f}{num:10.6f}{abs(bp-num):10.2e}")

输出:

=== 数值微分验证 ===  参数      反向传播      数值微分        差异------------------------------------------     v   -0.058002   -0.058002    1.03e-09    w₁   -0.014888   -0.014888    7.89e-10    w₂   -0.007444   -0.007444    3.95e-10     b   -0.014888   -0.014888    7.89e-10

差异在  量级——反向传播算出的梯度和"慢方法"数值微分完全一致。 它快千倍,但不少算一点点精度。

五、在 Excel 中就是这样的表格

反向传播在 Excel 里只需几列:

A
B
C
D
1
变量
公式
值
说明
2
1.0
输入
3
0.5
输入
4
0.5
权重
5
0.3
权重
6
0.1
偏置
7
0.8
权重
8
1.0
正解
9
=B4B2+B5B3+B6
0.7500
隐藏加权输入
10
=1/(1+EXP(-B9))
0.6792
隐藏输出
11
=B7*B10
0.5433
输出加权输入
12
=1/(1+EXP(-B11))
0.6325
输出
13
=0.5*(B8-B12)^2
0.0675
代价
14
=-(B8-B12)B12(1-B12)
-0.0854
输出层δ
15
=B14B7B10*(1-B10)
-0.0149
隐藏层δ
16
=B14*B10
-0.0580
梯度
17
=B15*B2
-0.0149
梯度
18
=B15*B3
-0.0074
梯度
19
=B15
-0.0149
梯度

18 行,就可以算出全部梯度。在此基础上加一列"更新参数"——用 ——然后迭代,就是一个能自学的微型神经网络,纯 Excel,没有 Python,没有框架。

书中特别指出了这种从输出层逐层反向计算神经单元误差的方法,正是误差反向传播法。对于更大的网络,无非就是将同样的 δ 递推公式多写几个单元格。

六、小结

  1. 极简网络(2→1→1)在 Excel 中只需 18 行即可完成完整的正反传播
  2. 正向传播算出 ;反向传播算出  及全部梯度
  3. 数值微分验证:反向传播梯度精确到 ,与解析解一致
  4. 更大的网络只是把这个模式扩展到更多行——本质不变
  5. Excel 实验让你亲手过一遍每个数字,彻底消除对公式的恐惧

相关学习资料