目录
第2章 感知机
2.1 感知机是什么
2.2 简单逻辑电路
2.2.1 与门
2.2.2 与非门和或门
2.3 感知机的实现
2.3.1 简单的实现
2.3.2 导入权重和偏置
2.3.3 使用权重和偏置的实现
2.4 感知机的局限性
2.4.1 异或门
2.4.2 线性和非线性
2.5 多层感知机
2.5.1 已有门电路的组合
2.5.2 异或门的实现
2.6 从与非门到计算机
2.7 小结
感知机是由美国学者Frank Rosenblatt在1957年提出来的。
感知机接收多个输入信号,输出一个信号。
上图是一个接收两个输入信号的感知机的例子。是输入信号,y是输出信号,是权重。图中的称为“神经元”或者“节点”。输入信号被送往神经元时,会被分别乘以固定的权重。神经元会计算传送过来的信号的总和,只有当这个总和超过了某个界限值时,才会输出1。这也称为“神经元被激活”。这里将这个界限值称为阈值。
把上述内容用数学式来表示,就是下式:
感知机的多个输入信号都有各自固有的权重,这些权重发挥着控制各个信号的重要性的作用。也就是说,权重越大,对应该权重的信号的重要性就越高。
这里决定感知机参数的并不是计算机,而是我们人。我们看着真值表这种“训练数据”,人工考虑了参数的值,而机器学习的课题就是将这个决定参数值的工作交由计算机自动进行。学习是确定合适的参数的过程,而人要做的是思考感知机的构造(模型),并把训练数据交给计算机。
相同构造的感知机,只需通过适当地调整参数的值,就可以像“变色龙演员”表演不同的角色一样,变身为与门、与非门、或门。
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
print(AND(0, 0))
print(AND(1, 0))
print(AND(0, 1))
print(AND(1, 1))
0
0
0
1
这样我们就实现了与门。按照同样的步骤,也可以实现与非门和或门。
此处,b称为偏置,w1和w2称为权重。感知机会计算输入信号和权重的乘积,然后加上偏置,如果这个值大于0则输出1,否则输出0.
import numpy as np
x = np.array([0, 1])
w = np.array([0.5, 0.5])
b = -0.7
c = np.sum(x*w) + b
print(c)
-0.19999999999999996
这里把命名为偏置b,但是请注意,偏置和权重的作用是不一样的。具体地说,是控制输入信号的重要性的参数,而偏置是调整神经元被激活的容易程度(输出信号为1的程度)的参数。
import numpy as np
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
def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5]) # 仅权重和偏置与AND不同
b = -0.2
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
异或门也被称为逻辑异或电路。仅当x1或x2中的一方为1时,才会输出1(“异或”是拒绝其他的意思)。
实际上,用前面介绍的感知机是无法实现这个异或门的,为什么用感知机可以实现与门、或门,却无法实现异或门呢?
想要用一条直线将上图中的和分开,无论如何都做不到。事实上,用一条直线是无法将二者分开的。
感知机的局限性就在于它只能表示由一条直线分割的空间,弯曲的曲线无法用感知机表示。另外,由曲线分割而成的空间称为非线性空间,由直线分割而成的空间称为线性空间。
现在思考一下,要实现异或门的话,需要如何配置与门、与非门和或门呢?
上一节讲到的感知机的局限性,严格地讲,应该是“单层感知机无法表示异或门”或者“单层感知机无法分离非线性空间”。接下来,我们将看到通过组合感知机(叠加层)就可以实现异或门。
x1和x2表示输入信号,y表示输出信号。x1和x2是与非门和或门的输入,而与非门和或门的输出则是与门的输入。
import numpy as np
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
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
def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5]) # 仅权重和偏置与AND不同
b = -0.2
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
print(XOR(0, 0))
print(XOR(1, 0))
print(XOR(0, 1))
print(XOR(1, 1))
0
1
1
0
这样,异或门的实现就完成了。我们试着用感知机的表示方法来表示这个异或门。
异或门是一种多层结构的神经网络,这里,将最左边的一列称为第0层,中间的一列称为第1层,最右边的一列称为第2层。
与门、或门是单层感知机,而异或门是2层感知机。叠加了多层的感知机也称为多层感知机。
上图中的感知机总共由3层构成,但是因为拥有权重的层实质上只有2层(第0层和第1层之间,第1层和第2层之间),所以称为“2层感知机”。
在异或门的感知机中,通过这样的结构(2层结构),感知机得以实现异或门。这可以解释为“单层感知机无法表示的东西,通过增加一层就可以解决”。也就是说,通过叠加层(加深层),感知机能进行更加灵活的表示。
人们一般会认为计算机内部进行的处理非常复杂,而令人惊讶的是,实际上只需要通过与非门的组合,就能再现计算机进行的处理。如果通过组合与非门可以实现计算机的话,那么通过组合感知机也可以表示计算机(感知机的组合可以通过叠加了多层的单层感知机来表示)。
在用与非门等低层的元件构建计算机的情况下,分阶段地制作所需的零件(模块)会比较自然,即先实现与门和或门,然后实现半加器和全加器,接着实现算数逻辑单元(ALU),然后实现CPU。因此,通过感知机表示计算机时,使用叠加了多层的构造来实现是比较自然的流程。
感知机通过叠加层能够进行非线性的表示,理论上还可以表示计算机进行的处理。
1.感知机是具有输入和输出的算法。给定一个输入后,将输出一个既定的值。
2.感知机将权重和偏置设定为参数。
3.使用感知机可以表示与门和或门等逻辑电路。
4.异或门无法通过单层感知机来表示。
5.使用2层感知机可以表示异或门。
6.单层感知机只能表示线性空间,而多层感知机可以表示非线性空间。
7.多层感知机(在理论上)可以表示计算机。