夜雨聆风学习资料网

ARTICLE · 1054215

Excel里的CNN反向传播:50次迭代的全过程

Excel里的CNN反向传播:50次迭代的全过程

之前用 Excel 求解器直接跳到了最优参数。但那依赖的是求解器内部的数值方法,并不是反向传播。这一篇,我们在 Excel 里亲手实现反向传播的每一步——正向算输出、反向算 δ、累加梯度、更新参数、迭代 50 次。不依赖任何求解器,就是纯 Excel 公式。

这和之前的 Excel 实验是同一个思路,但规模大了很多:69 个参数、96 张图像、50 轮迭代。

一、实验设定

  • 网络:3 个 3×3 过滤器 → 卷积层(3×4×4)→ 池化层(3×2×2)→ 输出层(3 单元)
  • 参数:69 个(27 个过滤器分量 + 3 个卷积偏置 + 36 个输出权重 + 3 个输出偏置)
  • 训练数据:96 张 6×6 手写数字图像
  • 激活函数:Sigmoid
  • 池化:最大池化
  • 学习率(小的正数,需要试错确定)
  • 代价函数

二、Excel 操作八步走

步骤 ①:读入 96 张图像数据

与 5-4 节相同,将 6×6 像素值和正解  读入工作表。

步骤 ②:设置参数初始值 + 学习率

69 个参数用标准正态分布随机数初始化,同时设定学习率 

书中特别备注:学习率  需要反复试错——太小收敛慢,太大可能不收敛。

import random, math

random.seed(42)

# 69个参数的初始值
filters = [[[random.gauss(00.5for _ in range(3)] for _ in range(3)]
for _ in range(3)]     # 3个过滤器 × 3×3
b_F = [random.gauss(00.5for _ in range(3)]   # 卷积偏置
W_O = [[[[random.gauss(00.5for _ in range(2)] for _ in range(2)]
for _ in range(3)] for _ in range(3)]     # 输出权重 (3×3×2×2→3)
b_O = [random.gauss(00.5for _ in range(3)]    # 输出偏置
eta = 0.05# 学习率

步骤 ③:正向传播——算出各层输出和平方误差 C

对第 1 张图像,用当前参数计算:

  • 卷积层加权输入  → 输出 
  • 池化层输出 (最大池化)
  • 输出层加权输入  → 输出 
  • 平方误差 

步骤 ④:反向传播——计算 δ

这是核心。按 5-5 节的公式:

先算输出层 δ

再递推到卷积层 δ

步骤 ⑤:计算平方误差 C 关于各参数的偏导数

用步骤④求出的 ,按 5-5 节的公式计算:

  • (过滤器分量梯度)
  • (卷积偏置梯度)
  • (输出权重梯度)
  • (输出偏置梯度)

步骤 ⑥:对全部 96 张图像累加,得到  和 

将步骤③~⑤中为第 1 张图像建立的公式复制到全部 96 张。

然后将所有 96 张图像的  相加得到 ,将所有偏导数相加得到梯度分量:

步骤 ⑦:梯度下降更新参数

按基本公式更新全部 69 个参数:

在 Excel 中,就是在下方开辟新的参数区域,每个参数 = 旧值 -  × 梯度分量。

步骤 ⑧:重复 ③~⑦,共 50 次

将第 1 轮的参数更新结果作为第 2 轮的起始参数,重复正向→反向→更新。把块状区域复制 49 份,得到 50 轮迭代。

三、运行结果

完成 50 次迭代后:

解释这个数字:

  • 96 张图像,每张平均平方误差 
  • 平方误差最大值:当输出  而正解是  时,(更极端的可达 1.5)
  • ——预测已经非常接近正解

四、用新图像测试

训练完成后,用没见过的 6×6 图像测试 CNN。

书中展示了一个测试用例:输入一个新的数字"3"的图像,输出的三个值中  最大——**CNN 正确判定为数字"3"**。

"""
测试:用训练后的参数预测新图像
"""

defpredict(image, filters, b_F, W_O, b_O):
# 卷积 + Sigmoid
    a_F = [[[0.0]*4for _ in range(4)] for _ in range(3)]
for k in range(3):
for i in range(4):
for j in range(4):
                s = sum(filters[k][p][q] * image[i+p][j+q]
for p in range(3for q in range(3))
                a_F[k][i][j] = sigmoid(s + b_F[k])

# 最大池化
    a_P = [[[0.0]*2for _ in range(2)] for _ in range(3)]
for k in range(3):
for i in range(2):
for j in range(2):
                a_P[k][i][j] = max(
                    a_F[k][2*i][2*j], a_F[k][2*i][2*j+1],
                    a_F[k][2*i+1][2*j], a_F[k][2*i+1][2*j+1]
                )

# 输出层
    a_O = [0.0]*3
for n in range(3):
        s = sum(W_O[k][n][i][j] * a_P[k][i][j]
for k in range(3for i in range(2for j in range(2))
        a_O[n] = sigmoid(s + b_O[n])

# 最大输出对应的数字 = 判定结果
return a_O.index(max(a_O)) + 1# 1, 2, 或 3


# 测试一个新图像
test_image = [
    [1,1,1,1,1,1],
    [0,0,0,0,0,1],
    [1,1,1,1,1,1],
    [0,0,0,0,0,1],
    [1,1,1,1,1,1],
    [0,0,0,0,0,1],
]
result = predict(test_image, filters, b_F, W_O, b_O)
print(f"判定结果: 数字 {result}")

五、代价函数跟踪:确认梯度下降在"工作"

书中提到:跟踪 50 次迭代中  的变化,可以确认梯度下降法正在发挥作用—— 应该随着迭代次数单调递减(如果不减,说明学习率或初始值有问题)。

典型的代价函数下降曲线:

C_T
 │
 │  ••
 │      •••
 │            ••••
 │                    •••••____
 └──────────────────────────────▶ 迭代次数
  0                         50

六、反向传播 vs 求解器:两种方法的对比

5-4 求解器方法
5-6 反向传播方法
梯度来源
求解器内部数值近似
解析公式递推
计算效率
低(每次参数调整都是盲搜)
高(一次正反传全算出)
可扩展性
差(参数多了跑不动)
好(可扩展到深度学习框架)
适用场景
验证模型结构
实际训练
Excel 行数
较少
大量(96 张 × 50 轮)

之前的求解器方法证明了"CNN 结构能解决这个问题",5-6 的反向传播法则证明了"反向传播在 CNN 中同样高效可用"。

七、小结

最后六篇文章,从"小恶魔扫描图像"的直觉出发,一路走到"在 Excel 中用反向传播训练 CNN 50 轮"——这是全书最综合的一章:

1:卷积神经网络的直觉——小恶魔主动扫描,卷积+池化
2:数学实现——过滤器扫描、特征映射、最大池化
3:变量关系式——CNN 的完整数学描述
4:Excel 求解器验证——69 参数能完美拟合数据
5:CNN 反向传播推导——δ 穿过池化层、过滤器梯度累加
6:Excel 反向传播实战——50 次迭代,

从最初的"一个隐藏单元做出判断",到第 4 章的"误差反向传播在多层的递推",再到现在的"卷积网络 + 反向传播"——28 篇文章,我们跟随一同用最基础的数学工具(偏导数、链式法则、Σ求和、Sigmoid),把深度学习最核心的数学拼图一块块搭完了。


全书正文到此结束。28 篇文章,如果从头跟到尾,你已经理解了神经网络从"做判断"到"自学习"的完整数学逻辑。剩下的就是挑一个你喜欢的框架(PyTorch、TensorFlow),用比 Excel 更方便的方式,让 GPU 替你跑这几千几万次矩阵运算。

恭喜你,完成了这场硬核而真诚的数学旅程。🎉

相关学习资料