引言
神经网络如今已经不算是特别热点的话题了,准确来说,它已经火了很久了。但不可否认的是,在当前环境下,神经网络依然是解决许多预测问题最准确的方法之一。
人工智能这一领域,有许许多多的名词,机器学习、深度学习、监督学习、非监督学习、强化学习、深度强化学习等等……本篇文章不对此进行过多解释,有兴趣的同学可以查一查。而所谓的“深度学习”,简单来说,就是通过神经网络进行学习,而深度,可以理解为神经网络有很多层,以及其他的一些机制。至于什么是神经网络,什么是层,以及神经网络如何搭建,就是我们今天的话题啦。
神经网络的引入
神经网络是什么?
上图就是一个简单的神经网络。可以看到,这个神经网络有四层,第一层我们一般称之为“输入层”,也就是我们的输入数据。最后一层是“输出层”,也就是输入数据经过一番操作后的输出结果。中间两层我们一般称之为“隐藏层”,这是因为在实际的学习以及应用过程中,我们一般不会关注神经网络内部的输入输出数据。
例如在进行人脸识别的时候,我们的输入就是我们自己的脸,或者说机器扫描到的关于人脸的数据,对应的输出,可以是人名,也可以是每个人的身份证号。高铁进站的时候,往往需要刷身份证并且刷脸,如果刷脸后扫描的身份结果与身份证一致,那么才被允许通过。虽然不晓得高铁站使用的人脸识别系统内部算法是什么,但是神经网络是可以解决这一问题的。另外,在使用过程中,我们只关心神经网络能否正确地将人脸与身份相匹配,并不关心神经网络的内部是如何运作的,数据在神经网络内部是如何处理的。因此,神经网络的内部就像一个加工数据的黑盒子,并不直接展现给我们,所以对应的中间层,我们一般称之为“隐藏层”啦。
神经网络之所以称为神经网络,一般可以理解为,它是对生物界中大脑工作机制的抽象与模仿。大脑是一个很神奇的器官,里面的基本单元就是如图所示的神经元。
我们在日常生活中接收信息,处理信息,作出反应等等,都是通过神经元的运作来实现的。神经元的结构十分简单,分为树突、轴突、终端。一般情况下,树突接受信号,经过轴突进行传递以及处理,之后再通过终端进行输出。考虑到不同的输入信号强度不同,对于那些强度较弱信号,神经元有时候并不会作出反应。也就是说,在神经元的工作机制中,存在着某种阈值。当信号强度高于这一阈值的时候,神经元才会作出反应,低于这一阈值的时候,神经元并不进行动作。
基于上述工作机制,1943年两位大佬就提出了如上图所示的神经元的数学模型。一个神经元接受来自其他神经元的多个输入,来自不同神经元的输入的效果是不同的,体现在模型中,就是权重不同。所有输入与相应权重的线性组合,构成了当前神经元的“总输入”,或者说“最终输入”。这一输入与阈值进行比较,再通过相应的函数 进行处理,就得到了当前神经元的输出。这里的函数 ,一般称之为“激活函数”,也就是对于输入数据的加工处理。
神经网络的简单工作机制
在之前的文章中,我们提到过感知机模型。所谓的感知机模型,其实就是一个简单的激活函数为阶跃函数的神经网络模型。
感知机模型可以解决简单的线性可分条件下的分类问题,也可以用于解决“与、或、非”这些基本逻辑运算。接下来通过感知机模型的运作,介绍一下神经网络的工作机制。
首先,说明一下基本的逻辑运算——与、或、非
与,即,只有当时,才为1,其他情况均为0(其中,下文同理)。与的运算结果如下:
或,即,当与之中有一个为时,为1,当时,才为0。或的运算结果如下:
非,即,当时,,当时,。
对于上述的三种基本逻辑运算,感知机模型就可以轻松实现。这里用到的感知机模型,其实就是一个简单的两层神经网络模型。如图所示:
这个神经网络的数学表达,即
因此,对于“与”运算,令,即,当且仅当时,。
对于“或”运算,令,即,当或时,。
对于“非”运算,令,则,当时,,当时,。
是不是很简单?两层神经网络的工作方式其实就是这样,输入数据,赋予权重()和偏置()值,经过激活函数处理之后,就得到输出。
上面的逻辑运算,是比较简单的运算,现在有一个问题,我们能否通过这样一个两层的神经网络模型,或者说感知机模型,实现一个“异或()”运算呢?
所谓的“异或”运算,其运算结果如下图所示。即当,,当时,。
事实上,对于这样一个简单的感知机模型,无论如何调整参数,都是无法实现异或运算的。原因很简单,之前的文章里提到过,一个感知机模型,对应的是高维空间中的一个超平面。对于上述的感知机模型,对应的其实就是二维平面上的一条直线。
如上图所示,对于“与”和“或”运算,在空间中,正类()和负类()是线性可分的,只需要一条直线就可以把它们分开,而且这样的直线有无数条。
对于“非”运算,同样存在无数条直线可以将正类与负类分开。
但是对于异或运算,它们的正类和负类在空间中是线性不可分的。如下图所示:
三角形代表正类,圆形代表负类,你能找到一条直线,将三角形和圆形分开吗?可以让它们分别位于直线划分出的两个半平面吗?
很明显是不可以的。
这就是一个典型的线性不可分问题,即无法找到一个线性超平面使得空间中的正类和负类分别位于超平面的两边。对于线性可分问题,一定可以使用感知机模型,通过算法求解出一个合适的线性超平面,而对于线性不可分的问题,是无法找到一个可以区分正负类的线性超平面的。
要是我们的分类器是下图这样的就好了:
是的,对于异或问题,我们需要一个非线性的分类器,才可以解决这一问题。既然如此,我们能否在感知机模型的基础上进行修改,进而得到一个非线性的分类器呢?
这就是我们将要引入的多层感知机模型,也就是一个三层的神经网络模型啦。
如上图所示,现在输入是 ,输出是 。由于两层神经网络模型,也就是简单的感知机模型无法解决异或问题,所以我们在其中再加一层神经元来尝试解决这个问题。这一层神经元就是之前提到的隐藏层,图中即为 。
事实上,我们可以使用之前提到的“与、或、非”运算来实现“异或”运算。如下表所示:
首先,我们令 表示 的“与非运算”,即 ,令 表示 的“或运算”,即 ,之后,我们再令 。这样,我们就成功通过“与或非”三种基本运算表达出了“异或”运算。
或者
反映到神经网络模型中,就是给对应的参数赋值。即
就这样,通过添加一层神经元,我们可以解决一个非线性的分类问题。
这里可以指出,神经网络模型理论上可以通过调整网络结构、设定参数等逼近任何一个线性或者非线性函数。这也是神经网络模型预测特别准确的原因之一。
神经网络的基本概念
经过上面的例子,我们已经简单了解了神经网络的工作机制。接下来为了方便说明,对一些概念进行集中解释。
输入层、隐藏层、输出层
上面已经提到过这三个概念了,输入层就是我们的输入数据所处的位置。一般而言,输入数据的维度就是输入层神经元的个数。输出层就是神经网络的输出结果,根据实际需要可以决定是一个输出还是多个输出。隐藏层就是输入层与输出层之间的,在实际应用中不会展示出来的一层一层对数据进行处理的神经元层,典型的深度学习,其实就是隐藏层数很多模型很复杂的神经网络。
参数
神经网络的参数一般有两部分,分别是之前提到过的权重与阈值。权重就是衡量神经元与神经元之间关系强弱的数值,阈值就是每一个神经元是否可以被激活的临界值。一般为了统一表示,我们也将阈值称之为“偏置”。如图所示:
对于第二层的第一个神经元而言,其输入
这里, 就是第二层第一个神经元的偏置。考虑到结构的一致性,我们可以直接在输入层上方添加一个偏置神经元,其输入为 ,偏置神经元与后一层每一个神经元之间的权重,即为后一层相应神经元的偏置,也就是“阈值”。
根据上图的模型,可知 ,应该比较容易理解吧。在实际的应用中, 是可正可负的,因此为了方便计算和表示,我们使用偏置 来进行表示。类似的,
激活函数
上面提到的仅仅是一层神经元的输入,从输入到输出,还需要激活函数的作用。
如上图所示,激活函数使用 进行表示,所以第二层神经元的输出
即
类似的,这一层的输出,就是下一层的输入,数据就这样一步步朝着输出单向传递,我们称这样的神经网络为前馈神经网络。
至于激活函数,常见的激活函数有三种,分别是上文提到的阶跃函数,sigmoid函数以及Relu函数。阶跃函数一般不常使用,因为其导数往往为0,在实际计算过程中不太方便使用。sigmoid函数一度十分常用,因为其导数易于计算,且具有较好的非线性。逻辑回归中一般也是使用sigmoid函数进行映射,主要因为其取值有时候可以看成概率。
但是sigmoid函数有一个缺点,即当 特别大或者特别小时,导数也慢慢趋于0,使得训练渐渐变得缓慢。
目前,Relu函数则是较为常用的激活函数,其导数也特别易于计算,并且基本不会出现导数消失的情况。
小结
以上,我们介绍了神经网络的基本概念,工作机制,以及对于非线性情况的处理。之前我们提到过,机器学习的三要素分别是“模型”,“策略”,“算法”。目前为止,我们仅仅提到了神经网络的模型,而且是最简单的模型,但对于一个实际问题,例如手写数字识别,并没有提到如何设计损失函数,如何使用算法求解参数。以及神经网络中大名鼎鼎的误差反向传播算法,这里也丝毫没有提及。
别着急,下一篇文章里,我们就会以非常非常简单的方式,实现对于神经网络的构建,误差反向传播算法的实现以及对于实际问题——MNIST手写数字数据集的模型参数求解。下次见~
参考文献
本文主要基于两本神经网络入门书籍进行编写: