感知器的实时交互式可视化学习工具
提供感知器学习过程的动态可视化演示;帮助程序员直观理解神经网络基础,适合 ML 初学者。
提供感知器学习过程的动态可视化演示;帮助程序员直观理解神经网络基础,适合 ML 初学者。
我读过大量介绍 Machine Learning(ML)模型工作原理的文章。它们基本都在用差不多的方式解释同样的内容。
但有一样东西,我始终没有找到:最纯粹的 Machine Learning 形式。
它应该简单到让我能直观地理解正在发生什么。在这个例子里,我可以亲眼看到一个模型如何从一无所知,到逐渐理解某些东西,并且能够准确跟上它工作过程中的每一步!
我的意思是,我(大概)理解 weights、biases 之类的概念。我曾设法用原生 JS 构建过一个 Neural Network(NN),甚至还用 CSS 构建过一个 Neural Network 🤯!但我仍然无法真正想象它究竟是什么样子。
后来,我了解到了「perceptron」(project PARA)。这是 20 世纪 50 年代末到 60 年代初最早期的 ML 实验之一——没错,我们从那么早就开始研究 Machine Learning 了,事实上可以追溯到 20 世纪 40 年代!
这正是我一直在寻找的东西。因为这种 Machine Learning 模型使用的是 ANALOGUE 系统,所以它必然更加简单。
正是得益于这种简单性,我终于可以构建自己想要的东西:一个简单的模型,让我们能够实时看到它如何学习;更重要的是,还能理解它在学习过程中究竟发生了什么!
如果你没耐心,可以直接跳到 demo。不过我建议先了解它的工作方式,以及它学习时遵循的规则,因为这些内容对于理解你接下来看到的现象非常重要!
Welch Labs 制作了一段非常精彩的 perceptron 讲解视频,正是它启发我写下了这篇文章。本文的一部分截图,也来自他们亲手搭建的实体 perceptron 机器!
这就是我构建的东西——或者更准确地说,是 03-mini 在大量 prompt 和一些手把手指导下构建的。顺便说一句,o3 mini 生成的一些代码糟糕透顶,但作为原型开发工具,它确实令人印象深刻!即便如此,把这个例子做出来还是花了大约 4 个小时。
我先解释一下你在截图中看到的内容,然后你就可以亲自玩一玩这个 demo 了!
最上方的前两个方框是我们的输入。
它们是两个 5×5 的方格,你可以在里面拨动「开关」。
选中的复选框代表正电压,未选中的复选框代表负电压。
为了让模型展示学习过程,我们需要一个「好」形状和一个「坏」形状。
它们是输入开关网格在代码中的表示。就像下面这个例子一样,你每次都需要手动拨动开关,组成一个「好」形状或「坏」形状:
在输入网格下方,是旋钮,也就是 weights。
在现实世界的 analogue 版本中,它们是真实存在的物理旋钮,会将输入电压乘以旋钮上显示的数值。
在我们的例子中,它们由每个方格中的数字表示,显示一个正数或负数形式的乘数。
你还会注意到,截图中的单元格带有颜色:正数使用绿色,负数使用红色,这样在视觉上更容易区分——至少对于没有色盲的人来说是如此。
最后,你还会看到每个方格中都有一个「+」或「-」,同样是为了表明它正在增强还是削弱对应输入的信号。
这实际上就是我们的 Neural Network。这些就是你可能在现代 Neural Network 中听说过的「weights / biases」。
如果某个网格单元为正数或绿色,就相当于把旋钮调高;如果某个网格单元为负数或红色,就相当于把旋钮调低。
它们代表的是一组如下所示的旋钮:
这部分只是为了帮助我们理解模型内部正在发生什么。它显示的是某个输入与一个「旋钮」相乘后的输出。
进一步解释一下,假设第一个旋钮被设置为「+18」。
然后,假设我们向 perceptron 输入一个正电压——所有输入在开启时都是 +10 伏,关闭时都是 -10 伏。
这意味着该旋钮将输出 +180 伏。
现在,假设我们将这个开关,也就是第一个复选框,改为「关闭」。此时我们会得到 -180v 的输出。
需要特别注意的是,如果这个「旋钮」为负数,例如设置为「-12」,结果就会完全相反。
如果开关处于「开启」状态,我们会得到 -120v 的输出,也就是 +10 伏乘以 -12;如果开关处于「关闭」状态,我们则会得到 +120v。
接下来,模型会把所有电压相加,以此完成计算。
对了,这里还有最后一个小细节:如果某个旋钮为「0」,我们就直接输出它接收到的电压。
电压输出表就是我们的最终输出。
它的计算方式是:将每个开关的输入电压,也就是复选框对应的 +10v 或 -10v,与相应的增益开关相乘,然后把所有结果加在一起。
在我们的 perceptron 中,正值代表「好」,负值代表「坏」。具体电压值有多大并不重要,重要的只是它高于 0 还是低于 0。
它代表了真实模型中的电压表:
这个 perceptron 模型遵循一些简单的规则。
它总是先接收一个形状。在这个例子中,我们先输入「好」形状,同时将所有旋钮,也就是 weights,设置为 0。
请记住,任何选中的复选框都会输出 +10 伏,任何未选中的复选框都会输出 -10 伏。
因此,如果我们画出的形状包含 4 个选中的复选框,就会从它们那里得到 +40 伏;但与此同时,其他复选框会产生 -450 伏——要记住,实际的面板是 7×7 的,所以一共有 49 个开启或关闭的输入。
因为目前没有任何 weighting 或 adjustment,所以最终得到的总输出电压是负数。
这正是关键所在,因为接下来我们会根据输出结果应用以下规则:
如果正确的输出电压应该为正数,也就是一个「好」形状,但实际得到的是负电压,那么我们会调高所有处于「开启」状态的单元格,同时调低其他所有单元格。
如果正确的输出电压应该为正数,而我们得到的也是正电压,那么什么都不做。
如果正确的输出电压应该为负数,也就是一个「坏」形状,但实际得到的是正电压,那么我们会调低所有处于「开启」状态的单元格,同时调高其他所有单元格。
如果正确的输出电压应该为负数,而我们得到的也是负电压,那么什么都不做。
在我们的模型中,每次调整都以 3 为增量。因此,完成一次训练后,我们会得到如下输出:
这正是神奇之处。
如果我们的形状与输出网格大小相同,那么也可以认为,我们实际上只是在内存中存储了这个形状。严格来说,模型并没有真正学到任何东西。
所以,接下来我们会把形状向右移动一格,然后重复同样的过程。
这一次,由于之前已经执行过调整,模型会输出不同的电压。因为现在有一些处于关闭状态的开关会乘以负数,从而产生正电压输出;同时,一些处于开启状态的开关会移动到负乘数所在的位置,从而产生负电压。
然后,我们再次根据这次的输出电压,遵循同样的规则。
最后,当我们尝试完「好」形状的全部 9 个位置,并针对每个位置调整过旋钮之后,就会再输入「坏」形状的 9 个位置。
这轮训练结束后,模型就学会了如何识别形状。经过一轮学习,它未必每次都能判断正确,但在反复训练多轮之后,它最终会得到正确结果——好吧,几乎总是如此。有几种形状组合永远无法「稳定」在正确的旋钮模式上。
好了,前面已经讲了很多,现在终于可以开始玩了!
理解完上面的内容之后,接下来就是 demo。
不过,在你真正开始操作之前,请先阅读以下说明。
正确使用这个模型至关重要,这会让你更容易理解其中究竟发生了什么!
点击复选框,在「好」方框中输入一个形状,再在「坏」方框中输入另一个不同的形状。
形状设置完成后,就可以开始训练了!
点击第一个按钮「start training」。
你会看到系统把「好」形状放入「dials and weights」方框最左上角的位置,并立即根据前面介绍的规则调整电压。
接下来,它会把形状向右移动一个位置,然后再次遵循同样的规则。移动过程中请留意电压表,这样你就能看到电压是正数还是负数,以及电压的正负如何改变模型的行为。
它会对 3 列和 3 行的全部组合重复这一过程,从而训练这个形状能够出现的所有位置。
然后,它会切换到「坏」形状,并遵循同样的规则——要记住,这一次我们期望得到的是负输出。
训练完成后,你会看到一条 alert:
现在你有两个选择。
方案 1:点击「Select Top-Left Position for Testing」方框中的 9 个方格之一。此时会出现一个 modal,询问你要测试哪一种形状——「A」代表「好」,「B」代表「坏」。
随后,你会收到一条包含 perceptron 猜测结果的 alert。
接下来,你会看到该形状被渲染到「Select Top-Left Position for Testing」方框中,同时还会显示每一组旋钮与开关组合产生的电压输出。
再多点击几个方格,选择「A」或「B」来测试「好」形状和「坏」形状,看看模型的猜测有多少次正确、多少次错误!
这是理解模型工作方式的最佳方法,所以请多尝试几次,并仔细检查输出结果。
方案 2:让系统一直测试,直到找到失败案例!如果你只是想看看模型当前的表现,可以点击「Test All」。
系统会依次测试两个形状的所有位置。如果它猜错了——例如,对一个「好」形状输出了负电压——测试就会停止并显示错误,同时告诉你失败发生在哪个位置。
或者,如果你真的很幸运,它可能会完成全部检查,而你将看到一条成功消息!
如果模型通过了测试,那么无论你把形状放在任何有效位置,它都能正确识别该形状是「好 / A」还是「坏 / B」。
这并不奇怪,毕竟你已经完成了一轮训练!
现在,你可以再次点击「start training」,不过这个过程是刻意设计得比较慢的。
为了加快速度,你可以点击「Self train and test」。
它会以 10 倍速度遍历所有训练位置,然后运行测试,直到某个形状测试失败。整个过程最多重复 50 次,或者在模型通过全部测试时提前结束!
当你理解了基本原理,并且已经充分体验过慢速版本之后,就可以点击这个按钮,观察每个方格的电压如何变化,以及模型如何在测试中逐渐走得更远,直到它最终——希望如此——通过全部测试!
如果它没有通过,可以换一个形状,或者再次点击「self train and test」,再运行 50 个周期!
当它通过全部测试后,可以试着点击「Select Top-Left Position for Testing」中的几个方格,然后选择「A」或「B」形状进行测试。
请特别关注每个方格中的电压和旋钮设置。留意哪些单元格最强、哪些最弱,等等。
我发现,理解其中发生的事情竟然如此「容易」,实在太有意思了!
如果你想尝试新的形状,或者只是想再次观察模型从零开始学习,只需点击「reset dials」,所有旋钮都会恢复为 0。
我知道前面讲了很多,但我希望它能帮助你理解一个模型在最简单的形式下是如何学习的。
相比 matrix multiplication、各种图形和图表,我发现这种方式更容易理解。虽然现代 LLM / ML 模型并不是这样工作的,但它非常适合用来理解其中的基本原理。
如果你觉得它很有用,或者它帮助你更好地理解了相关概念,欢迎在评论区告诉我!
部分评论可能只有登录后的访客才能看到。请登录以查看全部评论。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。