当前位置:首页>python>感知机:30 行 Python 从零写一个会"犯错-学习"的神经网络分类器

感知机:30 行 Python 从零写一个会"犯错-学习"的神经网络分类器

  • 2026-10-21 12:43:28
感知机:30 行 Python 从零写一个会"犯错-学习"的神经网络分类器

感知机:神经网络的第一个细胞

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₁
x₂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 的朋友 👍

最新文章

随机文章