感知机(perceptron)是由美国学者 Frank Rosenblatt 在 1957 年提出的。它作为神经网络(深度学习)的起源的算法,是学习神经网络和深度学习的重要一环
感知机接收多个输入信号,输出一个信号。感知机的信号会形成流,向前方传递信息。感知机的信号只有‘流’/‘不流’(1/0)两种取值。本书中,0
表示‘不传递信号’,1 表示‘传递信号’
下图是一个接收两个输入信号的感知机的例子。x1、x2 是输入信号,y 是输出信号,w1、w2
是权重。圆形是‘神经元’或‘节点’。输入信号被送往神经元时,会被分别乘以固定的权重(w1x1,w2x2)
。神经元会计算传送过来的信号的总和,只有这个总和超过了某个界限值时,才会输出 1。这也称为‘神经元被激活’。这个界限值称为阈值,用符号
θ 表示
感知机的多个输入信号都有各自固有的权重,发挥着控制各个信号的重要性的作用。也就是说,权重越大,对应该权重的信号的重要性就越高
与门是有两个输入和一个输出的门电路。与门仅在两个输入均为 1 时输出 1,其他时候输出 0
如果用感知机来表示,怎么确定 w1、w2、θ 的值才能满足该真值表?
实际上,满足该条件的参数的选择方法有无数个。比如(w1,w2,θ)=(0.5,0.5,0.7) or (w1,w2,θ)=(0.5,0.5,0.8) or (w1,w2,θ)=(
1.0,1.0,1.0)时。设定这样的参数后,仅当 x1 和 x2 同时为 1 时,信号的加权总和才会超过给定的阈值 θ。
与非门就是颠倒了与门的输出。仅当 x1 和 x2 同时为 1 时输出 0,其他时候则输出 1
感知机表示与非门,只需要将实现与门的参数值的符号取反就可以实现
与门是‘只要有一个输入信号是 1,输出就为 1’的逻辑电路
与门、与非门、或门的感知机构造是一样的。它们只有参数的值(权重和阈值)不同。也就是说,相同构造的感知机只要调整参数的值,就可以变成不同的逻辑电路
先定义一个接收参数 x1 和 x2 的 AND 函数
def AND(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.7
tmp = x1 * w1 + x2 * w2
if tmp <= theta:
return 0
elif tmp > theta:
return 1
在函数内初始化参数 w1、w2、theta,但输入的加权总和超过阈值时返回 1,否则返回 0
print(AND(0, 0)) # 0
print(AND(0, 1)) # 0
print(AND(1, 0)) # 0
print(AND(1, 1)) # 1
将之前的式子的阈值换成偏置,即 θ 换成-b
改变后,表达的内容依然完全相同。b 称为偏置,w 称为权重,感知机计算输入信号和权重的乘积,然后加上偏置,如果这个值大于 0 则输出
1,否则输出 0。
import numpy as np
x = np.array([0, 1]) # 输入
w = np.array([0.5, 0.5]) # 权重
b = -0.7 # 偏置
print(w * x)
np.sum(w * x)
print(np.sum(w * x) + b)
# -0.19999999999999996 大约为-0.2(由浮点小数造成的运算误差)
这里 numpy 数组乘法运算,当两个数组的元素个数相同时,各个元素分别相乘,之后 sum(w*x)计算相乘后的各个元素的总和。最后加上偏置,完成计算
def AND(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.7
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
权重 w1、w2 是控制输入信号的重要性的参数,而偏置是调整神经元被激活的容易程度(输出信号为 1 的程度)的参数。
继续实现与非门和或门
def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
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
异或门也称为逻辑异或电路。仅当 x1 或 x2 中的一方为 1 时,才会输出 1(‘异或’是拒绝其他的意思)。
前面介绍的感知机无法实现这个异或门。
我们将或门的动作形象化。或门的情况下,当权重参数(b,w1,w2)=(-0.5,1.0,1.0)时,可以用下面的式子表示
该式表示感知机会生成由直线-0.5 + x1 + x2 = 0 分割开的两个空间。其中一个空间输出 1,另一个空间输出 0
但是如何用一条直线分割出异或的 0、1 输出空间?事实上,用一条直线无法将 0、1 分开
感知机的局限性就在于它只能表示由一条直线分割的空间。如果用曲线分割,就可以实现。由曲线分割而成的空间称为非线性空间,由直线分割而成的空间称为线性空间。线性和非线性这两个术语在机器学习领域很常见。
感知机的绝妙之处在于它可以‘叠加层’(通过叠加层来表示异或门或门是本节的要点)。我们暂不考虑叠加层具体是指什么,先从其他视角来思考一下异或门的问题。
异或门制作方法有很多,其中之一就是与门、或门、与非门的组合。这几个门我们用下面的符号表示,图 2-9 中与非门前端的〇表示反转输出的意思
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
print(XOR(0, 0)) # 0
print(XOR(0, 1)) # 1
print(XOR(1, 0)) # 1
print(XOR(1, 1)) # 0
异或门是一种多层结构的神经网络。这里,将最左边的一列称为第 0 层,中间的一列称为第一层,最右边的一列称为第 2 层。
实际上,与门、或门是单层感知机,而异或门是 2 层感知机。叠加了多层的感知机也称为多层感知机(multi-layered perceptron)
在这种多层感知机中,第一层输出变为第二层输入,数据在之间不断传送。通过叠加层,感知机能进行更加灵活的表示。
多层感知机可以实现比之前见到的电路更复杂的电路。比如加法运算的加法器、二进制转十进制的编码器、满足某些条件就输出 1
的电路(用于等价检验的电路)……甚至可以表示计算机
计算机是处理信息的机器。输入信息,会按照某个既定规则进行计算,然后输出,这和感知机是一样的
只需要通过与非门的组合,就能再现计算机
多少层(层级多深)的感知机可以表示计算机?理论上可以说 2 层感知机就可以构建计算机。有研究证明,2 层感知机(严格地说是激活函数使用了非线性的
sigmoid 函数的感知机)可以表示任意函数。但是使用 2 层感知机的构造,通过设定合适的权重来构建计算机是非常累人的事。
实际上,用与非门等低层元件构建计算机的情况下,分阶段地制作所需的零件(模块)会比较自然,即先实现与门和或门,然后实现半加器和全加器,接着实现算数逻辑单元(ALU),然后实现
CPU。使用这种叠加了多层的构造来实现是比较自然的流程。