Deep Learning Book 学习笔记(6)

Deep Feedforward Networks

Posted by Wenlong Shen on April 25, 2018

深度前馈网络(deep feedforward network),也叫作前馈神经网络(feedforward neural network)或者多层感知机(multilayer perceptron, MLP),是典型的深度学习模型。

我们首先理解下“前向”的概念,即信息流从输入\(x\)流经中间函数\(f\),途中学习参数\(\theta\)得到最佳近似,最终到达输出\(y\)的过程。输出和模型本身之间没有反馈,若有则形成循环神经网络。

前馈网络是机器学习最重要的模型之一,卷积神经网络就是一类专门的前馈网络。前馈神经网络通常由许多不同函数复合而成,形成一个有向无环图,这些复合的函数连接成的链式结构就是神经网络最常见的结构,链的全长即为模型的深度(depth),链的最后一层是输出层(output layer),其它为隐藏层(hidden layer)。

实例:学习XOR

这里有一个具体的例子,即学习XOR函数,其中异或逻辑是指“相异为真,相同为假”。目标函数是\(y=f^*(x)\),我们的模型是\(y=f(x;\theta)\),学习算法需要不断调整\(\theta\)使\(f\)尽可能地接近\(f^*\)。

在这个例子里我们只使用四个点\(X=\{[0,0]^T,[0,1]^T,[1,0]^T,[1,1]^T\}\),使用均方误差作为损失函数,故评价整个训练集的表现即MSE为:

\[J(\theta)=\frac{1}{4}\sum_{x \in X}(f^*(x)-f(x;\theta))^2\]

假如我们为自己的模型\(y=f(x;\theta)\)选择一个线性形式,定义为:\(f(x;w, b)=x^Tw+b\),则使用正规方程解关于\(w\)和\(b\)最小化\(J(\theta)\)的解为\(w=0,\ b=\frac{1}{2}\),该模型对于任一输入的输出都是0.5。原因在于线性模型不足以描述XOR,但我们可以用另外的模型学习一个新的特征空间,使线性模型在该空间内有效。这样,我们就引入了前馈神经网络,它共有两层,第一层即隐藏层,通过\(f^{(1)}(x;W, c)\),得到隐藏向量\(h\),第二层即输出层,我们依然使用线性模型,只不过输入不再是\(x\),而是\(h\)。至此,我们的网络为链在一起的两个函数:\(h=f^{(1)}(x;W, c)\)和\(y=f^{(2)}(h;w, b)\),完整的形式即为:

\[f(x;W, c, w, b)=f^{(2)}(f^{(1)}(x))\]

下图详细描述了上述情况,即原模型中,当\(x_1=0\)时,模型的输出需要随着\(x_2\)的增大而增大,当\(x_1=1\)时,模型的输出又要随着\(x_2\)的增大而减小,可见线性模型无法满足这一条件。所以当我们通过新的函数将空间变换,就可以用线性模型描述其为\(h_1\)增大而\(h_2\)减小了。 xor 接下来我们需要使用合适的\(f^{(1)}\)函数,显然我们要用非线性函数。通常,神经网络常在仿射变换后跟一个激活函数来实现这个目标,我们使用相同的策略,定义\(h=g(W^Tx+c)\),激活函数为\(g(z)=max\{0,z\}\),即整流线性单元(rectified linear unit,ReLU)。现在,我们的整个网络为:

\[f(x;W, c, w, b)=w^Tmax\{0, W^Tx+c\}+b\]

至此,我们可以得到XOR问题的一个解,即为:

\[W=\left[ \begin{matrix} 1 & 1 \\ 1 & 1 \\ \end{matrix} \right],\ c=\left[ \begin{matrix} 0 \\ -1 \\ \end{matrix} \right],\ w=\left[ \begin{matrix} 1 \\ -2 \\ \end{matrix} \right],\ b=0\]

我们可以带入实际输入,一步步体会。这个例子中,我们简单地指定了解决方案,但在实际情况下面对大规模的训练样本时,我们无法如此简单猜解,相对地可以使用基于梯度的优化算法。

基于梯度的学习

神经网络的问题在于其非线性导致大部分代价函数变得非凸,训练过程中使用的迭代、基于梯度的优化不一定能保证全局收敛,且对初始参数值很敏感。

大多数现代的神经网络使用最大似然来训练。这意味着代价函数就是负的对数似然,它与训练数据和模型分布间的交叉熵等价。这个代价函数表示为

\[J(\theta)=-E_{x,y\sim p_{data}}log\ p_{model}(y\vert x)\]

我们通常需要代价函数的梯度足够大并具有足够的预测性,来为学习算法提供一个好的指引。饱和(变得非常平)的函数无法达到这一目的,因为它们的梯度变得非常小。一些用于产生隐藏单元或者输出单元的输出的激活函数会饱和,负的对数似然帮助我们在很多模型中避免这个问题。很多输出单元都会包含一个指数函数,这在它的变量取绝对值非常大的负值时会造成饱和,负对数似然代价函数中的对数函数消除了这些输出单元中的指数效果。

隐藏单元

前馈神经网络的一个独有问题是:选择什么样的隐藏单元,因而在整体的设计过程中充满了试错。

整流线性单元是一个不错的选择:\(g(z)=max\{0,z\}\),只要处于激活状态,它的导数都能保持较大,梯度较大且一致,易于学习,还可以作用于仿射变换:\(h=g(W^Tx+b)\)。其他一些常见的扩展在\(z_i<0\)时使用一个非零的斜率\(\alpha_i\):\(g(z,\alpha)_i=max\{0,z_i\}+\alpha_i\ min\{0,z_i\}\),如,绝对值整流令\(\alpha_i=-1\),渗漏整流线性单元令\(\alpha_i\)取一个很小的值,参数化整流线性单元则将\(\alpha_i\)作为学习的参数。我们还可以利用maxout单元进一步扩展整流线性单元,即将\(z\)分成每组具有\(k\)个值的组,从而对输入的\(x\)空间多个方向进行分段响应。

在引入整流线性单元之前,大多数神经网络使用logistic sigmoid激活函数:\(g(z)=\sigma(z)\),或者是双曲正切激活函数\(g(z)=tanh(z)\),这两个函数密切相关:\(tanh(z)=2\sigma(2z)-1\)。sigmoid单元在其大部分定义域内都饱和,这种广泛饱和性使得基于梯度的学习变得困难,我们往往需要一个合适的代价函数来抵消这种饱和性。另外,双曲正切激活函数通常要比logistic sigmoid函数表现更好。

其他一些常见的隐藏单元类型还包括:径向基函数,softplus函数,硬双曲正切函数等。

架构设计

神经网络设计的另一个关键点是它的架构,即确定单元的个数以及连接方式。

线性函数易于学习,但实际应用中多为非线性函数,不过万能近似定理告诉我们,一个前馈神经网络如果具有线性输出层和至少一个具有“挤压”性质的激活函数(如logistic sigmoid)的隐藏层,那么只要有足够数量的隐藏单元,它就可以以任意精度来近似任何从一个有限维空间到另一个有限维空间的Borel可测函数。即无论我们试图学习什么函数,都会有一个MLP一定能够表示这个函数。不过即使如此,我们依然面临这优化算法找不到参数值,或是过拟合而选择了错误函数的情况。一般地,具有\(d\)个输入、深度为\(l\)、每个隐藏层具有\(n\)个单元的整流网络可以描述的线性区域的数量是:

\[O\left(\left(\begin{matrix}n\\d\end{matrix}\right)^{d(l-1)}n^d\right)\]

层与层之间的连接方式也是架构中的重要问题之一,有的全连接,有的输入层中的每个单元仅连接到输出层单元的一个小子集,这些用于减少连接数量的策略减少了参数的数量以及用于评估网络的计算量,但通常高度依赖于问题,如卷积神经网络。

反向传播算法

对于前馈网络模型,从输入\(x\),传播到每一层的隐藏单元,最终输出\(\hat y\),这就是前向传播(forward propagation)。而在计算梯度的过程中,我们常使用反向传播算法,其允许来自代价函数的信息通过网络向后流动,便于计算梯度。注意反向传播常被误解为用于多层神经网络的整个学习算法,实际上,其仅指用于计算梯度的方法。

反向传播是一种计算链式法则的算法,使用高效的特定运算顺序。首先,链式法则是说

\[\frac{dz}{dx}=\frac{dz}{dy}\frac{dy}{dx}\]

然后,对于下图这样的模型,我们可以有 back

\[\frac{\partial z}{\partial w} = \frac{\partial z}{\partial y}\frac{\partial y}{\partial x}\frac{\partial x}{\partial w} = f'(y)f'(x)f'(w)\]