2.3 前向传递

前向传递,顾名思义,就是从神经网络的输入层开始,一层一层向输出层传递。这也是神经网络的一个常见的训练过程。

本节将阐述前向传递的流程,介绍常见的激活函数、损失函数,以及dropout的相关概念、神经网络的训练模式等。

2.3.1 前向传递的流程

我们以一个常见的三层神经网络为例解释前向传递的流程。如图2.7所示,左边是输入层,中间是隐藏层,右边是输出层。这样的结构是不是十分眼熟?在2.2节中介绍深度神经网络可以解决感知机不能解决的异或问题时,给出了相似的例子。只不过,在这里神经元的数量变多了,需要我们通过大量不同的特征值去预测需要的目标值,而且,在很多时候,在最终的输出层中也有不止一个神经元。

图2.7 三层神经网络

在前向传递中,最主要的过程就是神经元节点的权值运算。若使用表示第l层的第j个神经元的输入,则表示第l层的第j个神经元的输出,表示第l-1层的第k个神经元指向第l层的第j个神经元的权值,表示第l层的第j个神经元的偏移量,激活函数为σ,则第l层的输入与输出之间存在如下关系。

前向传递的思路和感知机类似,从输入层到输出层逐层计算,最后通过损失函数计算拟合误差。从整体看,前向传递的训练过程非常简单,只需要选定合适的激活函数和损失函数就可以完成。

2.3.2 激活函数

在2.1节和2.2节中都提到过激活函数,它的主要作用是使神经元的输出通过一个非线性函数实现,这样整个神经网络模型就不是线性的了。这个非线性函数就是激活函数。

本节将介绍几种常见的激活函数。在介绍之前要声明一下,激活函数是没有好坏之分的,要根据具体的问题选择合适的激活函数。

1.sigmoid函数

sigmoid函数的数学公式为,其函数图象如图2.8所示。

图2.8 sigmoid函数

从sigmoid函数的图象中我们可以知道,其输出在(0,1)这个开区间内。这一点很有意思,我们可以由此联想到概率。但是从严格意义上讲,不要把它当成概率。可以将它想象成一个神经元的放电率,中间斜率比较大的地方就是神经元的敏感区,两边比较平缓的地方就是神经元的抑制区。sigmoid函数曾是一个常用函数,而现在它已经不太受欢迎且很少被使用了,这主要由它的两个缺点所致。

(1)sigmoid函数饱和导致梯度消失

sigmoid神经元在函数的两端值为0或1时接近饱和,这些区域的梯度几乎为0。在后向传递中,这个局部梯度会与整个代价函数关于该单元输出的梯度相乘,结果也会接近0。因此,几乎没有信号通过神经元传到权重,再递归到数据了,这时的梯度对模型的更新没有任何贡献。

除此之外,为了防止饱和,应该特别留意权重矩阵的初始化。如果初始化权重过大,那么大多数神经元将会饱和,而这会导致神经网络几乎不学习。

(2)sigmoid函数不是关于原点中心对称的

这个缺点会导致网络层的输入不是以数值0为中心的,进而影响梯度下降的运作。如果输入的都是正数,那么关于w的梯度在后向传递的过程中,要么全是正数,要么全是负数,而这将导致梯度下降及在更新权重时出现“Z”字形的下降。当然,如果按batch(批)去训练,那么每个batch可能会得到不同的信号(将整个batch的梯度加起来,就可以缓解这个问题)。该问题与前面的神经元饱和问题相比,只是个小麻烦。

2.tanh函数

tanh函数的数学公式为,其函数图象如图2.9所示。

图2.9 tanh函数

tanh是双曲正切函数。tanh函数和sigmoid函数的曲线相似,但tanh函数的图象不像sigmoid函数的图象那样平缓。在输入很大或很小的时候,这两个函数的输出曲线都几乎是平滑的,梯度很小,不利于权重的更新。不过,这两个函数的输出区间不同,tanh函数的输出区间是(-1,1),而且整个函数是以0为中心的(这一点要比sigmoid函数有优势)。

在一般的二分类问题中,隐藏层会使用tanh函数,输出层会使用sigmoid函数。但是,这些并不是一成不变的,不仅要根据具体的问题来选择激活函数,而且要进一步进行调试。

3.ReLU函数

ReLU(rectified linear unit,修正线性单元)函数的数学公式为,其函数图象如图2.10所示。

图2.10 ReLU函数

ReLU函数是近年来比较热门的一个激活函数,与sigmoid函数和tanh函数相比,它有以下优点。

● 在输入为正数时,不存在梯度饱和问题。

● 由于ReLU函数只有线性关系,不管是前向传递还是后向传递,其计算速度比sigmoid函数和tanh函数都快很多。由于sigmoid函数和tanh函数需要计算指数,计算速度会比较慢。

当然,ReLU函数也有缺点。当输入为负数时,ReLU函数不会被激活,这表示一旦输入了负数,ReLU就会“死掉”。这种情况对前向传递的影响不大,因为有的区域是敏感的,有的区域是不敏感的。但是,在后向传递过程中,如果输入的是负数,梯度就为0(在这一点上,sigmoid函数和tanh函数有同样的问题)。另外,ReLU函数也不是以0为中心的函数。

4.maxout函数

maxout函数在深度神经网络的学习过程中增加了一个含有k个神经元的激活函数层,在多个输出值中取最大值。

需要注意的是,每个神经元的激活值仍然是由神经元决定的。如图2.11所示,在这个网络的第i层中有3个用红色圆圈表示的神经元,在第i+1层中有4个用彩色圆圈表示的神经元,在第i+1层中使用了k=3的maxout激活函数。根据连线颜色的不同也可以知道,第i+1层中的每个神经元都有3个激活值,其中最大的值才是该神经元的最终输出激活值。

图2.11 maxout函数

maxout函数的优点是可以在一定程度上避免梯度消失的发生,与ReLU函数相比不会出现“死掉”的现象。但是,maxout函数的缺点也很明显,从上述例子中可以看出,它不仅直接将参数量扩大了好几倍,而且需要很大的计算量。

5.softmax函数

softmax函数的数学公式为

softmax函数一般用在分类问题的输出层中,可以保证所有的输出神经元之和为1,每个输出所对应的[0,1]区间的数值就是输出的概率,取概率最大的作为预测值输出。这个激活函数也可以这么理解:当某个样本通过输出层使用softmax函数的神经网络进行分类时,在输出层的每个节点上输出的值均小于等于1,这些值分别代表它属于这些分类的概率。

2.3.3 损失函数

损失函数(loss function)用于估算模型的预测值与真实值的不一致程度。损失函数的值越小,模型的鲁棒性就越高。

1.均方误差损失函数

在介绍损失函数之前,要介绍一个概念——目标函数。目标函数用于衡量什么样的拟合结果才是最适合用来预测未知数据集的,从而进一步帮助神经网络拟合出更加精准的结果。其实,目标函数是一个比较宽泛的概念,因为有时实际情况与预测的差距并不是越小越好。

举一个常见的目标函数的例子。在均方误差目标函数中,N为总体样本数,yi为实际的输出值,为预测的输出值,公式如下。

可以看出,这个函数是用于计算方差均值的,这时显然函数值越小越好(模型的误差越小,损失就越小),所以该函数也称作“均方误差损失函数”。当然,在很多情况下,需要根据模型的特点和设立的目标来选择合适的损失函数。在大多数情况下,我们所说的目标函数就是损失函数,但也存在一些特殊情况。从上述例子中就能看出,损失函数在一定程度上可以帮助我们找出拟合度最高的模型,但是,如果出现了过拟合的情况,损失函数的判定方法就不那么适合了。过拟合的出现说明此时的模型过于复杂,并不适合进行预测,这时就需要进行正则化处理。

目标函数就是这个两方面的结合,它不仅要使得拟合损失尽可能低,还要避免出现像过拟合这样的干扰判断的情况,然后,通过综合考量,得出一个最好的结果。

2.交叉熵损失函数

除了均方误差损失函数,还有很多损失函数。在这里介绍一下交叉熵损失函数。同样,设N为总体样本数,yi为实际的输出值,为预测的输出值,计算公式如下。

我们都知道,要根据实际问题来选择合适的损失函数。例如,在处理多类别分类问题时,交叉熵损失函数就要比均方误差损失函数有优势。那么,什么样的问题可以称为多分类问题呢?在这里举一个简单的例子:我们要对动物照片进行分类,有猫、狗、鸡、鸭、鱼等N种动物,那么输出就有N维,在输入一幅图片进行分类判断时,每个输出维度都代表该图片与某类动物的符合程度的得分,数值大的自然符合程度高。

其实,多分类问题更倾向于输出不同类别的概率,因此这类问题的激活函数往往是softmax。softmax函数可以使输出变成概率的形式,并使所有输出的和为1。之所以选择交叉熵函数作为损失函数,是因为它对参数的偏导数的形式十分简洁,而这将使网络训练过程变得简单。

交叉熵损失函数的偏导数公式如下。

其中,zi表示第i层的输出值,表示预测的输出值,yi表示实际的输出值。下面我们介绍公式的推导过程[1]

为了方便起见,我们用替换2.3.2节中softmax函数的数学公式yj,可以得到下式。

需要求得的梯度公式是Loss对输出值zi的梯度。结合交叉熵损失函数,根据复合函数的链式求导法则,得到下式。

这里不是,而是,主要是softmax函数的特性所致。softmax函数公式的分母包含所有神经元的输出,也包含zi,对其求偏导可分为i=lil两种情况,且计算结果不同。直接理解有一定难度,将其代入推导过程将有助于我们思考。

将上式等号右边的式子分成两部分进行推导。先推导乘号左边的式子。方便起见,假设对数函数的底为e,那么就变成了

接着推导,分为两种情况。

i=l,则

il,则

结合上面三个公式的推导,得到下式。

对分类问题而言,最终yi只会有一个类别,即1,其余的全是0。因此,上式可化简为

但是,因为前向传递必然会产生一定的误差,在实际训练中,预测的输出值可能与实际的输出值差距很大(此时损失函数的值也会比较大),所以,需要使用更好的训练步骤来降低误差——这就是2.4节将要介绍的后向传递。