第2章 感知机
本章将介绍感知机A(perceptron)这一算法。感知机是由美国学者Frank Rosenblatt在1957年提出来的。为何我们现在还要学习这一很久以前就有的算法呢?因为感知机也是作为神经网络(深度学习)的起源的算法。因此,学习感知机的构造也就是学习通向神经网络和深度学习的一种重要思想。
2.1 感知机是什么
感知机(Perceptron)是模拟神经元行为的简单算法。它根据输入的信号是否超过某个阈值,决定输出0还是1,就像一个会“判断”的小脑袋。
公式如下:
y = { 0 ( w ⋅ x + b ≤ 0 ) 1 ( w ⋅ x + b > 0 ) y = \begin{cases} 0 & (w \cdot x + b \leq 0) \\ 1 & (w \cdot x + b > 0) \end{cases} y={01(w⋅x+b≤0)(w⋅x+b>0)
其中:
- x x x 是输入向量
- w w w 是权重向量
- b b b 是偏置(等价于负的阈值)
2.2 简单逻辑电路
2.2.1 与门
与门(AND)在输入都是1时输出1,其余为0:
def AND(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.7
tmp = x1 * w1 + x2 * w2
return 1 if tmp > theta else 0
测试:
for x in [(0,0), (0,1), (1,0), (1,1)]:
print(f"AND{x} => {AND(*x)}")
输出:
AND(0, 0) => 0
AND(0, 1) => 0
AND(1, 0) => 0
AND(1, 1) => 1
2.2.2 与非门和或门
NAND(与非)门:
NAND是Not AND的意思,与非门就是颠倒了与门的输出。
def NAND(x1, x2):
import numpy as np
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
return 1 if np.sum(w * x) + b > 0 else 0
OR(或)门:
或门是“只要有一个输入信号是1,输出就为1”的逻辑电路。
def OR(x1, x2):
import numpy as np
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.2
return 1 if np.sum(w * x) + b > 0 else 0
如上所示,我们已经知道使用感知机可以表示与门、与非门、或门的逻辑电路。这里重要的一点是:与门、与非门、或门的感知机构造是一样的。实际上,3个门电路只有参数的值(权重和阈值)不同。也就是说,相同构造的感知机,只需通过适当地调整参数的值,就可以像“变色龙演员”表演不同的角色一样,变身为与门、与非门、或门。
2.3 感知机的实现
2.3.1 简单的实现
最初版的感知机我们使用 if 条件判断和加权和:
def AND(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.7
tmp = x1 * w1 + x2 * w2
return 1 if tmp > theta else 0
2.3.2 导入权重和偏置
通过引入偏置 b = − θ b = -\theta b=−θ,公式变为:
y
=
{
0
(
w
⋅
x
+
b
≤
0
)
1
(
w
⋅
x
+
b
>
0
)
y = \begin{cases} 0 & (w \cdot x + b \leq 0) \\ 1 & (w \cdot x + b > 0) \end{cases}
y={01(w⋅x+b≤0)(w⋅x+b>0)
这个式子和之前的式子虽然有一个符号不同,但表达的内容是完全相同的。此处,b称为偏置,w₁和w₂称为权重。如式2所示,感知机会计算输入信号和权重的乘积,然后加上偏置,如果这个值大于0则输出1,否则输出0。下面,我们使用NumPy,按式2的方式实现感知机。在这个过程中,我们用Python的解释器逐一确认结果。
2.3.3 使用权重和偏置的实现
与门:
import numpy as np
def AND(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.7
return 1 if np.sum(x * w) + b > 0 else 0
NAND(与非)门:
def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5]) # 权重为负(取反)
b = 0.7
return 1 if np.sum(w * x) + b > 0 else 0
OR(或)门:
def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5]) # 和 AND 相同权重
b = -0.2 # 更小的偏置使得只需1个输入为1即可激活
return 1 if np.sum(w * x) + b > 0 else 0
🔍 为什么 AND、OR、NAND 的权重和偏置是这些值?
✅ 1. 为什么 AND 的 w 和 b 是 [0.5, 0.5]
, -0.7
我们来看 AND 的输出要求:
x1 | x2 | 期望输出 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 ✅ |
所以我们希望:
- 只有在 (1,1) 时输出 > 0(即激活)
- 其他情况
加权和 + 偏置 <= 0
试一下计算:
- (1,1):
0.5*1 + 0.5*1 + (-0.7)
=1.0 - 0.7 = 0.3 > 0 ✅
- (1,0):
0.5 + 0 + (-0.7) = -0.2 ❌
- (0,1):
0.5 + 0 + (-0.7) = -0.2 ❌
- (0,0):
0 - 0.7 = -0.7 ❌
这就刚好满足我们对 AND 的“真值表”需求。
✅ 2. 为什么 OR 的 w 是 [0.5, 0.5]
, b 是 -0.2
OR 的要求是:
x1 | x2 | 输出 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 ✅ |
0 | 1 | 1 ✅ |
1 | 1 | 1 ✅ |
我们要求:
- 只要有一个为1就激活
选 [0.5, 0.5]
是因为我们想让两个输入权重“等价”。
验证计算:
- (1,0):
0.5 + 0 - 0.2 = 0.3 > 0 ✅
- (0,1):
0.5 + 0 - 0.2 = 0.3 > 0 ✅
- (1,1):
1.0 - 0.2 = 0.8 > 0 ✅
- (0,0):
0.0 - 0.2 = -0.2 ❌
也刚好满足 OR 的逻辑规则!
✅ 3. 为什么 NAND 是 w = [-0.5, -0.5]
, b = 0.7
NAND 是 AND 的反逻辑:
x1 | x2 | 输出 |
---|---|---|
0 | 0 | 1 ✅ |
0 | 1 | 1 ✅ |
1 | 0 | 1 ✅ |
1 | 1 | 0 ❌ |
我们可以从 AND 的逻辑取反来理解:
- 原来只有 (1,1) 输出1,现在 (1,1) 输出0
- 所以我们只要把权重取反,偏置调高一些
验证计算:
- (1,1):
-0.5 - 0.5 + 0.7 = -0.3 ❌
- (1,0):
-0.5 + 0 + 0.7 = 0.2 ✅
- (0,1):
0 - 0.5 + 0.7 = 0.2 ✅
- (0,0):
0 + 0 + 0.7 = 0.7 ✅
✅ 完美复现 NAND!
2.4 感知机的局限性
到这里我们已经知道,使用感知机可以实现与门、与非门、或门三种逻辑电路。现在我们来考虑一下异或门(XOR gate)。
2.4.1 异或门
异或门也被称为逻辑异或电路。如图2-5所示,仅当x1或x2中的一方为1时,才会输出1(“异或”是拒绝其他的意思)。那么,要用感知机实现这个异或门的话,应该设定什么样的权重参数呢?
异或(XOR)逻辑如下:
x1 | x2 | XOR |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
单层感知机无法表示这种逻辑,因为它是非线性可分的。
❌ 为什么单层感知机无法表示 XOR(异或)?
🧠 首先回顾 XOR 的逻辑:
x1 | x2 | XOR |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
通俗地说,两个输入一样时输出0,输入不一样时输出1。
🔍 图示理解
我们将输入点画在二维平面上:
- (0,0) → 输出 0(❌)
- (0,1) → 输出 1(✅)
- (1,0) → 输出 1(✅)
- (1,1) → 输出 0(❌)
你会发现 ——
无法只用一条直线把“输出为1”的点和“输出为0”的点分开!
📐 什么叫线性可分?
“线性可分”就是:能用一条直线(或超平面)把正例和负例完全分开。
像 AND、OR 都是线性可分:
- AND → 只有 (1,1) 为1,容易线性分隔
- OR → 任意有1即可为1,也很容易分隔
- NAND → AND 的反例,也能画线隔开
但 XOR 无论如何画一条线,都不能准确分类所有点。
🧱 为什么单层感知机不行?
因为单层感知机只能学一条“直线”的边界。
它内部的判断方式是:
y = { 1 if w ⋅ x + b > 0 0 otherwise y = \begin{cases} 1 \quad \text{if } w \cdot x + b > 0 \\ 0 \quad \text{otherwise} \end{cases} y={1if w⋅x+b>00otherwise
也就是用向量点积 + 偏置,判断是否大于0。
这就决定了它只能实现线性可分的问题。
✅ 如何解决:用多层感知机!
见2.5部分。
2.4.2 线性和非线性
感知机只能画一条直线来分类,但异或问题需要“弯曲”的边界,必须引入“多层结构”才能搞定。
2.5 多层感知机
2.5.1 已有门电路的组合
感知机不能表示异或门让人深感遗憾,但也无需悲观。实际上,感知机的绝妙之处在于它可以“叠加层”(通过叠加层来表示异或门是本节的要点)。这里,我们暂且不考虑叠加层具体是指什么,先从其他视角来思考一下异或门的问题。
异或门可以通过图2-11所示的配置来实现。这里,x1和x2表示输入信号,y表示输出信号。x1和x2是与非门和或门的输入,而与非门和或门的输出则是与门的输入。
最后有:
2.5.2 异或门的实现
我们用现成的 NAND、OR、AND 组合构建 XOR:
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
return AND(s1, s2)
for x in [(0,0), (0,1), (1,0), (1,1)]:
print(f"XOR{x} => {XOR(*x)}")
这个XOR函数会输出预期的结果。
XOR(0, 0) # 输出0
XOR(1, 0) # 输出1
XOR(0, 1) # 输出1
XOR(1, 1) # 输出0
这样,异或门的实现就完成了。下面我们试着用感知机的表示方法(明确地显示神经元)来表示这个异或门,结果如图2-13所示。
如图2-13所示,异或门是一种多层结构的神经网络。这里,将最左边的一列称为第0层,中间的一列称为第1层,最右边的一列称为第2层。
图2-13所示的感知机与前面介绍的与门、或门的感知机(图2-1)形状不同。实际上,与门、或门是单层感知机,而异或门是2层感知机。叠加了多层的感知机也称为多层感知机(multi-layered perceptron)。
2.6 从与非门到计算机
令人惊讶的是,仅凭“与非门”(NAND)就可以构建出整个计算机的基本逻辑单元。
感知机虽然简单,但它启发了现代神经网络的“积木式搭建”思想。
🤯 惊人的事实:任何逻辑电路都可以只用 NAND 构造!
我们常说构建计算机需要一堆逻辑门:AND、OR、NOT、XOR…… 但事实上:
只要你有足够多的 NAND 门,你可以构造出所有其它逻辑门,进而构建整个计算机。
这在数字电路中被称为:函数完备性(Functional Completeness)。
🔁 你可以用 NAND 门构建哪些?
目标门 | 由 NAND 实现方式 |
---|---|
NOT | A NAND A |
AND | (A NAND B) NAND (A NAND B) |
OR | (A NAND A) NAND (B NAND B) |
XOR | 多层组合 |
💡 那感知机呢?
我们前面实现的感知机,其实可以表示 NAND 门:
def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
return 1 if np.sum(w * x) + b > 0 else 0
这就意味着 ——
你可以用多个感知机拼成 NAND、AND、OR、XOR……
换句话说:
用感知机可以构建任意逻辑电路,而逻辑电路正是计算机的基础。
🧩 感知机构建计算机的“分阶段模块化”思想
在实际构建计算机(或数字系统)时,工程师并不会直接拿 NAND 门堆一个完整 CPU。而是采取一种**“由下而上、模块分层”**的方式,就像搭积木一样,把简单单元逐步组合成复杂系统。
这也和“用感知机模拟计算机”的思想高度一致。
🔨 分阶段构建计算机的步骤
我们通常会按如下顺序构建:
① 构建基础逻辑门(逻辑基础)
先用 NAND 构造出:
- NOT 门(非)
- AND 门(与)
- OR 门(或)
- XOR 门(异或)
这些是构建一切逻辑的“字母表”。
② 构建加法器(运算基础)
然后组合逻辑门,构造加法器(Adder):
- 半加器(Half Adder):能处理两个1位数相加
- 全加器(Full Adder):能处理进位 + 两数相加
加法器是构建“加法”运算的基本模块。
③ 构建算术逻辑单元(ALU)
ALU 是 CPU 的“计算核心”,可以执行:
- 加法、减法
- 与、或、异或等逻辑操作
- 条件判断(大于、小于、等于)
④ 构建 CPU(大脑)
再进一步,就可以构建一个CPU,具备:
- 寄存器(记忆)
- 运算控制逻辑
- 指令解码和执行能力
🧠 用感知机构建时也必须“分层叠加”
感知机能模拟 NAND 门,也能模拟 AND、OR……
但是要表示复杂运算,比如“加法”、“条件判断”,就必须:
将多个感知机组合成一层,再将多层组合成一个系统。
这就自然需要用多层结构来实现复杂功能:
- 第一层模拟基础逻辑
- 第二层组合出模块(加法器)
- 第三层组合成运算系统(ALU、CPU)
这和现代神经网络完全一致!
📌 总结:为什么“多层”是自然的?
在数字电路中,从门电路到CPU是逐层构建的。
在神经网络中,从感知机到深度学习也是逐层构建的。
感知机 = 可模拟逻辑门的神经元。
多个感知机组合起来,能够构造出数字电路 → 算术单元 → 控制单元 → CPU的完整路径。
虽然这在实际中效率很低,但从理论角度来看,是完全可行的
2.7 小结
- 感知机模仿神经元,用权重和偏置做简单分类
- 单层感知机能实现基本逻辑(AND、OR、NAND),但不能实现 XOR
- 多层感知机能实现非线性问题,为神经网络打下基础
- 多层感知机(在理论上)可以表示计算机。