文章目录
感知机
感知机的概念
感知机(Perceptron)是二分类模型,接收多个信号,输出一个信号。感知机的信号只有0、1两种取值。下图是一个接收两个输入信号的感知机的例子:

x 1 , x 2 是输入信号, y 是输出信号, w 1 , w 2 是权重,○称为神经元或节点 x_{1},x_{2}是输入信号,y是输出信号,w_{1},w_{2}是权重,○称为神经元或节点 x1,x2是输入信号,y是输出信号,w1,w2是权重,○称为神经元或节点。输入信号被送往神经元时,会分别乘以固定的权重。神经元会计算传送过来的信号的总和,只有当这个总和超过某个界限值时才会输出1,也称之为神经元被激活。这里将界限值称之为阈值θ
。
y = { 0 ( w 1 x 1 + w 2 x 2 ≤ θ ) 1 ( w 1 x 1 + w 2 x 2 > θ ) y=\left\{\begin{matrix}0\ \ \ \ \left(w_{1}x_{1}+w_{2}x_{2}\leq \theta \right) \\ 1\ \ \ \ \left(w_{1}x_{1}+w_{2}x_{2}\gt \theta \right)\end{matrix}\right. y={0 (w1x1+w2x2≤θ)1 (w1x1+w2x2>θ)
感知机的多个输入信号都有各自的权重,这些权重发挥着控制各个信号的重要性的作用,权重越大,对应信号的重要性越高。
简单逻辑电路
与门
尝试使用感知机解决简单的问题,如实现逻辑电路中的与门(AND gate)。与门是具有两个输入和一个输出的门电路,仅在两个输入均为1时输出1,其他时候输出0。这种输入信号和输出信号对应表称为真值表。

使用感知机表示与门需要确定能满足上述真值表的 w 1 , w 2 , θ 的值 w_{1},w_{2},\theta 的值 w1,w2,θ的值,满足条件的参数有无数个,如 ( w 1 , w 2 , θ ) = ( 0.5 , 0.5 , 0.7 ) 或 ( 1.0 , 1.0 , 1.0 ) 。 \left(w_{1},w_{2},\theta \right)=\left(0.5,\ \ 0.5,\ \ 0.7\right)或\left(1.0,\ \ 1.0,\ \ 1.0\right)。 (w1,w2,θ)=(0.5, 0.5, 0.7)或(1.0, 1.0, 1.0)。
与非门
再来考虑下与非门(NAND gate),与非门颠倒了与门的输出, 仅当 x 1 , x 2 同时为 1 时输出 0 ,其他时候输出 1 仅当x_{1},x_{2}同时为1时输出0,其他时候输出1 仅当x1,x2同时为1时输出0,其他时候输出1。

要表示与非门,满足条件的参数也有无数个,如 ( w 1 , w 2 , θ ) = ( − 0.5 , − 0.5 , − 0.7 ) \left(w_{1},w_{2},\theta \right)=\left(-0.5,\ \ -0.5,\ \ -0.7\right) (w1,w2,θ)=(−0.5, −0.5, −0.7)。实际上,只要把实现与门的参数值的符号取反即可。
或门
再来看一下或门(OR gate)。或门只要有一个输入信号为1,输出就为1。

( w 1 , w 2 , θ ) = ( 0.5 , 0.5 , 0 ) \left(w_{1},w_{2},\theta \right)=\left(0.5,\ \ 0.5,\ \ 0\right) (w1,w2,θ)=(0.5, 0.5, 0)。
感知机的实现
简单实现
先来实现与门,定义一函数AND接受 x 1 和 x 2 ,在函数内部初始化参数 w 1 , w 2 , θ x_{1}和x_{2},在函数内部初始化参数w_{1},w_{2},\theta x1和x2,在函数内部初始化参数w1,w2,θ 。当输入的加权总和超过阈值时返回1,否则返回0。
python
def AND(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.7
res = x1 * w1 + x2 * w2
if res <= theta:
return 0
elif res > theta:
return 1
print(AND(0, 0)) # 0
print(AND(1, 0)) # 0
print(AND(0, 1)) # 0
print(AND(1, 1)) # 1
可以以同样的方式实现与非门和或门,不过在此之前先做一些修改.
导入权重和偏置
考虑到以后的事情,我们将其修改为另外一种实现形式。将θ换为-b,表示感知机行为的式子变为如下形式:
y = { 0 ( b + w 1 x 1 + w 2 x 2 ≤ 0 ) 1 ( b + w 1 x 1 + w 2 x 2 > 0 ) y=\left\{\begin{matrix}0\ \ \ \ \left(b+w_{1}x_{1}+w_{2}x_{2}\leq 0\right) \\ 1\ \ \ \ \left(b+w_{1}x_{1}+w_{2}x_{2}\gt 0\right)\end{matrix}\right. y={0 (b+w1x1+w2x2≤0)1 (b+w1x1+w2x2>0)
b 为偏置, w 1 , w 2 为权重。下面我们使用 N u m p y 按上述形式分别实现与门、与非门和或门。 b为偏置,w_{1},w_{2}为权重。下面我们使用Numpy按上述形式分别实现与门、与非门和或门。 b为偏置,w1,w2为权重。下面我们使用Numpy按上述形式分别实现与门、与非门和或门。
与门:
python
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
print(AND(0, 0)) # 0
print(AND(1, 0)) # 0
print(AND(0, 1)) # 0
print(AND(1, 1)) # 1
偏置b与权重w_{1},w_{2}的作用是不同的,具体地说w_{1},w_{2}是控制输入信号的重要性的参数,而偏置是调整神经元被激活的容易程度的参数。
接下来实现与非门和或门:
python
import numpy as np
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
print(NAND(0, 0)) # 1
print(NAND(1, 0)) # 1
print(NAND(0, 1)) # 1
print(NAND(1, 1)) # 0
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(OR(0, 0)) # 0
print(OR(1, 0)) # 1
print(OR(0, 1)) # 1
print(OR(1, 1)) # 1
与门、与非门、或门是具有相同构造的感知机,区别仅在于权重参数的值。因此在与非门和或门的实现中,仅设置权重和偏置的值这一点和与门的实现不同。
感知机的局限
现在来考虑一下异或门(XOR gate)。 异或门仅当 x 1 或 x 2 中的一方为 1 时才会输出 1 。 异或门仅当x_{1}或x_{2}中的一方为1时才会输出1。 异或门仅当x1或x2中的一方为1时才会输出1。

之前的感知机是无法实现这个异或门的,具体原因让我们来分析一下。
感知机表示或门的式子如下:
y = { 0 ( − 0.5 + x 1 + x 2 ≤ 0 ) 1 ( − 0.5 + x 1 + x 2 > 0 ) y=\left\{\begin{matrix}0\ \ \ \ \left(-0.5+x_{1}+x_{2}\leq 0\right) \\ 1\ \ \ \ \left(-0.5+x_{1}+x_{2}\gt 0\right)\end{matrix}\right. y={0 (−0.5+x1+x2≤0)1 (−0.5+x1+x2>0)
上式表示感知机会生成由直线 − 0.5 + x 1 + x 2 = 0 -0.5+x_{1}+x_{2}=0 −0.5+x1+x2=0划分的两个空间,其中一个空间输出1,另一个空间输出0,如图:
如果要实现异或门,是无法使用一条直线将0和1分开的:

但如果将直线这个限制条件去掉就可以了:

感知机的局限性就在于它只能表示由一条直线划分的空间,而上图中的曲线无法用感知机表示。由曲线划分的空间称为非线性空间,由直线划分的空间称为线性空间。
多层感知机
我们先来考虑一下如何使用与门、与非门和或门来组合出异或门。
与门、与非门、或门用下图的符号表示:

将其组合构成异或门:


使用之前实现的与门、与非门和或门代码来实现异或门:
python
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])
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
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(1, 0)) # 1
print(XOR(0, 1)) # 1
print(XOR(1, 1)) # 0
试着使用感知机的表示方法来表示这个异或门:
如图所示,这是一种多层感知机结构。
第0层的两个神经元接收输入信号,并将信号发送给第1层的神经元。第1层的神经元将信号发送给第2层的神经元。第2层的神经元输出结果。
通过叠加层,感知机能进行更加灵活的表示。
感知机是一种非常简单的算法,也是后续学习神经网络的基础。

