【深度学习笔记】感知机


感知机是美国学者Frank Rosenblatt在1957年提出的,是学习神经网络和深度学习的一个重要思想。感知机是模拟神经元的工作,有多个输入信号,一个输出信号,信号只有通和不通两种(即1和0),其结构如下图。

其中x1和x2为输入信号,w1和w2为权重,y为输出信号,抽象成数学表达式就是

其中θ称为阈值,当带权输入信号到达阈值时,感知机被激活,输出1,否则输出0。感知机的各个输入信号都有自己对应的权重,权重发挥着控制各输入信号的重要性的作用,显然权重越大,信号重要性越高。

感知机的简单应用

感知机的一个简单应用是实现逻辑中的与门,与非门,或门。
由与、或、非的真值表和感知机的数学表达式可知,只要选取合适的权重和阈值,就可以实现这三个逻辑。我实现时选取的参数如下(不唯一):

与门:w1 = 1, w2 = 1, θ = 1.5
与非门:w1 = -1, w2 = -1, θ = -1.5
或门:w1 = 1, w2 = 1, θ = 0.5

代码如下:

# 简单实现

# 与
def AND(x1, x2):
    w1, w2, theat = 1, 1, 1.5
    t = x1 * w1 + x2 * w2
    
    if t <= theat:
        return 0
    else:
        return 1

# 或
def OR(x1, x2):
    w1, w2, theat = 1, 1, 0.5
    t = x1 * w1 + x2 * w2
    
    if t <= theat:
        return 0
    else:
        return 1

# 与非
def NAND(x1, x2):
    w1, w2, theat = -1, -1, -1.5
    t = x1 * w1 + x2 * w2
    
    if t <= theat:
        return 0
    else:
        return 1

# 与
print('and:')
print('x1  x2  y')
print('0   0   {}'.format(AND(0, 0)))
print('0   1   {}'.format(AND(0, 1)))
print('1   0   {}'.format(AND(1, 0)))
print('1   1   {}'.format(AND(1, 1)))
print('\n')

# 或
print('or:')
print('x1  x2  y')
print('0   0   {}'.format(OR(0, 0)))
print('0   1   {}'.format(OR(0, 1)))
print('1   0   {}'.format(OR(1, 0)))
print('1   1   {}'.format(OR(1, 1)))
print('\n')

# 与非
print('not and:')
print('x1  x2  y')
print('0   0   {}'.format(NAND(0, 0)))
print('0   1   {}'.format(NAND(0, 1)))
print('1   0   {}'.format(NAND(1, 0)))
print('1   1   {}'.format(NAND(1, 1)))
print('\n')

运行结果如下:

and:
x1  x2  y
0   0   0
0   1   0
1   0   0
1   1   1


or:
x1  x2  y
0   0   0
0   1   1
1   0   1
1   1   1


not and:
x1  x2  y
0   0   1
0   1   1
1   0   1
1   1   0

以上是感知机的简单实现,简单的实现很方便理解,但有些时候不够灵活,为了使以后构造神经网络更加灵活,将原来的θ用偏置来代替,本文偏置用字母b表示,b = -θ。
引入偏置后,感知机数学表达式如下:

偏置也并非所有情况下都要引入,一般情况下,偏置对网络的影响并不显著(除非网络特别小,拟合很差),还有些时候偏置并不会影响到网络,引入偏置反而会导致训练时显卡显存的浪费。

引入偏置后感知机的实现如下

# 引入偏置,使用numpy实现
# 偏置 b = -theta

import numpy as np

# 与
def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.7
    t = np.sum(x*w)+ b
    
    if t <= 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
    t = np.sum(x*w)+ b
    
    if t <= 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
    t = np.sum(x*w)+ b
    
    if t <= 0:
        return 0
    else:
        return 1

感知机的局限性

感知机可以表示与门,或门,与非门,但如果表示异或门,就出现问题了,权重等参数根本没有符合条件的取值。
一个感知机可以轻松地实现与门,或门,与非门,是因为这些都是简单的线性结构,而异或门是非线性的,如下图,以或门为例,绿色标注的是输出为1的地方,黄色为输出为0的地方,一条直线可以轻松分开两种结果:

而异或,只能用曲线来划分开两种结果(绿色为1,黄色为0):

但根据逻辑代数,我们可以对异或进行转化,用与门、与非门和或门来实现异或,化简结果如下:

可以先让两个输入信号通过与非门,得到结果s1,再通过或门,得到结果s2,最后让s1和s2通过与门,就实现了异或门。

异或门实现:

# 异或,依赖已实现的与门、与非门、或门
def XOR(x1, x2):
    s1 = NAND(x1, x2)
    s2 = OR(x1, x2)
    y = AND(s1, s2)
    return y

print('xor:')
print('x1  x2  y')
print('0   0   {}'.format(XOR(0, 0)))
print('0   1   {}'.format(XOR(0, 1)))
print('1   0   {}'.format(XOR(1, 0)))
print('1   1   {}'.format(XOR(1, 1)))

运行结果

xor:
x1  x2  y
0   0   0
0   1   1
1   0   1
1   1   0

异或门通过多个感知机叠加实现,这种叠加了多层的感知机,称为多层感知机。可见,单层感知机虽有局限性,但可以通过叠加来灵活地表示单层感知机不方便表示地东西,感知机地灵活性还是很高的。

理论上,用感知机可以模拟一台计算机的运行,因为感知机可以表示出与或非等逻辑门,而计算机就是基于逻辑电路与运行的。

声明:楓の街|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 【深度学习笔记】感知机


Just For Fun...