Excel 中的机器学习






4.86/5 (28投票s)
逐个单元格讲解神经网络的数学原理。
引言
本文为那些对神经网络 (NN) 背后的数学原理感到好奇的人撰写。如果您正在尝试开发自己的 NN,它可能也会有所帮助。本文将逐个单元格地讲解一个三层 NN,每层有两个神经元。实现使用 Excel 完成。
背景
如果您还在阅读本文,我们可能至少有一个共同点。我们都对机器学习和神经网络感到好奇。这个领域有许多框架和免费 API,使用它们可能比重新发明已经存在的东西更明智。但另一方面,深入了解机器学习的工作原理也无妨。而且,深入探索事物也更有趣。
我的机器学习之旅或许才刚刚开始。我从 Google 搜索开始,阅读了许多很棒的互联网资料。我还观看了一些不错的 YouTube 视频。但我很难获得足够的知识来开始编写自己的 AI。
最后,我找到了这篇博文: Matt Mazur 的反向传播逐步示例。它很适合我,本文的其余部分也以此为基础。
然后,当你开始迭代 2(这是构建迭代的开始)时,你可能想要复制测试用例并将它们重新分类到迭代 2。这还允许对测试用例进行粒度跟踪,并允许你说某个测试用例在一个迭代中是准备好的,但在另一个迭代中不是。同样,如何做到这一点取决于你以及你希望如何报告。 “场景”部分提供了更多细节。
神经网络 (NN) 由许多神经元层组成。神经元有一个值以及与下一层所有其他神经元连接的权重。
第一层是输入层,最后一层是输出层。输入层和输出层之间可能有一个或多个隐藏层。每层神经元的数量是可变的。
如果 NN 用于(例如)图像分类,则输入层中的神经元数量当然等于图像中的像素数量。然后,在输出层中,每个神经元代表图像的一种分类。(例如,一种动物类型、一朵花或一个数字。)
计算
在计算之前,NN 中的所有权重都必须用随机数进行初始化。
下图是我在本文其余部分中引用的电子表格的屏幕截图。最好保持该电子表格的窗口打开。这样可以更容易地跟进。
提示:第 2 行是计算顺序。
步骤 1 - 3。前向传播
一个神经元的值是通过将每个前一个神经元乘以其权重之和来计算的。
还添加了一个没有神经元的额外偏差权重
F3 = A3 * B3 + A7 * B4 + B5
该值通过激活函数进行归一化。神经网络中使用了几种不同的激活函数。
我使用了逻辑函数:
G3 = 1 / (1 + EXP(-F3))
步骤 4 - 5。前向传播
输出层的神经元以与隐藏层相同的方式计算。
L3 = G3 * H3 + G7 * H4 + H5
and
M3 = 1 / (1 + EXP(-L3))
步骤 6 - 7。误差
每个输出神经元的误差是使用预期值或目标值计算的。在图像分类中,通常将一个神经元设置为接近 1,其余神经元设置为接近零。
对于 Q 列中的误差
Q3 = (M3 - O3)²
和
Q7 = (M7 - O7)²
总误差 R5
是所有误差的平均值,并且随着网络训练,它应该越来越接近零。
R5 = (Q3 + Q7) / 2
反向传播
神经网络通过反复传递大量训练数据来训练。
然后,对于每次迭代,都会计算误差和增量。这用于对所有权重进行微小调整,使网络变得越来越好。
这称为反向传播。
由于总误差可以表示为每个权重的数学函数,因此可以对这些函数进行求导,以获得函数曲线在一点处的斜率。斜率指示了总误差最小值的方向,并按比例指示了每个权重应调整多少,以使总误差趋近于零。
下面为每个权重计算一个增量值。增量分别存储在输出层和隐藏层的 I 列和 D 列中。
链式法则 - 反向传播之友
实际上,我们想对 H3 求总误差 R5 的导数,所以我们首先使用代换将 R5 表示为 H3 的函数。
因为
R5 = (Q3 + Q7) / 2
R5 = (M3 - O3)² / 2 + (M7 - O7)² / 2
上面的函数看起来不太容易求导。甚至可能吗?
我们将转而使用链式法则2。
它指出,如果函数有 f(g(x)) 这样的两个或多个函数的复合,并且令 F(x) = f(g(x)),我们可以这样求导:
F'(x) = f'(g(x)) * g'(x) 或用另一种符号表示
在我们的例子中,我们有以下依赖关系
R5(M3(L3(H3)))
我们可以写成
步骤 9。输出层增量
总误差函数 R5
对输出层的第一个权重 H3
求导。
在上面的公式中,链式法则被用来简化求导。
因为
逻辑函数求导的证明可在本文3中找到。
由于 将在反向传播中用到,因此将其存储在单元格
P3
中。
P3 = (M3-O3) * M3 * (1 - M3)
上面求导链的最后一个导数更简单。
因为 L3 = G3 * H3 + G7 * H4 + H5
我们现在可以将所有内容整合起来,并将 存储到单元格 I3 中。
I3 = P3 * G3
输出层其余权重的计算方式相同,我们得到
P7 = (M7-O7) * M7 * (1 - M7)
I4 = G7 * P3
I5 = 1 * P3 (bias neuron)
I7 = G3 * P7
I8 = G7 * P7
I9 = 1 * P7 (bias neuron)
步骤 10。隐藏层反向传播
在此步骤中,我们计算
前几步的链式法则有助于将其转换为我们可以使用的形式
第一项也必须分成 Q3
和 Q7
两个误差,所以
首先看这个
它可以进一步分解为这样
首先, 已存储在
P3 = (M3-O3) * M3* (1 - M3)
中
因为 L3 = G3 * H3 + G7 * H4 + H5
当我们把上面这些放在一起,我们得到
并以与上面相同的方式
第一个问题解决了。
是时候计算
我们知道
我们之前已经学习过如何推导逻辑函数。
现在
因为
现在我们将上述各项结合起来,得到总误差对隐藏层第一个权重的导数表达式。
这存储在单元格 C3
中。
以上计算对所有隐藏层权重重复进行
C3 = (P3 * H3 + P7 *H7) * (G3 *(1 - G3)) * A3
C4 = (P3 * H3 + P7 *H7) * (G3 *(1 - G3)) * A7
C5 = (P3 * H3 + P7 *H7) * (G3 *(1 - G3)) * 1
C7 = (P3 * H4 + P7 *H8) * (G7 *(1 - G7)) * A3
C8 = (P3 * H4 + P7 *H8) * (G7 *(1 - G7)) * A7
C9 = (P3 * H4 + P7 *H8) * (G7 *(1 - G7)) * 1
现在可以使用单元格 A13
中选定的学习率轻松计算新权重。
例如:(新的 B3
)
D3 = B3 - C3 * A13
Excel 文档中的训练按钮连接了一个宏。该宏会迭代多次,我们可以看到 M 列中的输出神经元如何越来越接近其目标值,以及 R5 中的总误差如何越来越接近零。
版本 1.1 更新:
我发现使用激活函数 Leaky Relu4 可以提高学习率和准确性
f(x) = x 如果 x > 0
否则 f(x) = x/20
将逻辑函数替换为 Leaky Relu 可能是一个很好的练习。
提示
G3 = IFS(F3 > 0; F3; F3 <= 0; F3/20) and P3= (M3-O3) * IFS(M3 > 0;1;M3<=0;1/20)
(也附上新版本的 xls 文件,以防万一...)
结束语
我意识到这篇文章可能需要一些时间来消化。我尽力按照我的理解来解释。如果您发现任何错误,请在下方评论。
在弄清楚 NN 在 Excel 中的工作原理后,我编写了一个 C# 程序,可以识别手写数字。它有一个运行良好的 Windows Forms 用户界面。它似乎能识别我绘制的几乎所有数字,即使是丑陋的数字。这对我来说是一个证明,表明我对人工神经网络的理解目前是正确的。
该文章可以在这里找到
链接
历史
- 2019 年 1 月 1 日 - 版本 1.0
- 2019 年 1 月 8 日 - 版本 1.1
- 将逻辑激活函数替换为 LeakyReLu
- 2019 年 1 月 11 日 - 版本 1.2
- 更新图表中偏差名称
- 2019 年 1 月 23 日 - 版本 1.3
- 将 du 计算更改为总误差的平均值