在本章中,我们将定义一个多层线性网络,并将其作为本书的第一个代码示例。从历史上来看,感知机这个名称是指具有单一线性层的模型,因此,如果它有多层,我们就可以称之为多层感知机(Multilayer perceptron,MLP)。图1.1展示了一个一般的神经网络,它具有一个输入层、一个中间层和一个输出层。
图1.1
在图1.1中,第一层中的每个节点接收一个输入,并根据预设的本地决策边界值确定是否激发。然后,第一层的输出传递给中间层,中间层再传递给由单一神经元组成的最终的输出层。有趣的是,这种分层组织似乎模仿了我们前面讨论过的人类的视觉系统。
全连接的网络是指每层中的每个神经元和上一层的所有神经元有连接,和下一层的所有神经元也都有连接。
让我们来考虑一个单一的神经元如何选择最佳的权重 w 和偏差 b ?理想情况下,我们想提供一组训练样本,让机器通过调整权重值和偏差值,使输出误差最小化。为了更加的具体,我们假设有一组包含猫的图像,以及另外单独的一组不包含猫的图像。为了简单起见,假设每个神经元只考虑单个输入像素值。当计算机处理这些图像时,我们希望我们的神经元调整其权重和偏差,使得越来越少的图像被错误识别为非猫。这种方法似乎非常直观,但是它要求权重(和/或偏差)的微小变化只会在输出上产生微小变化。
如果我们有一个较大的输出增量,我们就不能进行渐进式学习(而非在所有的方向上进行尝试——这样的过程称为穷举搜索——我们不知道是否在改进)。毕竟,小孩子是一点一点学习的。不幸的是,感知机并不表现出这种一点一点学习的行为,感知机的结果是0或1,这是一个大的增量,它对学习没有帮助,如图1.2所示。
我们需要一些更平滑的东西,一个从0到1逐渐变化不间断的函数。在数学上,这意味着我们需要一个可以计算其导数的连续的函数。
图1.2
sigmoid函数的定义如下:
如图1.3所示,当输入在(−∞,∞)的区间上变化时,位于(0,1)区间上的输出值变化很小。从数学的角度讲,该函数是连续的。典型的sigmoid函数如图1.3所示。
图1.3
神经元可以使用sigmoid来计算非线性函数 σ ( z = wx + b )。注意,如果 z = wx + b 是非常大的正值,那么e − z →0,因而 σ ( z )→1;而如果 z = wx + b 是非常大的负值,e − z →∞,因而 σ ( z )→0。换句话说,以sigmoid为激活函数的神经元具有和感知机类似的行为,但它的变化是渐进的,输出值如0.553 9或0.123 191非常合理。在这个意义上,sigmoid神经元可能正是我们所要的。
sigmoid并非可用于神经网络的唯一的平滑激活函数。最近,一个被称为修正线性单元(Rectified Linear Unit,ReLU)的激活函数很受欢迎,因为它可以产生非常好的实验结果。
ReLU函数简单定义为 f ( x )=max(0, x ),这个非线性函数如图1.4所示。对于负值,函数值为零;对于正值,函数呈线性增长。
图1.4
在神经网络领域,sigmoid和ReLU通常被称为激活函数。在“Keras中的不同优化器测试”一节中,我们将看到,那些通常由sigmoid和ReLU函数产生的渐进的变化,构成了开发学习算法的基本构件,这些构件通过逐渐减少网络中发生的错误,来一点一点进行调整。图1.5给出了一个使用 σ 激活函数的例子,其中( x 1 , x 2 , …, x m )为输入向量,( w 1 , w 2 , …, w m )为权重向量, b 为偏差, 表示总和。
图1.5
Keras支持多种激活函数,完整列表请参考Keras官网。