1.6 理解反向传播

本节将从直观上解释反向传播。反向传播是一种使用链式法则计算梯度的方法。理解这个过程及其精妙之处,对于理解并有效地开发、设计和调试神经网络至关重要。

通常,给定一个函数f(x),其中x是一个输入向量,我们要计算f在x点的梯度,用∇(f(x))来表示。这是因为在神经网络中,函数f基本上是一个损失函数(L),输入x是权重和训练数据的组合。符号∇发音是nabla。

(xi,yi)i=1……N

为什么要对权重参数求梯度?

考虑到训练数据通常是固定的,而参数是可以控制的变量。通常计算参数的梯度以便用它进行参数更新。梯度∇f是偏导数向量,即

∇f=[df/dx,df/dy]=[y,x]

概括地说,反向传播将包括:

·做一个前馈运算。

·将模型输出与期望输出进行比较。

·计算误差。

·向后运行前馈运算(反向传播),将误差分散到每个权重。

·以此来更新权重,得到一个更好的模型。

·持续这些步骤,直到得到一个满意的模型。

构建一个神经网络来识别数字0到9。这种网络应用能根据邮政编码对邮件进行分类、从图像中识别电话号码或者住宅电话、从包裹的图像中提取包裹数量等。

在大多数情况下,反向传播是在框架中实现的,比如TensorFlow。然而,通过简单地添加任意数量的隐含层,反向传播不总能在数据集上神奇地工作。事实上,如果权重初始化得很草率,这些非线性函数就会饱和并停止学习。这意味着训练损失将会趋于平缓,不会继续下降,这就是所谓的梯度消失问题。

如果权重矩阵W初始化得太大,则矩阵相乘的输出值范围也可能很大,这反过来会使向量z中的所有输出几乎都是二进制的:1或0。然而如果是这样,则sigmoid非线性局部梯度z*(1-z)在这两种情况下都将变为0(消失),这将使x和W的梯度也为0。由于链式法则里的乘法,从这一点开始,剩下的向后传递的结果都将是0。

另一个非线性激活函数是ReLU,它在0处的阈值神经元如下所示。使用以ReLU为核心的全连接层的前向和后向传递计算如下:

如果观察一段时间,你会发现如果一个神经元在前向传递(即z=0,不会被激活)中被固定为零,那么它的权值就会得到一个零梯度。这可能会导致所谓的dead ReLU问题。这意味着如果一个ReLU神经元不幸以这种方式初始化,以至它永远不会被激活,或者如果一个神经元的权重在训练过程中被一个大的更新给破坏了,在这种情况下,这个神经元将永远死去。它类似于永久性的、不可恢复的脑损伤。有时,你甚至能够通过一个训练好的网络将整个训练集向前推进,最终却发现大部分(大约40%)神经元在整个过程中都是0。

在微积分中,链式法则用于计算两个或多个函数的复合函数的导数。也就是说,如果有两个函数f和g,链式法则表示复合函数f°g的导数。将x映射到f(g(x))的函数用函数f和g的导数及函数的乘积表示如下:

(f°g)'=(f'°g)·g'

有一种更明确的方法来表示它,通过变量,让F=f°g,或者对于所有x,F(x)=f(g(x)),然后可以表示为:

F'(x)=f'(g(x))g'(x)

链式法则也可以用莱布尼兹表示法写成,方法如下。如果一个变量z依赖一个变量y,变量y又依赖一个变量x(y和z是因变量),那么z通过中间变量y也依赖x。链式法则表示如下:

z=1/(1+np.exp(-np.dot(W,x))) # forward pass

dx=np.dot(W.T,z*(1-z)) # backward pass:local gradient for x

dW=np.outer(z*(1-z),x) # backward pass:local gradient for W

如图1-8所示,图左边的前向传递运用输入变量x和y通过函数f(x,y)计算输出z。图右边表示后向传递,接收dL/dz,即损失函数对z的梯度,损失函数对x和y的梯度可以用链式法则计算,如图1-8所示。

图1-8 前向/后向传递的链式法则