你能构建的最小大脑:Python中的感知机

Hacker News Top 工具

摘要

感知机是最简单的神经网络构建块。本教程从零开始用Python实现一个感知机,通过清晰的示例解释权重、偏置和学习过程。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/06/08 03:14

# 你能构建的最小大脑 来源:https://ranpara.net/posts/perceptron-explained-from-scratch/ 感知机是你能构建的最小大脑。输入一个数字,输出一个“是”或“否”的答案。就这么简单。 听起来简单到不值一提。但这个微小的想法是今天所有神经网络的基础。在这篇文章中,我们将用 Python 从零开始构建一个感知机,并在浏览器里实时观察它的学习过程。没有沉重的数学,没有庞大的库。只有一个权重、一个偏置和一个循环。 我不是英语母语者,而且我自己也还在学习这个领域。所以我会用我希望别人向我解释的方式来讲解:缓慢地,从头开始。 ### 什么是感知机? 1958 年,一位名叫弗兰克·罗森布拉特的研究员制造了一台他称之为感知机的机器。 它的灵感来源于一个单一的脑细胞——神经元。神经元接收信号,如果信号足够强,它就会触发。罗森布拉特用数学复制了这个想法: ``` output = 1 if (w · x + b) > 0 0 otherwise ``` 这里的 `x` 是输入,`w` 是权重,`b` 是偏置。现在不用太在意这些术语,我们通过构建真实的东西来认识它们。 ### 先用人脑思考 在机器做决定之前,我们先观察一个人如何决策。假设有个人叫张三,他有一份工作邀请,需要回答一个问题:他应该接受吗? 张三不会抛硬币。他会权衡利弊。某些因素对他更重要。 | 因素(输入) | 数值 | 张三的在意程度(权重) | | ------------ | -------------------------- | ---------------------- | | 额外薪酬 | 高 | 非常在意 | | 留在同一个城市 | 不,他必须搬家 | 非常在意 | 张三把每个因素乘以他在意的程度,然后把所有结果加起来。如果总和足够高,他就说“是”,否则就说“否”。 这就是感知机。因素就是 **输入**,他在意的程度就是 **权重**,而“足够高”是他脑子里设定的一个阈值。记住这个阈值,稍后我们会给它一个名字:偏置。 ``` w1 ──→ × 输入: 额外薪酬 │ ├── Σ → 偏置 b → 是否>0? → 接受? Yes/No 输入: 同一个城市 │ ──→ × w2 ``` (示意图:两个输入,分别乘以权重,与偏置求和,最终输出一个“是/否”答案) 张三如何决定:每个输入乘以权重,结果加上偏置,总和变成一个“是/否”的答案。 ### 最简单可能的判断:这个数是正数吗? 我们把问题缩小到几乎不能再小:一个输入,一个问题。 > 这个数是正数吗? 就这么简单。给机器一个数字,它应该为正数返回 True,为负数返回 False。 机器是这样猜测的: ``` prediction = (weight * value + bias) > 0 ``` 把输入乘以权重,加上偏置,然后检查结果是否大于 0。如果是,就预测 True;否则预测 False。这个小小的公式就是 **分类器**,也叫决策函数。 一开始,权重和偏置只是随机数。所以机器猜得很差。现在唯一巧妙的步骤来了:它从错误中学习。 ``` if prediction != result: error = result - prediction # True - False = 1, False - True = -1 weight += learning_rate * error * value bias += learning_rate * error ``` 当猜测错误时,我们朝正确的方向微调权重和偏置。**误差**告诉我们朝哪个方向调整,**学习率**决定每次调整的幅度。我们对每个样本都这样做,然后重复整个一轮。一轮完整的数据遍历称为一个 **epoch**。重复 epochs 就是 **训练**。 下面就是这样的机器。点击 **Train**,观察它学习。绿色圆点代表正数(True),红色圆点代表负数(False),蓝色虚线是它决定分割的位置。 epoch **0** weight **0** bias **0** boundary **–** accuracy **0%** 它几乎立即就位。观察读数:边界正好落在 **0** 附近,偏置也稳定在 **0** 附近。 这不是偶然。对于这个问题,我们根本不需要偏置。这有点奇怪,因为偏置按理说很重要。为什么它重要?我们需要一个更难的问题来回答。 ### 什么是决策边界? 那条蓝线有个名字:**决策边界**。它是机器从输出 False 切换到输出 True 的确切点。 我们可以计算它。边界位于 `w · x + b = 0` 处。解出 `x`: ``` decision_boundary = -bias / weight ``` 对于“这个数是正数吗?”这个问题,边界应该在 0 处。确实如此。现在看看当正确的答案不在 0 时会发生什么。 ### 为什么需要偏置?学生及格的例子 新问题,同样的机器。我们给它 0 到 100 的考试分数,然后问: > 学生及格了吗? 规则很简单:分数达到 50 分或以上就算及格。所以决策边界应该位于 **50**,而不是 0。 我们试试像解决前一个问题那样只用权重来解决。在下面的演示中,**关闭“Use bias”**,然后点击 **Train**。 epoch **0** weight **0** bias **0** boundary **–** accuracy **0%** □ Use bias 观察准确率。它会爬到大约 50%,然后就卡住了。无论你训练多久,它都无法更好。 原因如下。没有偏置,公式只是 `weight * score`。每个考试分数都是正数。所以如果权重为正,机器会将 **所有** 学生判为及格;如果权重为负,则判为不及格。边界被固定在 0,无法移动。被迫通过零点的直线根本无法区分“低于 50”和“50 及以上”。 现在 **重新打开“Use bias”**,再按 **Train**。准确率一路爬到 100%,边界滑动到 50 附近。 这就是偏置的全部工作。权重决定斜率。**偏置** 将边界向左或向右移动,使其可以位于正确答案所在的位置。记住 `decision_boundary = -bias / weight`。有了偏置,边界可以是任何值。没有偏置,它就永远被卡在零点。 一句话总结:**当你的输入远离零时,你需要偏置将直线移动到它们所在的位置。** ### 感知机如何学习?Epochs 和学习率 你在训练时看到了两个旋钮:epochs 和学习率。 **Epoch** 是对所有数据的一次完整遍历。机器很少能在一次遍历中就全部正确,所以我们会一遍又一遍地重复。更多的 epochs 意味着有更多机会修正错误。这就是为什么准确率会随着持续训练而上升。 **学习率** 是每次修正的幅度。在代码中是 `learning_rate` 乘数: ``` weight += learning_rate * error * value ``` 小步走小心但缓慢。大步走快速但可能过冲并来回震荡。选好学习率是一门手艺。这里我们用了 `0.1`,足够平缓以保持稳定。 ### 为什么需要归一化数据? 在及格例子中隐藏着一个安静的问题。再看一下更新行: ``` weight += learning_rate * error * value ``` 修正量乘以 `value`。对于考试分数,`value` 可以大到 100。所以一次错误的猜测就可能使权重发生巨大变化。机器虽然还能学习,但会踉踉跄跄,而不是平滑地收敛。 解决办法是 **归一化**:在训练之前将输入缩放到一个小的、整齐的范围。最简单的版本是将每个分数除以最大可能分数,这样 0 到 100 就变成了 0 到 1。 在下面的演示中,先关闭归一化按 **Train**,观察准确率曲线在上升过程中跳跃。然后 **打开“Normalize data”**,重置,再训练一次。同样的机器,同样的答案,但它只需很少的 epochs 就能到达,而且爬升很平滑。 epoch **0** weight **0** bias **0** boundary **–** accuracy **0%** □ Normalize data 老实说,对于像这样的单一输入,归一化主要带来速度和稳定性。当你的输入量级差异很大时,归一化就变得至关重要。回想张三的例子:他的薪酬以千美元计,而“同一个城市”只是 0 或 1。如果不归一化,薪酬会淹没一切,机器基本上会忽略城市因素。把两者放在同一个量级上,每个因素才能得到公平的表达。(除以最大值是简单的版本;另一种常用的通用方法是减去均值并除以标准差,称为标准化。) ### Python 中的完整感知机 以下是“这个数是正数吗?”的完整程序,没有任何隐藏。它短到可以一口气读完。 ```python import random learning_rate = 0.1 EPOCHS = 100 weight = random.uniform(-1, 1) bias = random.uniform(-1, 1) # 正数为 True,负数为 False data = [(i * 0.1, True) for i in range(1, 501)] data += [(i * 0.1, False) for i in range(-500, 0)] random.shuffle(data) for epoch in range(EPOCHS): for value, result in data: prediction = (weight * value + bias) > 0 if prediction != result: error = result - prediction # +1 或 -1 weight += learning_rate * error * value bias += learning_rate * error decision_boundary = -bias / weight print(f"weight = {weight:.3f}") print(f"bias = {bias:.3f}") print(f"decision boundary = {decision_boundary:.3f}") ``` 要把它变成学生及格的机器,你只需要改两处:让数据变成考试分数,并设置 `result = score >= 50`;如果你想感受缺失偏置的痛苦,就把偏置冻结为 0。其余保持不变。 ### 致谢 这篇文章的核心灵感来自 Welch Labs 的精彩视频 [ChatGPT is made from 100 million of these [The Perceptron]](https://www.youtube.com/watch?v=l-9ALe3U-Fg)。如果你是视觉学习者,想了解这些概念背后的丰富历史与硬件,我强烈推荐观看! ### 下一步是什么? 你刚刚构建了一个能工作的感知机。它接收输入,加权,加上偏置,然后做出判断。它从自己的错误中学习,一个 epoch 接着一个 epoch。 一个神经元只能画一条直线。真正的魔法从堆叠开始:一个神经元的输出成为下一个神经元的输入。足够多的层叠在一起,你就得到了一个神经网络,它可以学习远复杂于一条直线的形状。但其中的每个神经元都在做你刚才看到的事情:一个权重,一个偏置,一个决策。 如果你想了解我是如何最终在加拿大写代码的非技术故事,我在这篇文章中写了:[The Outsider Who Shipped Anyway](https://ranpara.net/posts/the-outsider-who-shipped-anyway/)。 谢谢你和我一起构建。现在去修改数字,把它弄坏吧——这是最快的学习方法。

相似文章

Age of Empires II 中的感知器

Hacker News Top

本文演示了在游戏 Age of Empires II 中构建一个感知器和与非门,认为改变 LLM 的基质会改变对属性的感知,并批评了关于 LLM 拟人化的研究。