代码改变世界

机器学习 感知机实现与、或、与非门和异或门

2022-04-05 13:59  jym蒟蒻  阅读(1506)  评论(0编辑  收藏  举报

机器学习-感知机【perceptron】

    • what is 感知机
    • 单层感知机运用实例
    • 多层感知机

 

what is 感知机

感知机接收多个输入信号,输出一个信号。

接收两个信号的感知机,如下图:

在这里插入图片描述

x1与x2是输入信号;y是输出信号;

w1与w2是权重。圆圈O代表”神经元”或者”节点”。

神经元被激活:当x1w1+x2w2超过某个界限值时,y才会输出1。

阈值:这里将界限值称为阈值,用θ符号表示。

权重越大,对应该权重的信号的重要性就越高。

由此可以得到感知机的一种数学表示方法:

在这里插入图片描述

感知机的另一种数学表示方法:

在这里插入图片描述

上式的b称为偏置。感知机计算输入信号和权重的乘积,然后加上偏置,这个值大于0则输出1,否则输出0。

单层感知机运用实例

使用感知机可以实现与、或、与非门。

首先与门,两个都是1,才输出1:

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

if __name__ == '__main__':
    for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = AND(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))

输出结果:

(0, 0) -> 0
(1, 0) -> 0
(0, 1) -> 0
(1, 1) -> 1

然后是或门,两个输入只要有一个是1,就输出1.

import numpy as np


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

if __name__ == '__main__':
    for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = OR(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))

输出结果:

(0, 0) -> 0
(1, 0) -> 1
(0, 1) -> 1
(1, 1) -> 1

最后是与非门,就是把与的结果取反:

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

if __name__ == '__main__':
    for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = NAND(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))

输出结果:

(0, 0) -> 1
(1, 0) -> 1
(0, 1) -> 1
(1, 1) -> 0

由上面的例子我们可以看出,与、或、与非门是具有相同构造的感知机,区别只在于权重w和偏置b的值不同。

多层感知机

首先来看一下异或逻辑的真值表:

输入x1输入x2输出Y
0 0 0
0 1 1
1 0 1
1 1 0

将他们标在平面坐标系中可发现,任何直线也不能把两类样本分开。

在这里插入图片描述

单层感知机的数学表示方法如下:

在这里插入图片描述

它的几何意义:w2x1+w2x2+b=0是一条直线,这条直线分割开两个空间,其中一个空间输出1,另一个空间输出0 。

也就是说通过单层感知机,无法把异或逻辑的两类样本分开。

单层感知机只能表示由一条直线分割的空间;非线性空间:曲线分割成的空间。

之前已经用单层感知机实现了与门、与非门、或门,那么实现异或门的话,可以把前面那几个门叠加起来。

x1,x2表示输入,s1表示与非门的输出,s2表示或门的输出,y表示与门的输出

在这里插入图片描述

通过观察x1、x2、y的值,发现,符合异或门的输出。

实现异或门的代码:

from and_gate import AND
from or_gate import OR
from nand_gate import NAND

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

if __name__ == '__main__':
    for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = XOR(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))

输出结果:

(0, 0) -> 0
(1, 0) -> 1
(0, 1) -> 1
(1, 1) -> 0

由上述可知,通过叠加层,感知机能进行更加灵活的表示。如果说通过组合与非门可实现计算机,那么通过组合感知机也可以表示计算机。

已有研究证明,2层感知机可以表示任意函数,但是不容易设计合适的权重和构造。通常用小模块叠加的方法来构造,就比如上面的先实现与门、或门、与非门,再叠加起来实现异或门。