欢迎光临
我们一直在努力

第二章感知机

感知机 (Perceptron)

  • 提出时间:1957 年
  • 提出者:弗兰克·罗森布拉特 (Frank Rosenblatt) —— 美国康奈尔航空实验室的心理学家。
  • 灵感原型:生物神经元(基于 1943 年提出的 McCulloch-Pitts 神经元模型)。
  • 算法本质:一种二类线性分类器。
    • 简单说,就是在一个平面上画一条直线,把东西分成“是”和“否”两类。
  • 硬件载体:最初不是纯软件,而是一台名为 Mark I Perceptron 的庞大机器(用电位器和电机模拟权重调节)。

感知机的运行原理非常简单,可以用一个公式概括:加权求和,然后过阈值。

在《深度学习入门》这本书里,作者为了让你适应后续神经网络的写法,将数学公式分成了两个阶段。我们直接看最成熟的那个版本(引入偏置 bbb 后的版本)。

1. 核心数学公式

感知机接收两个输入信号 x1,x2x_1, x_2x1,x2,最终输出一个信号 yyy(0 或 1)。

y={0(b+w1x1+w2x2≤0)1(b+w1x1+w2x2>0)y = \\begin{cases} 0 & (b + w_1x_1 + w_2x_2 \\le 0) \\\\ 1 & (b + w_1x_1 + w_2x_2 > 0) \\end{cases}y={01(b+w1x1+w2x20)(b+w1x1+w2x2>0)

这个公式虽然只有两行,但它包含了三个关键部分,我们逐一拆解:


2. 公式拆解(三个变量的含义)

A. 输入信号 (xxx)
  • 符号:x1,x2x_1, x_2x1,x2
  • 含义:外界传递给神经元的信息。比如“天气是否晴朗(1/0)”、“是否有空(1/0)”。
B. 权重 (www) —— “控制信号的重要性”
  • 符号:w1,w2w_1, w_2w1,w2 (Weight)
  • 含义:权重的绝对值越大,对应的输入信号对结果的影响就越大。
    • 如果 w1=0.5w_1 = 0.5w1=0.5w2=2.0w_2 = 2.0w2=2.0,说明 x2x_2x2x1x_1x1 重要得多。
  • 物理类比:水管的粗细。权重越大,水管越粗,流过去的水(信号)就越多。
C. 偏置 (bbb) —— “控制兴奋的难易度”
  • 符号:bbb (Bias)
  • 含义:这是一个常数,它决定了神经元被激活的门槛。
    • 注意公式里的 b+⋯>0b + \\dots > 0b+>0。如果 bbb 是一个很大的负数(例如 −100-100100),那么 w1x1+w2x2w_1x_1 + w_2x_2w1x1+w2x2 必须非常大才能把结果拉到 0 以上。这就叫“很难激活”。
    • 如果 bbb 是正数,哪怕没有输入,神经元也可能处于激活状态。
  • 书中的变化:书里最开始用的是 θ\\thetaθ (阈值),公式是 w1x1+w2x2>θw_1x_1 + w_2x_2 > \\thetaw1x1+w2x2>θ。后来把 θ\\thetaθ 移到左边变成了 −θ- \\thetaθ,也就是现在的 bbb。这是为了方便后续用矩阵计算。

3. 向量形式(NumPy 写法)

既然你已经学了 NumPy,感知机的公式其实可以写得更优雅。

如果我们把输入和权重看作向量:

  • 输入向量 x=[x1,x2]\\mathbf{x} = [x_1, x_2]x=[x1,x2]
  • 权重向量 w=[w1,w2]\\mathbf{w} = [w_1, w_2]w=[w1,w2]

那么公式就变成了点积 (Dot Product) 加上偏置:

A=w⋅x+bA = \\mathbf{w} \\cdot \\mathbf{x} + bA=wx+b

y={0(A≤0)1(A>0)y = \\begin{cases} 0 & (A \\le 0) \\\\ 1 & (A > 0) \\end{cases}y={01(A0)(A>0)

这一步非常关键!因为它把物理上的“信号传输”变成了数学上的“矩阵运算”。

总结

感知机就是在做一件事:

计算 XXXWWW 的加权和,加上偏置 bbb,如果结果大于 0,就输出 1;否则输出 0。

这就是所谓的“线性分类器”的数学本质。你现在能理解为什么偏置 bbb 这么重要了吗?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

问得好!这个 “1” (偏置输入) 其实是深度学习里一个非常经典的**“数学障眼法”**。

简单来说:为了让计算更统一,我们虚构了一个永远是 1 的输入节点。

我们可以分两步来拆解这个设计:

1. 为什么要强行加个“1”?

你看原本的公式是这样的:

y=(w1x1+w2x2)+by = (w_1x_1 + w_2x_2) + by=(w1x1+w2x2)+b

这里有个尴尬的地方:

  • w1w_1w1w2w_2w2 都有对应的 xxx 相乘。
  • bbb 是孤零零的一个常数,没有 xxx 和它配对。

这在数学写法上不够“整齐”。于是,数学家们想了个办法:给 bbb 也配一个伴侣!

因为 b×1=bb \\times 1 = bb×1=b,所以公式可以改写成:

y=w1x1+w2x2+b⋅1y = w_1x_1 + w_2x_2 + \\mathbf{b \\cdot 1}y=w1x1+w2x2+b1

2. 图解的变化

为了配合这个新公式,我们在画图时:

  • 把 偏置 bbb 看作是一个特殊的 权重 (Weight)。
  • 把这个 “1” 看作是一个特殊的 输入 (Input)。

这样一来,图里的每一个箭头就都变成了 “输入 ×\\times× 权重” 的形式。

  • 普通输入:x1,x2x_1, x_2x1,x2 (是变化的)
  • 偏置输入:111 (永远固定是 1)
  • 偏置权重:bbb (这也是我们要学习的参数)

💡 一个生活中的类比

想象你在搞一次考试:

  • 题目得分:x1x_1x1 是答对的题数,w1w_1w1 是每题的分数。这是 w1x1w_1x_1w1x1
  • 卷面起步分:老师规定,只要名字写对了,就先送你 10 分。

这个 10 分 (bbb) 怎么算进总分里?

你可以把它想象成:有一道特殊的“送分题”(输入永远是 1),但这道题的分值是 10 分(权重是 bbb)。


⚠️ 代码里的区别

在《深度学习入门》这本书的代码实现(NumPy)里,你会发现作者为了让你看懂,并没有刻意去构造这个“1”的数组,而是直接写成了:

Python

import numpy as np
x = np.array([0, 1]) # 输入
w = np.array([0.5, 0.5]) # 权重
b = -0.7 # 偏置

# 作者直接把 b 单独加上去了,这更符合直觉
y = np.sum(w*x) + b

但在更高级的框架(比如 TensorFlow 或 PyTorch)或者书后面讲到矩阵运算时,这个“虚构的 1”经常会被整合进矩阵里,让所有运算都变成单纯的矩阵乘法(Dot Product),以此来提升计算速度。

所以,看到那个“1”,你就把它当成是专门用来承载 bbb 的一个“虚拟插座”就好了。

与门 (AND Gate) 是感知机能实现的最简单的逻辑电路之一。在《深度学习入门》第二章,这也是你遇到的第一个“用参数控制逻辑”的例子。

它的逻辑非常直观:只有当两个输入 x1x_1x1x2x_2x2 都是 1 时,才会输出 1;否则输出 0。

1. 它的“真值表” (Truth Table)

这是我们在设计感知机参数时的“目标清单”:

x1 (输入1)x2 (输入2)y (期望输出)
0 0 0
1 0 0
0 1 0
1 1 1

2. 如何用感知机实现?

我们需要找到一组 权重 (w1,w2w_1, w_2w1,w2) 和 偏置 (bbb),代入感知机公式:

y={0(b+w1x1+w2x2≤0)1(b+w1x1+w2x2>0)y = \\begin{cases} 0 & (b + w_1x_1 + w_2x_2 \\le 0) \\\\ 1 & (b + w_1x_1 + w_2x_2 > 0) \\end{cases}y={01(b+w1x1+w2x20)(b+w1x1+w2x2>0)

让它满足上面的真值表。

思考过程(解谜时间):
  • 看最后一行:当 x1=1,x2=1x_1=1, x_2=1x1=1,x2=1 时,加权和必须大于 0。
    • 也就是 w1+w2+b>0w_1 + w_2 + b > 0w1+w2+b>0
  • 看中间两行:当只有一个是 1 时,加权和必须小于等于 0。
    • 也就是 w1+b≤0w_1 + b \\le 0w1+b0w2+b≤0w_2 + b \\le 0w2+b0
  • 满足条件的解(这组解不唯一):

    书中给出的经典参数是:

    • w1=0.5w_1 = 0.5w1=0.5
    • w2=0.5w_2 = 0.5w2=0.5
    • b=−0.7b = -0.7b=0.7

    我们来验算一下:

    • (0, 0): 0+0−0.7=−0.70 + 0 – 0.7 = -0.70+00.7=0.7 (≤0\\le 00) →\\rightarrow 输出 0 ✅
    • (1, 0): 0.5+0−0.7=−0.20.5 + 0 – 0.7 = -0.20.5+00.7=0.2 (≤0\\le 00) →\\rightarrow 输出 0 ✅
    • (0, 1): 0+0.5−0.7=−0.20 + 0.5 – 0.7 = -0.20+0.50.7=0.2 (≤0\\le 00) →\\rightarrow 输出 0 ✅
    • (1, 1): 0.5+0.5−0.7=0.30.5 + 0.5 – 0.7 = 0.30.5+0.50.7=0.3 (>0> 0>0) →\\rightarrow 输出 1 ✅

    3. 几何意义(画条线)

    如果我们在平面坐标系上画出来,与门其实就是画一条直线,把 (1,1)(1, 1)(1,1) 这个点单独圈出来,把它和另外三个点 (0,0),(0,1),(1,0)(0,0), (0,1), (1,0)(0,0),(0,1),(1,0) 分开。

    这条直线就是 0.5×1+0.5×2−0.7=00.5x_1 + 0.5x_2 – 0.7 = 00.5x1+0.5x20.7=0

    与非门 (NAND Gate) 的全称是 Not AND。

    顾名思义,它就是与门 (AND) 的“唱反调”版本。它的输出结果和与门完全相反。

    1. 它的逻辑:专门“拆散”一对

    • 与门:只有两人都同意 (1,1)(1, 1)(1,1),结果才通过 (1)(1)(1)
    • 与非门:只有两人都同意 (1,1)(1, 1)(1,1),结果才不通过 (0)(0)(0);其他情况统统通过 (1)(1)(1)

    看看它的真值表:

    x1x2y (输出)
    0 0 1
    1 0 1
    0 1 1
    1 1 0

    2. 参数怎么变?(甚至不需要动脑算)

    你还记得刚才与门的参数吗?

    • w1=0.5w_1 = 0.5w1=0.5
    • w2=0.5w_2 = 0.5w2=0.5
    • b=−0.7b = -0.7b=0.7

    要实现与非门,最简单的方法就是把所有符号反过来(乘以 −1-11):

    • w1=−0.5w_1 = -0.5w1=0.5
    • w2=−0.5w_2 = -0.5w2=0.5
    • b=0.7b = 0.7b=0.7

    我们来快速验算一下那个“特殊情况” (1,1)(1, 1)(1,1)

    (−0.5×1)+(−0.5×1)+0.7=−0.3(-0.5 \\times 1) + (-0.5 \\times 1) + 0.7 = -0.3(0.5×1)+(0.5×1)+0.7=0.3

    结果是 −0.3-0.30.3≤0\\le 00),所以输出 0。没毛病!

    3. 深度学习的一个重要启示

    在《深度学习入门》这本书里,作者特意把 AND、NAND、OR 放在一起讲,是为了告诉你一个深刻的道理:

    感知机的“构造”是完全一样的。

    你看,无论是 AND 还是 NAND,模型的形状(代码逻辑)没有任何改变。改变的只是 参数(权重和偏置)。

    • 这就好比同一个收音机,只是旋钮(参数)拧到了不同的位置,就能收到不同的频道(功能)。
    • 深度学习的训练过程,其实就是在自动寻找这些旋钮的最佳位置。

    或门 (OR Gate) 是感知机三兄弟里最“随和”、“宽容”的一个。

    它的逻辑很简单:只要有一点信号(输入里有一个 1),我就让你过(输出 1)。

    只有在彻底没信号(两个输入都是 0)的时候,它才会拒绝(输出 0)。


    1. 它的“真值表”

    看看它有多容易被激活:

    x1x2y (输出)
    0 0 0
    1 0 1
    0 1 1
    1 1 1

    2. 怎么调参数?(找感觉)

    我们再回头看看公式:

    y={0(b+w1x1+w2x2≤0)1(b+w1x1+w2x2>0)y = \\begin{cases} 0 & (b + w_1x_1 + w_2x_2 \\le 0) \\\\ 1 & (b + w_1x_1 + w_2x_2 > 0) \\end{cases}y={01(b+w1x1+w2x20)(b+w1x1+w2x2>0)

    想象一下:

    • 权重 (www) 还是保持 0.50.50.5 不变(只要有输入,就有贡献)。
    • 偏置 (bbb) 应该怎么变?
      • 在 与门 (AND) 里,我们要很严格,只有两份 0.50.50.5 加起来才能抵消 bbbb=−0.7b=-0.7b=0.7)。
      • 在 或门 (OR) 里,我们要很宽松,只要有一份 0.50.50.5,就应该能抵消 bbb,让结果大于 0。

    所以,bbb 的负值必须变小(门槛变低)。

    比如把 bbb 设为 −0.2-0.20.2

    验算一下:

    • (1, 0): 0.5+0−0.2=0.30.5 + 0 – 0.2 = 0.30.5+00.2=0.3 (>0> 0>0) →\\rightarrow 输出 1 ✅
    • (0, 0): 0+0−0.2=−0.20 + 0 – 0.2 = -0.20+00.2=0.2 (≤0\\le 00) →\\rightarrow 输出 0 ✅

    3. 暴风雨前的宁静

    到现在为止,我们学了 AND、NAND、OR。

    你发现没有?它们都有一个共同点:

    都能用一条直线把结果分开。

    在平面图上,无论是切掉 (0,0)(0,0)(0,0),还是切掉 (1,1)(1,1)(1,1),只要画一条直线就能把“输出 0 的点”和“输出 1 的点”完美分割开。这在数学上叫 “线性可分”。

    这绝对是《深度学习入门》这本书里的第一个高潮,也是人工智能历史上著名的“至暗时刻”。

    我们之前学的 AND、NAND、OR 门,仿佛无所不能。但到了 异或门 (XOR Gate) 这里,单层感知机就像撞上了一堵墙。

    让我们来看看为什么这堵墙这么硬。


    1. 什么是异或 (XOR)?

    XOR 全称是 Exclusive OR(互斥或)。

    它的逻辑是:只有当两个输入不同的时候,才输出 1。 如果两个输入一样(都是 0 或者都是 1),它就拒绝(输出 0)。

    真值表 (Truth Table):

    x1x2y (输出)备注
    0 0 0 相同,拒绝
    1 0 1 不同,通过
    0 1 1 不同,通过
    1 1 0 相同,拒绝

    2. 为什么感知机搞不定它?

    为了理解这个问题,我们必须把这四个点画在坐标轴上。

    • 圆圈 (○) 代表输出 0 的点:(0,0)(0, 0)(0,0)(1,1)(1, 1)(1,1)
    • 三角 (△) 代表输出 1 的点:(1,0)(1, 0)(1,0)(0,1)(0, 1)(0,1)
    核心冲突:直线 vs. 曲线

    感知机的数学公式 y=w1x1+w2x2+by = w_1x_1 + w_2x_2 + by=w1x1+w2x2+b 在几何上代表什么?

    它代表一条 直线。

    • 不管你怎么调整 www(斜率)和 bbb(截距),它永远是一条直挺挺的线。

    请你试想一下:

    你能画一条直线,把图中的两个 ○ 和两个 △ 完美分开吗?

    • 如果你把直线画在 (0,0)(0,0)(0,0)(1,0)(1,0)(1,0) 之间,那 (1,1)(1,1)(1,1) 这个 ○ 就被错分到 △ 那边去了。
    • 不管你怎么旋转这条线,总有一个点会“跑错阵营”。

    这就是感知机的致命局限性:它只能解决线性可分的问题。 而 XOR 是一个典型的 非线性 问题。


    3. 历史上的“AI 寒冬”

    这件事在历史上非常有名。

    1969 年,AI 界的泰斗 马文·明斯基 (Marvin Minsky) 和 西摩·派普特 (Seymour Papert) 写了一本书叫《感知机》。他们在书中从数学上严格证明了:单层感知机甚至连简单的 XOR 逻辑都无法实现。

    这一结论给当时热火朝天的神经网络研究泼了一盆冰水。大家觉得:“搞了半天,这东西连个简单的逻辑电路都比不上,还能指望它像人脑一样思考?”

    于是,神经网络的研究进入了长达十几年的冰河期 (AI Winter)。


    4. 怎么破局?(多层感知机)

    虽然一条直线分不开,但如果我们能画两条直线呢?或者画一条曲线呢?

    这就是《深度学习入门》接下来要讲的精彩部分:叠加层数。

    虽然单层感知机搞不定 XOR,但我们可以组合已有的门来解决它。

    逻辑电路里有一个著名的公式:

    XOR=(NAND)+(OR)+(AND)\\text{XOR} = (\\text{NAND}) + (\\text{OR}) + (\\text{AND})XOR=(NAND)+(OR)+(AND)

    意思是:我们可以把 NAND、OR、AND 这三个简单的感知机像搭积木一样叠起来。

  • 第 0 层:输入 x1,x2x_1, x_2x1,x2
  • 第 1 层:分别经过 NAND 门 和 OR 门。
  • 第 2 层:把第 1 层的两个输出,作为输入传给 AND 门。
  • 神奇的事情发生了:通过多层结构的组合,直线变成了曲线(或者说多条直线的组合),原本分不开的区域现在可以分开了!

    为了让你看着更踏实,我把这个逻辑像剥洋葱一样彻底拆解给你看,证明它是如何“天衣无缝”的。


    1. 拆解证明:为什么这三个门拼起来就是 XOR?

    我们用真值表来一步步推导。请盯着中间那两列(也就是第一层的输出 s1s_1s1s2s_2s2):

    公式逻辑:y=AND(s1,s2)y = \\text{AND}(s_1, s_2)y=AND(s1,s2),其中 s1=NANDs_1 = \\text{NAND}s1=NANDs2=ORs_2 = \\text{OR}s2=OR

    输入 x1输入 x2第1步: NAND (s1)(只有1,1是0)第2步: OR (s2)(有1就是1)第3步: AND (y)(s1 和 s2 都是1才行)结果分析
    0 0 1 0 0 ✅ (相同为0)
    1 0 1 1 1 ✅ (不同为1)
    0 1 1 1 1 ✅ (不同为1)
    1 1 0 1 0 ✅ (相同为0)

    2. 直观理解:它们在“吵架”还是“合作”?

    你可以把这三个门想象成三个安检员,它们在筛选符合“异或(XOR)”条件的人(条件是:必须一男一女,不能两个男也不能两个女)。

    • OR 门(安检员 A)说:“你们两个至少要有一个人是男的(是 1),否则别想过!”
      • 结果:把 (0,0)(0, 0)(0,0) 拦住了。
    • NAND 门(安检员 B)说:“你们两个不能同时都是男的(都是 1),否则别想过!”
      • 结果:把 (1,1)(1, 1)(1,1) 拦住了。
    • AND 门(最终 Boss)说:“安检员 A 和 B 都放行的人,我才放行。”
      • 最终结果:只有 (1,0)(1, 0)(1,0)(0,1)(0, 1)(0,1) 这种“一男一女”的情况,才能同时通过 A 和 B 的检查,最终被 Boss 放行。

    这就是**“组合”**的力量。

    3. 这在书中的意义

    你在图片里看到的这段文字,核心想表达的是:

    单层感知机(一个门)是线性的,像一把直尺,解决不了 XOR 问题。

    多层感知机(把门叠起来)是非线性的,像一把剪刀,能把需要的区域剪出来。

    你现在学的这个结构:

    输入 -> [NAND, OR] -> [AND] -> 输出

    正是最简单的 2 层神经网络。

    所以,结论是:完全正确,尽管放心大胆地往下学! 第三章会告诉你,这种“搭积木”的思想是如何演变成现代能识别猫狗、能写代码的超级 AI 的。


    总结

    • 局限性:单层感知机只能画直线(线性分类),无法处理非线性分布的数据(如 XOR)。
    • 解决方法:多层感知机 (Multi-layer Perceptron, MLP)。
      • 这一步跨越非常重要,因为它标志着我们从简单的“逻辑门”迈向了真正的“神经网络”。
      • 现在的深度学习,其实就是叠加了无数层的感知机。

    实现代码:

    import numpy as np

    # 1. 定义与门 (AND)
    def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5]) # 权重
    b = 0.7 # 偏置

    # 核心公式:w*x + b
    tmp = np.sum(w * x) + b

    if tmp <= 0:
    return 0
    else:
    return 1

    # 2. 定义与非门 (NAND)
    def NAND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5]) # 权重变负(与AND相反)
    b = 0.7 # 偏置变正

    tmp = np.sum(w * x) + b

    if tmp <= 0:
    return 0
    else:
    return 1

    # 3. 定义或门 (OR)
    def OR(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5]) # 权重
    b = 0.2 # 偏置(门槛降低)

    tmp = np.sum(w * x) + b

    if tmp <= 0:
    return 0
    else:
    return 1

    # ==========================================
    # 测试部分 (验证真值表)
    # ==========================================

    print("— AND 门测试 —")
    print(f"AND(0, 0) -> {AND(0, 0)}")
    print(f"AND(1, 0) -> {AND(1, 0)}")
    print(f"AND(0, 1) -> {AND(0, 1)}")
    print(f"AND(1, 1) -> {AND(1, 1)}")

    print("\\n— NAND 门测试 —")
    print(f"NAND(0, 0) -> {NAND(0, 0)}")
    print(f"NAND(1, 0) -> {NAND(1, 0)}")
    print(f"NAND(0, 1) -> {NAND(0, 1)}")
    print(f"NAND(1, 1) -> {NAND(1, 1)}")

    print("\\n— OR 门测试 —")
    print(f"OR(0, 0) -> {OR(0, 0)}")
    print(f"OR(1, 0) -> {OR(1, 0)}")
    print(f"OR(0, 1) -> {OR(0, 1)}")
    print(f"OR(1, 1) -> {OR(1, 1)}")

    def XOR(x1, x2):
    s1 = NAND(x1, x2)
    s2 = OR(x1, x2)
    y = AND(s1, s2)
    return y

    print("\\n— XOR 门测试 —")
    print(f"XOR(0, 0) -> {XOR(0, 0)}") # 0
    print(f"XOR(1, 0) -> {XOR(1, 0)}") # 1
    print(f"XOR(0, 1) -> {XOR(0, 1)}") # 1
    print(f"XOR(1, 1) -> {XOR(1, 1)}") # 0

    (1, 0) -> {NAND(1, 0)}“)
    print(f"NAND(0, 1) -> {NAND(0, 1)}”)
    print(f"NAND(1, 1) -> {NAND(1, 1)}")

    print(“\\n— OR 门测试 —”)
    print(f"OR(0, 0) -> {OR(0, 0)}“)
    print(f"OR(1, 0) -> {OR(1, 0)}”)
    print(f"OR(0, 1) -> {OR(0, 1)}“)
    print(f"OR(1, 1) -> {OR(1, 1)}”)

    def XOR(x1, x2):
    s1 = NAND(x1, x2)
    s2 = OR(x1, x2)
    y = AND(s1, s2)
    return y

    print(“\\n— XOR 门测试 —”)
    print(f"XOR(0, 0) -> {XOR(0, 0)}“) # 0
    print(f"XOR(1, 0) -> {XOR(1, 0)}”) # 1
    print(f"XOR(0, 1) -> {XOR(0, 1)}“) # 1
    print(f"XOR(1, 1) -> {XOR(1, 1)}”) # 0

    赞(0)
    未经允许不得转载:171主机测评 » 第二章感知机
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址