深度学习从零开始(2)——由感知机到神经网络

1、 感知机

在大部分的神经网络或者深度学习的教材中,基本上都会在开头介绍感知机。为什么呢?因为感知机是神经网络乃至深度学习算法的源头,后两者虽然更为复杂,但是本质上不过是感知机稍作改进,堆叠而成。因此学习感知机也对学习后续的神经网络和深度学习,以及认识到历史发展过程中一系列改进的重要性有所帮助。其中最主要的就是激活函数还有反向传播,这是后话,我们会在后面的章节中详细讲解。首先我们来看看感知机是什么。

1.1 感知机是什么?

感知机这个名字听起来挺高端,其实是一个非常简单的算法。一句话概括:感知机是一个接收多个输入,输出单个输出的算法。最好理解的例子是,你把感知机想象成很多人推一辆汽车的情景。每个人的推力就是一个输入,而这个车动(1)或者不动(0)就是输出。当众人的合力大于汽车的摩擦力的时候,车子就动了。在感知机中同样如此,当输入的和大于或等于某个设定值θ时,感知机输出1(激活),否则就输出0(抑制)。而这个数θ就称为感知机的阈值,阈值代表感知机被激活的容易程度,阈值越小,感知机越容易激活,反之,则越难激活。

                                             

下图是一个简单的感知机的例子,感知机有两个输入,分别是x1 和x2,输出为y。值得注意的是,感知机不是简单地将x1和 x2 直接相加,而是分别赋予信号权重 w1 和 w2,这两个权重代表对应两个输入信号的重要性,w越大,说明对应的信号越重要,对输出的结果影响也越大。 因此,两个输入信号先分别乘上权重,再相加,最后输入到圆形O(也称为神经元或者神经节点)中,当两者的加权和大于或等于设定的θ时,神经元输出1,否则输出0。

                                          

以上就是感知机的所有原理,可以用数学式表达如下:   

                                                    

可以看出,感知机的数学表达方式非常简单,而这个简单的表达式居然是深度学习的基础,不可思议吧。其实深度学习相对这个感知机的改进并不复杂,我们后面会一步一步从这个式子发展出能够用于图像识别的卷积神经网络。首先,我们先用感知机来解决一些简单的问题。

1.2 感知机和逻辑门

其实从感知机的输出来看,我们很容易联想到 bool 电路,其中最为基本的就是三大逻辑门:与门、或门、非门。其后还有由它门组成的与非门,与或门和或非门等等,在这个小节中,我们将会讲解与门、或门和与非门的实现。之所以选择这三个逻辑门,是因为这三个门的组合可以形成异或门,而异或问题是感知机发展历史上非常关键的问题,它直接催生了神经网络。首先,我们来看三个逻辑门的真值表,如下所示:

                                  

我们先来尝试实现与门。其实很简单,我们只要设定 [ w1, w2, θ ] 的值即可,比如我们设定 w1 = 1, w2 = 1, θ = 1.5,就可以实现与门:

def and_gate(x1,x2):
    w1=w2=1
    theta=1.5
    y=w1*x1+w2*x2
    if y>theta:
        return 1
    else:
        return 0

and_gate(0,0) # 输出 0
and_gate(0,1) # 输出 0
and_gate(1,0) # 输出 0
and_gate(1,1) # 输出 1
    

显然,测试的结果符合与门的要求。实际上 [ w1, w2, θ ] 有无数中设法,读者可以自行设置一个。

好了,在接下去要实现或门之前,我们先把感知机写成另外一种写法,方便用矩阵的运算来表示:

在新的表达式中,引入了一个新的概念,叫偏置,通常用斜体的符号b 来表示,这里的偏置等于 ﹣θ,它同样代表感知机被激活的容易程度。之所以改成这种写法,是为了在一层有多个感知机(神经元)的时候用矩阵表示更为方便,现在不用计较这些问题,后面会详细讲解。OK,采用这种表达式之后,我们来对上面与门的实现稍作改动,这里面把 w1, w2 合并成向量 [w1, w2 ],把输入 x1x2 也合并成向量 [x1, x2 ],方便直接用矩阵运算,这里要用到 numpy 库:

import numpy as np

def and_gate(x1,x2):
    w=np.array([1,1]) # 将 w1 和 w2 结合成向量的形式
    x=np.array([x1,x2]) # 将输入的变量也组合成向量的形式
    b=-1.5
    y=np.sum(w*x)+ b # * 代表元素间相乘,比如 [1,2]*[3,4]=[3,8]
    if y > 0:
        return 1
    else:
        return 0

and_gate(0,0) # 输出 0
and_gate(0,1) # 输出 0
and_gate(1,0) # 输出 0
and_gate(1,1) # 输出 1

同样的道理,我们设置 [ w1, w2, b ]=[1,1,﹣0.5] 可以实现或门:

import numpy as np

def or_gate(x1,x2):
    w=np.array([1,1]) # 将 w1 和 w2 结合成向量的形式
    x=np.array([x1,x2]) # 将输入的变量也组合成向量的形式
    b=-0.5
    y=np.sum(w*x)+ b # * 代表元素间相乘,比如 [1,2]*[3,4]=[3,8]
    if y > 0:
        return 1
    else:
        return 0

or_gate(0,0) # 输出 0
or_gate(0,1) # 输出 1
or_gate(1,0) # 输出 1
or_gate(1,1) # 输出 1

我们设置  [ w1, w2, b ]=[﹣1,﹣1,﹣1.5] 可以实现与非门:

import numpy as np

def nand_gate(x1,x2):
    w=np.array([-1,-1]) # 将 w1 和 w2 结合成向量的形式
    x=np.array([x1,x2]) # 将输入的变量也组合成向量的形式
    b = 1.5
    y=np.sum(w*x)+ b # * 代表元素间相乘,比如 [1,2]*[3,4]=[3,8]
    if y > 0:
        return 1
    else:
        return 0

or_gate(0,0) # 输出 1
or_gate(0,1) # 输出 1
or_gate(1,0) # 输出 1
or_gate(1,1) # 输出 0

1.3 单个感知机的局限性—异或问题

在感知机发展的历史上,有“人工智能之父” 之称的马文·明斯基曾经提出“感知机无法解决异或问题”,一语道出了单个感知机的局限性,直接导致了感知机研究的低潮。我们先来看看什么是异或问题,以异或门为例,其真值表如下所示,它的输出特性可以用一句话来总结:若两个输入信号相同,则输出为零;若两个输入信号相异,则输出为1。

                                                                                

那么为什么单层感知机无法解决异或问题呢,我们先来看看与门,或门还有与非门的实现的原理,我们把它们的真值表上的四种输入画到坐标图上,它们的参数组 [ w1, w2, b ] 对应的 y=w1*x1+w2*x2+b 画成直线(与门 [1, 1, -1.5],或门 [1, 1, -0.5 ],与非门 [-1, -1, 1.5]),如下图如所示:

                                  

从图中可以看出,感知机的本质其实是分类。并且用于划分两个类别的为直线,也就是线性分类。我们再来看看异或问题的图。我们可以发现,异或门的输出无法用一条直线来分类,而只能用一条曲线来分类。像这种只能用曲线划分的问题,叫做非线性分类。对于非线性分类问题,单层感知机无能为力。

                                                        

那么异或问题如何解决呢,其实在上面的介绍中就已经作了提示,读者可以先行思考一番再往下看。

1.4 异或问题的解决——多层感知机

异或问题解决的答案就是:多层感知机!而这种增加层数来解决复杂问题的思想,也是催生深度学习的因素之一。在1.2 感知机与逻辑门 一节中,我们讲解了与门、或门和或非门的实现。如何如何实现异或门呢?答案就藏在前三个逻辑门的真值表中:

                  

发现了什么规律吗?或门和非门的输出相与,刚好就是异或门的输出。用逻辑门组合图画出来如下所示:

                                                           

我们将这个图转换成感知机的形式,如下图所示。是不是觉得眼熟?不错,这就是神经网络的雏形了。只不过在讲真正的神经网络之前,还需要一些改进。我们先回过头来看这个多层感知机。这是一个两层感知机,通常,我们把输入层称为第0层。

                                                            

有了这个两层感知机的连接方式,我们可以很轻易地写出异或门的实现程序。

def xor_gate(x1,x2):
    or_result = or_gate(x1,x2)
    nand_result = nand_gate(x1,x2)
    # 把或门和与非门的输出作为输入,输入到与门
    and_result = and_gate(or_result,nand_result)
    return and_result

print(xor_gate(1,1)) # 输出 0
print(xor_gate(0,0)) # 输出 0
print(xor_gate(1,0)) # 输出 1
print(xor_gate(0,1)) # 输出 1

1.5 逻辑门和计算机

也许看到这你会有疑问,逻辑门这么简单,用感知机能实现也没什么了不起嘛。逻辑门简单,这句话不错。但是我如果告诉你,用这些逻辑门可以做一部计算机,你相信吗?事实上,就像异或门可以通过组合多个逻辑门实现一样。通过组合这些逻辑门,我们可以实现各种各样复杂的逻辑器件,从最基本的触发器、振荡器到复杂的加法器、乘法器和寄存器等等。事实上,现代计算机就是建立在bool逻辑基础之上的,通过这种简单的二值电路居然可以建立起复杂的计算机,真的是不可思议!更为神奇的是,这个建立的过程并不复杂,有兴趣的朋友可以去看看《编码》这本经典的计算机科普图书,这本书就是从零开始教你怎么做一部现代意义上的计算机,整部书行文简易,风趣,非常易读,看完相信你对计算机有更大的兴趣。

为什么要讲这个问题呢?因为利用“大量简单的逻辑,组合而实现复杂的逻辑” 恰恰就是深度学习的哲学。深度学习现在已经有上千层的模型了,但是其最基本的元素还是神经元,只不过其组织的方式不同罢了。所以,学习深度学习的朋友不要有畏难的心理,在后面的学习中,你会发现,深度学习也不过如此嘛。

2 从多层感知机到神经网络

神经网络的改进,激活函数。未完待续。

发布了9 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/u012995500/article/details/88186084