感知机:神经网络的第一个细胞
1957 年的疯狂预言 · 加权求和 · 阶跃函数 · 梯度下降雏形 · 从零手写一个二分类器
1957 年,一个叫 Frank Rosenblatt 的人造了一台叫 Mark-1 感知机 的机器。它有 400 个光电池作为"眼睛",能识别简单的几何图形。当时《纽约时报》兴奋地预言这台机器将能"行走、说话、看见、书写、自我复制"。
预言夸张了,但感知机的核心思想——加权求和 + 阈值判断——至今仍是所有神经网络的基础单元。这节课我们用 Python 从零实现一个感知机,理解它的每一个细节。理解感知机 = 理解深度学习的 DNA。
📚 本节课你会学到: ① 感知机的历史与核心思想② 加权求和 + 阶跃激活函数的完整流程③ "犯错-调整"训练算法的直觉和公式④ 从零用 Python 实现感知机(含训练+测试)⑤ 感知机在二维平面画了一条线——直观理解⑥ 感知机的致命局限:为什么 XO 分不开 |
Python 热身:本节课用到的语法
这节课的核心计算全靠 NumPy——它能一瞬间算出几百个数的加权和。提前认识三个用法:
① NumPy 数组与点积 普通 Python 列表算加权和又慢又烦。NumPy 一个 np.dot 搞定: import numpy as np; z = np.dot([1,2,3], [0.5,0.3,0.1]) → 1.4 |
|
② random.choice 和列表推导式 训练时随机选样本用 random.choice;提取数据用一行列表推导式。 random.choice(正例) · x值 = [d["x"] for d in 数据] |
|
| ⚠️ 先装 NumPy:Jupyter 里运行 pip install numpy 即可。如果已经装了 Anaconda,NumPy 会自动包含。 |
一、1957 年:一个疯狂的预言
1957 年,康奈尔航空实验室的 Frank Rosenblatt 造了 Mark-1 感知机。输入是 20×20=400 个光电池,输出是二进制的"是三角形吗?是/否"。整个网络只有一个神经元,权重靠手动调节电位器来训练。
《纽约时报》当时的报道:"这是电子计算机的胚胎,海军预计它将能行走、说话、看见、书写、自我复制,并意识到自己的存在。"
| 💡 现在看来预言太乐观了——但感知机的核心思想(加权求和+阈值判断)到今天仍是所有神经网络的基础。下一课的多层感知机、后面的 CNN、Transformer,全部建立在这个最简单的细胞之上。 |
二、感知机是怎么工作的
感知机是二分类模型——只能回答"是 +1"或"不是 -1"。假设有 N 个特征,每个特征对应一个权重。原理就一句话:
输出 = f( w₁x₁ + w₂x₂ + ... + wₛxₛ ) 加权求和 → 过"门槛"函数 → 出结果 |
⚡ 阶跃激活函数 f(x) 如果 x ≥ 0 → 输出 +1(正类) 如果 x < 0 → 输出 -1(负类) 像个门槛:信号够强就触发,不够就沉默。 | 🧠 直觉理解 "要不要去跑步?" 天气好(+1)×0.5 + 不累(+1)×0.3 + 有朋友陪(+1)×0.2 → 总分 > 0 就去,否则不去。 |
🔬 感知机内部结构 | x₁ | | ↓ w₁=0.5 ↓ w₂=0.3 ↓ w₃=0.2 | | Σwx |
↓ 阶跃函数 f → +1(去!)或 -1(不去) |
三、感知机怎么学习:犯错,然后调整
感知机不会一开始就知道正确的权重。它的学习策略极其朴素——猜错了就调,猜对了就过:
第 1 步:初始化 所有权重设为 0(或很小的随机数)。感知机此时对世界一无所知。 |
|
第 2 步:随机挑一个样本,预测 从训练集随机选一个正例和一个负例,用当前权重算出输出。 |
|
第 3 步:如果猜错了,调整权重 正例被错判为负 → 权重加上特征值(往正方向拉)负例被错判为正 → 权重减去特征值(往负方向推) |
|
第 4 步:重复 N 次,直到收敛 不断循环 2-3 步。权重逐渐收敛到把两类干净分开的值。 |
|
| 💡 核心公式(不用完全懂,代码会帮我们算):w_new = w_old + η × (标签 × 特征)这就是梯度下降的雏形——每次朝误差减小的方向走一小步。步长取决于学习率 η:大了跳过头,小了学太慢。 |
四、动手写:从零实现感知机
分三步:造数据 → 训练 → 测试。30 行核心代码,直接复制到 Jupyter 跑。
第一步:生成训练数据
人为造一些"线性可分"的二维数据——正例在右上角,负例在左下角:
| import numpy as npimport random# 正例:在右上角 (x>0, y>0)正例 = [np.array([1.5,2.0]), np.array([3.0,1.5]), np.array([2.5,3.0]), np.array([3.5,2.5]), np.array([2.0,3.5])]# 负例:在左下角 (x<0, y<0)负例 = [np.array([-1.5,-2.0]), np.array([-2.5,-1.0]), np.array([-3.0,-2.5]), np.array([-1.0,-3.0]), np.array([-2.0,-3.5])] |
第二步:训练函数(核心)
| def训练感知机(正例, 负例, 迭代=100, 学习率=1.0): 维度 =len(正例[0]) +1# 特征数+1(偏置) 权重 = np.zeros(维度)foriinrange(迭代): 正样本, 负样本 = random.choice(正例), random.choice(负例) 正入 = np.append([1], 正样本) # 加偏置 负入 = np.append([1], 负样本)ifnp.dot(正入, 权重) <0: # 正例错判 权重 += 学习率 * 正入ifnp.dot(负入, 权重) >=0: # 负例错判 权重 -= 学习率 * 负入return权重最终权重 = 训练感知机(正例, 负例, 迭代=100, 学习率=1.0) |
| 💡 偏置 bias 是什么?往输入前面加的"1",对应的权重就是偏置。没有偏置的话,感知机只能画经过原点的直线,限制太大了。 |
第三步:测试——它学会了吗?
| def预测(权重, 样本): 输入 = np.append([1], 样本)return1if np.dot(输入, 权重) >= 0else -1# 测试新样本print(预测(最终权重, [2.0,2.0])) # → 1(右上角,正确!)print(预测(最终权重, [-2.0,-1.5])) # → -1(左下角,正确!) |
跑完这三步,训练集准确率应该是 100%——因为数据是人为构造的、线性可分的。如果不是 100%,试着把迭代次数从 100 改到 200,或者检查你的数据有没有混在一起。
五、直觉理解:感知机在二维平面画了一条线
当只有两个特征(x₁, x₂)时,感知机的决策公式其实就是一条直线:
w₀ + w₁x₁ + w₂x₂ = 0 这是一条直线的方程!一边是正类,一边是负类。 |
训练的过程,本质上是不断旋转和移动这条线,直到它刚好把正负两类分开。训练前权重都是 0,线不存在;训练后权重收敛,线干净地把两类切开。
训练前 权重全是 0,决策线不存在。正负例混在一起,感知机什么都分不清。 | 训练后 权重收敛,决策线(也叫"超平面")把两类干净分开。右上角 +1,左下角 -1。 |
| ⚠️ 感知机的致命局限:它只能处理线性可分的问题。如果数据像同心圆(正类在里圈、负类在外圈),一根直线永远分不开。1969 年 Minsky 在《感知机》一书中指出了这一点,直接导致了第一次 AI 冬天。解法?下一课的多层感知机。 |
六、现实应用:手写数字识别
课程 Notebook 里有一个更实战的例子:用感知机区分手写数字 0 和 1。28×28 = 784 个像素展平成向量,就是感知机的 784 个输入。每个像素一个特征,一个权重。
更进一步的挑战:识别 0-9 全部数字 策略是"一对多"——训练 10 个感知机,每个只管"这个数字是 X 吗?"最后投票。→ 在 Jupyter 里打开课程的 PerceptronMultiClass.ipynb 试试。 |
一张图记住感知机
输入 特征值 x₁, x₂, ..., xₛ(像素值、肿瘤大小等) |
|
计算 加权求和 z = w₁x₁ + w₂x₂ + ... + wₛxₛ + 偏置 |
|
激活 阶跃函数:z ≥ 0 → +1(正类),z < 0 → -1(负类) |
|
训练 猜错就调:正例错判 → 加特征值;负例错判 → 减特征值。这是梯度下降的雏形。 |
|
局限 只能处理线性可分问题。多层网络(下节课)突破了这个限制。 |
|
知识检测
(长按选中文字即可看到答案)
Q1. 感知机的输出是什么类型的? A. 二分类(+1或-1) B. 多分类 C. 任意实数值 D. 概率值 A。感知机是二分类器,只输出 +1 或 -1。 |
Q2. 感知机的核心计算是什么? A. 直接相加 B. 加权求和后过阶跃函数 C. 多层传播 D. Sigmoid 输出 B。加权求和(w₁x₁+w₂x₂+...)是核心,然后过阶跃函数。 |
Q3. 正例被错判为负时,权重怎么调? A. 不改 B. 把特征值加到权重上 C. 减特征值 D. 反向传播 B。正例错判说明权重太小,需要加上特征值往正方向拉。 |
Q4. 感知机最大的局限是什么? A. 永远学不会 B. 只能两个特征 C. 只能处理线性可分 D. 计算太慢 C。只能处理线性可分问题,这是 Minsky 1969 年指出的致命弱点。 |
课后行动
1 跑代码(必做) 把上面三块代码复制到 Jupyter Notebook,运行后确认准确率 100%。这节课不跑代码等于白学。 预计用时:20 分钟 |
2 调参实验 把学习率改成 0.1 和 5.0,观察训练过程有什么不同。迭代次数改到 10 和 500 呢?把发现的规律记下来。 预计用时:15 分钟 |
3 造数据 自己再造一组正例和负例(比如 x 很大的点),看感知机还能分开吗?如果正负例在图上交叉了会怎样? 预计用时:10 分钟 |
4 在线 Quiz 去课程页面做课前和课后测验(英文),看看正确率。链接在 Lesson 3 的 GitHub 页面里。 预计用时:10 分钟 |
下节课预告
一个感知机只能画一条线。如果把很多个感知机堆叠起来呢?下节课是整门课最硬核的一节:
• 多层网络突破 XOR 线性不可分• Sigmoid / ReLU 非线性激活函数替代粗糙的阶跃• 从零写一个微型深度学习框架(前向传播 + 反向传播)• 这是整个课程最值得投入时间的一节课
| 📌 下节课的数学预习:微积分中的"链式法则"和"偏导数"——听起来吓人,但我会用最直观的方式讲。你可以现在搜一下 3Blue1Brown 的反向传播视频,先建直觉。 |
课程来源:microsoft/AI-For-Beginners · Lesson 3 (Perceptron) Notebook:GitHub 搜 "AI-For-Beginners Perceptron.ipynb" |
🤖 代码跑通了吗?准确率到 100% 了吗? 把你的调参实验结果告诉我——学习率改成 0.1 和 5.0 分别发生了什么?——或者你自己造的数据长什么样。我们来讨论为什么有些情况感知机能分开,有些不行。 觉得有用的话,点「在看」转给一起学 AI 的朋友 👍 |