笔记二:感知机 - 图1

《DLS》第二章笔记:感知机

2.1 感知机

2.1.1 神经元

  1. 对于生物学意义上的神经元,一个神经元具有多个树突接收输入信号,一个细胞主体处理输入信号,一个轴突传递输出信号,如下图:<br />![](https://img-blog.csdnimg.cn/20210213161900518.png#crop=0&crop=0&crop=1&crop=1&id=eFRWw&originHeight=645&originWidth=1000&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br /> 将神经元抽象为一个算法模型:<br />![](https://img-blog.csdnimg.cn/20210213162107757.png#crop=0&crop=0&crop=1&crop=1&id=bXTZb&originHeight=262&originWidth=397&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br /> 我们将这个模型称为人工神经元,也称感知机。

2.1.2 感知机的组成

   一个感知机由输入权值、激活函数、输出三部分组成。

笔记二:感知机 - 图2%5C%5C%0A1%2C(b%2Bw%7B1%7Dx%7B1%7D%2Bw%7B2%7Dx%7B2%7D%2B…%2Bw%7Bn%7Dx%7Bn%7D%3E0)%5C%5C%0A%5Cend%7Bcases%7D%0A#card=math&code=y%3D%5Cbegin%7Bcases%7D%0A0%2C%28b%2Bw%7B1%7Dx%7B1%7D%2Bw%7B2%7Dx%7B2%7D%2B…%2Bw%7Bn%7Dx%7Bn%7D%5Cleq%200%29%5C%5C%0A1%2C%28b%2Bw%7B1%7Dx%7B1%7D%2Bw%7B2%7Dx%7B2%7D%2B…%2Bw%7Bn%7Dx%7Bn%7D%3E0%29%5C%5C%0A%5Cend%7Bcases%7D%0A&id=qjYZo)

   输入权值:一个感知机可以接收多个输入![](https://g.yuque.com/gr/latex?x_%7B1%7D%EF%BC%8Cx_%7B2%7D%EF%BC%8C...%EF%BC%8Cx_%7Bn%7D(x_%7Bi%7D%5Cin%5Cmathbb%7BR%7D)#card=math&code=x_%7B1%7D%EF%BC%8Cx_%7B2%7D%EF%BC%8C...%EF%BC%8Cx_%7Bn%7D%28x_%7Bi%7D%5Cin%5Cmathbb%7BR%7D%29&id=Jf4Fp),每个输入上有一个权重值![](https://g.yuque.com/gr/latex?w_%7Bi%7D%5Cin%5Cmathbb%7BR%7D#card=math&code=w_%7Bi%7D%5Cin%5Cmathbb%7BR%7D&id=t031B),此外还有一个偏置项![](https://g.yuque.com/gr/latex?b%5Cin%5Cmathbb%7BR%7D#card=math&code=b%5Cin%5Cmathbb%7BR%7D&id=JwfDO),即![](https://g.yuque.com/gr/latex?w_%7B0%7D#card=math&code=w_%7B0%7D&id=wI3qi)。输入信号被送往神经元时会被分别乘以固定的权重。<br />       (权重是控制输入信号重要性的参数,偏置是调整神经元被激活的容易程度的参数)

   激活函数:![](https://g.yuque.com/gr/latex?f(x)#card=math&code=f%28x%29&id=E9JAX) 决定如何来计算输入信号的总和。只有当总和超过某个界限时,才会输出1,即“神经元被激活”,这个界限值被称为阈值。

   输出:输出 ![](https://g.yuque.com/gr/latex?y%3Df(x)#card=math&code=y%3Df%28x%29&id=dnOwc),输出值只有两个,即0或1。总和超过阈值时输出1,总和未超过阈值时输出0。

2.1.3 神经元和感知机的对应关系

神经元 感知机
树突接收的信号 输入权值
细胞主体 激活函数
轴突输出的信号 输出

2.2 逻辑门

2.2.1 与门

   与门对应逻辑运算“与”,真值表如下:<br />![](https://img-blog.csdnimg.cn/20210213164748349.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUwMjk5MTUw,size_16,color_FFFFFF,t_70#pic_center#crop=0&crop=0&crop=1&crop=1&id=K2TDG&originHeight=371&originWidth=763&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       用感知机实现与门,实际上就是寻找一组能满足与门真值表的![](https://g.yuque.com/gr/latex?w_%7B1%7D#card=math&code=w_%7B1%7D&id=miixY)、![](https://g.yuque.com/gr/latex?w_%7B2%7D#card=math&code=w_%7B2%7D&id=W1mBh)、![](https://g.yuque.com/gr/latex?%5Ctheta#card=math&code=%5Ctheta&id=EYSbA)的值。这样的值有无数多个,选择不同的值就是选择不同的权重。

   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

x1, x2 = map(int, input().split())
print(AND(x1, x2))
   C++实现:
#include<iostream>
using namespace std;
bool AND(bool x1,bool x2);

int main() 
{
    bool x1,x2;
    cin>>x1>>x2;
    cout<<AND(x1,x2);    
    return 0;
} 

bool AND(bool x1,bool x2)
{
    double w1 = 0.5,w2 = 0.5,b = -0.7;
    double tmp = x1*w1+x2*w2+b;
    return tmp <= 0 ? 0 : 1;
}

2.2.2 与非门

   与非门对应逻辑运算“与”和“非”,真值表如下:<br />![](https://img-blog.csdnimg.cn/20210213170123431.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUwMjk5MTUw,size_16,color_FFFFFF,t_70#pic_center#crop=0&crop=0&crop=1&crop=1&id=AMlfk&originHeight=370&originWidth=741&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       与非门的输出实际上就是颠倒了与门的输出,只要把实现与门的参数值![](https://g.yuque.com/gr/latex?w_%7B1%7D#card=math&code=w_%7B1%7D&id=nMYUm)、![](https://g.yuque.com/gr/latex?w_%7B2%7D#card=math&code=w_%7B2%7D&id=UVoqt)、![](https://g.yuque.com/gr/latex?%5Ctheta#card=math&code=%5Ctheta&id=fhGUR)取反就可以实现与非门。

   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

x1, x2 = map(int, input().split())
print(AND(x1, x2))
   C++实现:
#include<iostream>
using namespace std;
bool NAND(bool x1,bool x2);

int main() 
{
    bool x1,x2;
    cin>>x1>>x2;
    cout<<NAND(x1,x2);    
    return 0;
} 

bool NAND(bool x1,bool x2)
{
    double w1 = -0.5,w2 = -0.5,b = 0.7;
    double tmp = x1*w1+x2*w2+b;
    return tmp <= 0 ? 0 : 1;
}

2.2.3 或门

   或门对应逻辑运算“或”,真值表如下:<br />![](https://img-blog.csdnimg.cn/20210213170611517.png#crop=0&crop=0&crop=1&crop=1&id=gkyYG&originHeight=356&originWidth=763&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       用感知机实现或门,实际上就是寻找一组能满足或门真值表的![](https://g.yuque.com/gr/latex?w_%7B1%7D#card=math&code=w_%7B1%7D&id=ms33w)、![](https://g.yuque.com/gr/latex?w_%7B2%7D#card=math&code=w_%7B2%7D&id=JlsSY)、![](https://g.yuque.com/gr/latex?%5Ctheta#card=math&code=%5Ctheta&id=uIEno)的值。这样的值有无数多个,选择不同的值就是选择不同的权重。<br />       Python实现:
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

x1, x2 = map(int, input().split())
print(AND(x1, x2))
   C++实现:
#include<iostream>
using namespace std;
bool OR(bool x1,bool x2);

int main() 
{
    bool x1,x2;
    cin>>x1>>x2;
    cout<<OR(x1,x2);

    return 0;
} 

bool OR(bool x1,bool x2)
{
    double w1 = 0.5,w2 = 0.5,b = -0.2;
    double tmp = x1*w1+x2*w2+b;
    return tmp <= 0 ? 0 : 1;
}
   与门、与非门和或门是具有相同结构的感知机,区别只在于权重参数的值。

2.2.4 异或门

   异或门对应逻辑运算“异或”,真值表如下:<br />![](https://img-blog.csdnimg.cn/20210213171513210.png#crop=0&crop=0&crop=1&crop=1&id=sLNRe&originHeight=452&originWidth=938&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       异或(XOR)的运算是特性是“相同为0,不同为1”,即仅当![](https://g.yuque.com/gr/latex?x_%7B1%7D#card=math&code=x_%7B1%7D&id=IjqRO)或![](https://g.yuque.com/gr/latex?x_%7B2%7D#card=math&code=x_%7B2%7D&id=oPoxY)中的一方为1时,才会输出1(“异或”是拒绝其他的意思)。简单实践就可发现,我们无法用单层感知机实现异或门。

2.3 多层感知机

2.3.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
   表示$$y=\begin{cases}<br />0,(-0.5+x_{1}+w_{2}\leq 0)\<br />1,(-0.5+x_{1}+w_{2}>0)\<br />\end{cases}       即,坐标系被直线−0.5 + x1 + x2 = 0分割开的两个空间。其中一个空间输出1,另一个空间输出0。<br />![](https://img-blog.csdnimg.cn/20210213175326941.png#crop=0&crop=0&crop=1&crop=1&id=EQMda&originHeight=504&originWidth=722&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)

2.3.2异或门可视化

   对于异或门<br />![](https://img-blog.csdnimg.cn/20210213175531992.png#crop=0&crop=0&crop=1&crop=1&id=QFfiM&originHeight=515&originWidth=699&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       显然,无法使用一条直线把三角和圆圈分割开来,考虑:<br />![](https://img-blog.csdnimg.cn/20210213180209247.jpg#crop=0&crop=0&crop=1&crop=1&id=YSBl7&originHeight=514&originWidth=699&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       即通过与门、或门、与非门的组合来实现异或门。<br />![](https://img-blog.csdnimg.cn/2021021318065387.png#crop=0&crop=0&crop=1&crop=1&id=hQtQ6&originHeight=209&originWidth=721&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       寻找实现异或门的组合:

笔记二:感知机 - 图3

2.3.3 异或门的实现

   列出与门的真值表:
笔记二:感知机 - 图4 笔记二:感知机 - 图5 笔记二:感知机 - 图6 (AND)
0 0 0
1 0 0
0 1 0
1 1 1
   列出与非门的真值表:
笔记二:感知机 - 图7 笔记二:感知机 - 图8 笔记二:感知机 - 图9 (NAND)
0 0 1
1 0 0
0 1 0
1 1 0
   列出或门的真值表:
笔记二:感知机 - 图10 笔记二:感知机 - 图11 笔记二:感知机 - 图12 (OR)
0 0 0
1 0 1
0 1 1
1 1 1
   则可发现:
笔记二:感知机 - 图13(NAND) 笔记二:感知机 - 图14(OR) 笔记二:感知机 - 图15 (AND)
1 0 0
1 1 1
1 1 1
0 1 0
   因此可作如下组合:<br />![](https://img-blog.csdnimg.cn/20210213180612704.png#crop=0&crop=0&crop=1&crop=1&id=GRQWx&originHeight=224&originWidth=738&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       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

x1, x2 = map(int, input().split())
print(XOR(x1, x2))
   C++实现:
#include<iostream>
using namespace std;
bool AND(bool x1,bool x2);
bool NAND(bool x1,bool x2);
bool OR(bool x1,bool x2);
bool XOR(bool x1,bool x2);

int main() 
{
    bool x1,x2;
    cin>>x1>>x2;
    cout<<XOR(x1,x2);

    return 0;
} 

bool AND(bool x1,bool x2)
{
    double w1 = 0.5,w2 = 0.5,b = -0.7;
    double tmp = x1*w1+x2*w2+b;
    return tmp <= 0 ? 0 : 1;
}

bool NAND(bool x1,bool x2)
{
    double w1 = -0.5,w2 = -0.5,b = 0.7;
    double tmp = x1*w1+x2*w2+b;
    return tmp <= 0 ? 0 : 1;
}

bool OR(bool x1,bool x2)
{
    double w1 = 0.5,w2 = 0.5,b = -0.2;
    double tmp = x1*w1+x2*w2+b;
    return tmp <= 0 ? 0 : 1;
}

bool XOR(bool x1,bool x2)
{
    double s1 = NAND(x1, x2);
    double s2 = OR(x1, x2);
    double y = AND(s1,s2);
    return y;
}

2.3.4 多层感知机

   叠加了超过两层的感知机被称为多层感知机,异或门就是通过双层感知机实现的。多层感知机可以实现单层感知机实现不了的结构,通过叠加层(加深层),感知机能进行更加灵活的表示。<br />![](https://img-blog.csdnimg.cn/2021021318251266.png#crop=0&crop=0&crop=1&crop=1&id=HH9zy&originHeight=360&originWidth=735&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)<br />       上图所示的2层感知机中,先在第0层和第1层的神经元之间进行信号的传送和接收,然后在第1层和第2层之间进行信号的传送和接收,具体如下所示:

1.第0层的两个神经元接收输入信号,并将信号发送至第1层的神经元。
2.第1层的神经元将信号发送至第2层的神经元,第2层的神经元输出y。

2.4 感知机和计算机

   两层感知机(使用sigmoid函数为激活函数)就可以表示任意函数。<br />       《计算机系统要素:从零开始构建现代计算机》:以深入理解计算机为主题,论述了仅通过 NAND构建可运行俄罗斯方块的计算机的过程。