Skip to content

Latest commit

 

History

History
executable file
·
350 lines (251 loc) · 25.7 KB

neural_network.md

File metadata and controls

executable file
·
350 lines (251 loc) · 25.7 KB

机器学习之神经网络算法

在机器学习和认知科学领域,人工神经网络(英文:artificial neural network,缩写ANN),简称神经网络(英文:neural network,缩写NN)或类神经网络,是一种模仿生物神经网络(动物的中枢神经系统,特别是大脑)的结构和功能的数学模型或计算模型,用于对函数进行估计或近似。神经网络由大量的人工神经元联结进行计算。大多数情况下人工神经网络能在外界信息的基础上改变内部结构,是一种自适应系统。现代神经网络是一种非线性统计性数据建模工具。

神经网络(Neural Network)概述

神经网络算法能够提供一种复杂且非线性的假设模型$h_{W,b}(x )$,它具有参数$W, b$,可以以此参数来拟合我们的数据。

为了描述神经网络,我们先从最简单的神经网络讲起,这个神经网络仅由一个“神经元”构成,以下即是这个“神经元”的图示:

singleneuron

这个“神经元”是一个以$x_1, x_2, x_3$及截距$+1$为输入值的运算单元,其输出为$h_{W,b}(x) = f(W^Tx) = f(\sum_{i=1}^3 W_{i}x_i +b)$,其中函数$f : \Re \mapsto \Re$被称为“激活函数”。在本教程中,我们选用sigmoid函数作为激活函数$f(\cdot)$ $$f(z) = \frac{1}{1+\exp(-z)}$$

可以看出,这个单一“神经元”的输入-输出映射关系其实就是一个逻辑回归(logistic regression)。

虽然本系列教程采用sigmoid函数,但你也可以选择双曲正切函数(tanh): $$f(z) = \tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}$$ 以下分别是sigmoid及tanh的函数图像

sigmoid function tanh

$\tanh(z)$函数是sigmoid函数的一种变体,它的取值范围为$[-1,1]$,而不是sigmoid函数的$[0,1]$。

注意,与其它地方不同的是,这里我们不再令$x_0=1$。取而代之,我们用单独的参数$b$来表示截距。

最后要说明的是,有一个等式我们以后会经常用到:如果选择$f(z) = 1/(1+\exp(-z))$,也就是sigmoid函数,那么它的导数就是$f'(z) = f(z) (1-f(z))$(如果选择tanh函数,那它的导数就是$f'(z) = 1- (f(z))^2$,你可以根据sigmoid(或tanh)函数的定义自行推导这个等式。

神经网络模型

所谓神经网络就是将许多个单一“神经元”联结在一起,这样,一个“神经元”的输出就可以是另一个“神经元”的输入。例如,下图就是一个简单的神经网络:

network331

我们使用圆圈来表示神经网络的输入,标上“$+1$”的圆圈被称为偏置节点,也就是截距项。神经网络最左边的一层叫做输入层,最右的一层叫做输出层(本例中,输出层只有一个节点)。中间所有节点组成的一层叫做隐藏层,因为我们不能在训练样本集中观测到它们的值。同时可以看到,以上神经网络的例子中有3个输入单元(偏置单元不计在内),3个隐藏单元及一个输出单元。

我们用${n}l$来表示网络的层数,本例中$n_l=3$,我们将第$l$层记为$L_l$,于是$L_1$是输入层,输出层是$L{n_l}$。本例神经网络有参数$(W,b) = (W^{(1)}, b^{(1)}, W^{(2)}, b^{(2)})$,其中$W^{(l)}_{ij}$(下面的式子中用到)是第$l$层第$j$单元与第$l+1$层第$i$单元之间的联接参数(其实就是连接线上的权重,注意标号顺序),$b^{(l)}_i$是第$l+1$层第$i$单元的偏置项。因此在本例中,$W^{(1)} \in \Re^{3\times 3}$,$W^{(2)} \in \Re^{1\times 3}$。注意,没有其他单元连向偏置单元(即偏置单元没有输入),因为它们总是输出$+1$。同时,我们用$s_l$表示第$l$层的节点数(偏置单元不计在内)。

我们用$a^{(l)}_i$表示第$l$层第$i$单元的激活值(输出值)。当$l=1$时,$a^{(1)}i = x_i$,也就是第$i$个输入值(输入值的第$i$个特征)。对于给定参数集合$W,b$,我们的神经网络就可以按照函数$h{W,b}(x)$来计算输出结果。本例神经网络的计算步骤如下:

$$ \begin{align} a_1^{(2)} &= f(W_{11}^{(1)}x_1 + W_{12}^{(1)} x_2 + W_{13}^{(1)} x_3 + b_1^{(1)}) \\ a_2^{(2)} &= f(W_{21}^{(1)}x_1 + W_{22}^{(1)} x_2 + W_{23}^{(1)} x_3 + b_2^{(1)}) \\ a_3^{(2)} &= f(W_{31}^{(1)}x_1 + W_{32}^{(1)} x_2 + W_{33}^{(1)} x_3 + b_3^{(1)}) \\ h_{W,b}(x) &= a_1^{(3)} = f(W_{11}^{(2)}a_1^{(2)} + W_{12}^{(2)} a_2^{(2)} + W_{13}^{(2)} a_3^{(2)} + b_1^{(2)}) \end{align}$$

我们用$z^{(l)}i$表示第$l$层第$i$单元输入加权和(包括偏置单元),比如,$z_i^{(2)} = \sum{j=1}^n W^{(1)}_{ij} x_j + b^{(1)}_i$,则$a^{(l)}_i = f(z^{(l)}_i)$。

这样我们就可以得到一种更简洁的表示法。这里我们将激活函数$f(\cdot)$扩展为用向量(分量的形式)来表示,即$f([z_1, z_2, z_3]) = [f(z_1), f(z_2), f(z_3)]$,那么,上面的等式可以更简洁地表示为: $$ \begin{align} z^{(2)} &= W^{(1)} x + b^{(1)} \ a^{(2)} &= f(z^{(2)}) \ z^{(3)} &= W^{(2)} a^{(2)} + b^{(2)} \ h_{W,b}(x) &= a^{(3)} = f(z^{(3)}) \end{align}$$

我们将上面的计算步骤叫作前向传播。回想一下,之前我们用$a^{(1)} = x$表示输入层的激活值,那么给定第$l$层的激活值$a^{(l)}$后,第$l+1$层的激活值$a^{(l+1)}$就可以按照下面步骤计算得到: $$ \begin{align} z^{(l+1)} &= W^{(l)} a^{(l)} + b^{(l)} \ a^{(l+1)} &= f(z^{(l+1)}) \end{align}$$

将参数矩阵化,使用矩阵-向量运算方式,我们就可以利用线性代数的优势对神经网络进行快速求解。

目前为止,我们讨论了一种神经网络,我们也可以构建另一种结构的神经网络(这里结构指的是神经元之间的联接模式),也就是包含多个隐藏层的神经网络。最常见的一个例子是$n_l$层的神经网络,第$1$层是输入层,第$n_l$层是输出层,中间的每个层$l$与层$l+1$紧密相联。这种模式下,要计算神经网络的输出结果,我们可以按照之前描述的等式,按部就班,进行前向传播,逐一计算第$L_2$层的所有激活值,然后是第$L_3$层的激活值,以此类推,直到第$L_{nl}$层。这是一个前馈神经网络的例子,因为这种联接图没有闭环或回路。

神经网络也可以有多个输出单元。比如,下面的神经网络有两层隐藏层:$L_2$及$L_3$,输出层$L_4$有两个输出单元。 network3322

要求解这样的神经网络,需要样本集$(x^{(i)}, y^{(i)})$,其中$y^{(i)} \in \Re^2$。如果你想预测的输出是多个的,那这种神经网络很适用。(比如,在医疗诊断应用中,患者的体征指标就可以作为向量的输入值,而不同的输出值$y_i$可以表示不同的疾病存在与否。)

Backpropagation算法

假设我们有一个固定样本集${(x^{(1)}, y^{(1)}), \cdots, (x^{(m)}, y^{(m)})}$,它包含$m$个样例。我们可以用批量梯度下降法来求解神经网络。具体来讲,对于单个样例$(x,y)$,其代价函数为: $$\begin{align} J(W,b; x,y) = \frac{1}{2} \left| h_{W,b}(x) - y \right|^2. \end{align}$$ 这是一个(二分之一的)方差代价函数。给定一个包含$m$个样例的数据集,我们可以定义整体代价函数为: $$ \begin{align} J(W,b) &= \left[ \frac{1}{m} \sum_{i=1}^m J(W,b;x^{(i)},y^{(i)}) \right] + \frac{\lambda}{2} \sum_{l=1}^{n_l-1} ; \sum_{i=1}^{s_l} ; \sum_{j=1}^{s_{l+1}} \left( W^{(l)}{ji} \right)^2 \ &= \left[ \frac{1}{m} \sum{i=1}^m \left( \frac{1}{2} \left| h_{W,b}(x^{(i)}) - y^{(i)} \right|^2 \right) \right] + \frac{\lambda}{2} \sum_{l=1}^{n_l-1} ; \sum_{i=1}^{s_l} ; \sum_{j=1}^{s_{l+1}} \left( W^{(l)}_{ji} \right)^2 \end{align}$$ 以上关于$J(W,b)$定义是一个均方差项。以上的代价函数经常被用于分类和回归问题。在分类问题中,我们用$y = 0$或$1$,来代表两种类型的标签(回想一下,这是因为 sigmoid激活函数的值域为$[0,1]$;如果我们使用双曲正切型激活函数,那么应该选用$-1$和$+1$作为标签)。对于回归问题,我们首先要变换输出值域(译者注:也就是$y$,以保证其范围为$[0,1]$(同样地,如果我们使用双曲正切型激活函数,要使输出值域为$[-1,1]$。

我们的目标是针对参数$W$和$b$来求其函数$J(W,b)$的最小值。为了求解神经网络,我们需要将每一个参数$W^{(l)}_{ij}$和$b^{(l)}i$初始化为一个很小的、接近零的随机值(比如说,使用正态分布${Normal}(0,\epsilon^2 )$生成的随机值,其中$\epsilon$设置为$0.01 )$,之后对目标函数使用诸如批量梯度下降法的最优化算法。因为$J(W, b)$是一个非凸函数,梯度下降法很可能会收敛到局部最优解;但是在实际应用中,梯度下降法通常能得到令人满意的结果。最后,需要再次强调的是,要将参数进行随机初始化,而不是全部置为$0$。如果所有参数都用相同的值作为初始值,那么所有隐藏层单元最终会得到与输入值有关的、相同的函数(也就是说,对于所有$i$,$W^{(1)}{ij}$都会取相同的值,那么对于任何输入$x$都会有:$a^{(2)}_1 = a^{(2)}_2 = a^{(2)}_3 = \ldots )$。随机初始化的目的是使对称失效。

梯度下降法中每一次迭代都按照如下公式对参数$W 和$b 进行更新: $$ \begin{align} W_{ij}^{(l)} &= W_{ij}^{(l)} - \alpha \frac{\partial}{\partial W_{ij}^{(l)}} J(W,b) \ b_{i}^{(l)} &= b_{i}^{(l)} - \alpha \frac{\partial}{\partial b_{i}^{(l)}} J(W,b) \end{align}$$ 其中$\alpha$是学习速率。其中关键步骤是计算偏导数。我们现在来讲一下反向传播算法,它是计算偏导数的一种有效方法。

我们首先来讲一下如何使用反向传播算法来计算$\frac{\partial}{\partial W_{ij}^{(l)}} J(W,b; x, y)$和$\frac{\partial}{\partial b_{i}^{(l)}} J(W,b; x, y)$,这两项是单个样例$(x,y)$的代价函数$J(W,b;x,y)$的偏导数。一旦我们求出该偏导数,就可以推导出整体代价函数$J(W,b)$的偏导数:

$$ \begin{align} \frac{\partial}{\partial W_{ij}^{(l)}} J(W,b) &= \left[ \frac{1}{m} \sum_{i=1}^m \frac{\partial}{\partial W_{ij}^{(l)}} J(W,b; x^{(i)}, y^{(i)}) \right] \\ \frac{\partial}{\partial b_{i}^{(l)}} J(W,b) &= \frac{1}{m}\sum_{i=1}^m \frac{\partial}{\partial b_{i}^{(l)}} J(W,b; x^{(i)}, y^{(i)}) \end{align}$$

反向传播算法的思路如下:给定一个样例$(x,y)$,我们首先进行“前向传导”运算,计算出网络中所有的激活值,包括$h_{W,b}(x)$的输出值。之后,针对第$l$层的每一个节点$i$,我们计算出其“残差”$\delta^{(l)}_i$,该残差表明了该节点对最终输出值的残差产生了多少影响。对于最终的输出节点,我们可以直接算出网络产生的激活值与实际值之间的差距,我们将这个差距定义为$\delta^{(n_l)}_i$(第$n_l$层表示输出层)。对于隐藏单元我们如何处理呢?我们将基于节点(译者注:第$l+1$层节点)残差的加权平均值计算$\delta^{(l)}_i$,这些节点以$a^{(l)}_i$作为输入。下面将给出反向传导算法的细节:

进行前馈传导计算,利用前向传导公式,得到$L_2, L_3, \ldots$直到输出层$L_{n_l}$的激活值。 对于第$n_l$层(输出层)的每个输出单元$i$,我们根据以下公式计算残差: $$ \begin{align} \delta^{(n_l)}_i = \frac{\partial}{\partial z^{(n_l)}i} ;; \frac{1}{2} \left|y - h{W,b}(x)\right|^2 = - (y_i - a^{(n_l)}_i) \cdot f'(z^{(n_l)}_i) \end{align}$$

[译者注: $$ \begin{align} \delta^{(n_l)}i &= \frac{\partial}{\partial z^{n_l}i}J(W,b;x,y) = \frac{\partial}{\partial z^{n_l}i}\frac{1}{2} \left|y - h{W,b}(x)\right|^2 \ &= \frac{\partial}{\partial z^{n_l}i}\frac{1}{2} \sum{j=1}^{S{n_l}} (y_j-a_j^{(n_l)})^2 = \frac{\partial}{\partial z^{n_l}i}\frac{1}{2} \sum{j=1}^{S{n_l}} (y_j-f(z_j^{(n_l)}))^2 \ &= - (y_i - f(z_i^{(n_l)})) \cdot f'(z^{(n_l)}_i) = - (y_i - a^{(n_l)}i) \cdot f'(z^{(n_l)}i) \end{align} ]$$ 对$l = n_l-1, n_l-2, n_l-3, \ldots, 2$的各个层,第$l$层的第$i$个节点的残差计算方法如下: $$ \delta^{(l)}i = \left( \sum{j=1}^{s{l+1}} W^{(l)}{ji} \delta^{(l+1)}_j \right) f'(z^{(l)}_i)$$

{译者注: $$ \begin{align} \delta^{(n_l-1)}i &=\frac{\partial}{\partial z^{n_l-1}i}J(W,b;x,y) = \frac{\partial}{\partial z^{n_l-1}i}\frac{1}{2} \left|y - h{W,b}(x)\right|^2 = \frac{\partial}{\partial z^{n_l-1}i}\frac{1}{2} \sum{j=1}^{S{n_l}}(y_j-a_j^{(n_l)})^2 \ &= \frac{1}{2} \sum{j=1}^{S_{n_l}}\frac{\partial}{\partial z^{n_l-1}i}(y_j-a_j^{(n_l)})^2 = \frac{1}{2} \sum{j=1}^{S_{n_l}}\frac{\partial}{\partial z^{n_l-1}i}(y_j-f(z_j^{(n_l)}))^2 \ &= \sum{j=1}^{S_{n_l}}-(y_j-f(z_j^{(n_l)})) \cdot \frac{\partial}{\partial z_i^{(n_l-1)}}f(z_j^{(n_l)}) = \sum_{j=1}^{S_{n_l}}-(y_j-f(z_j^{(n_l)})) \cdot f'(z_j^{(n_l)}) \cdot \frac{\partial z_j^{(n_l)}}{\partial z_i^{(n_l-1)}} \ &= \sum_{j=1}^{S_{n_l}} \delta_j^{(n_l)} \cdot \frac{\partial z_j^{(n_l)}}{\partial z_i^{n_l-1}} = \sum_{j=1}^{S_{n_l}} \left(\delta_j^{(n_l)} \cdot \frac{\partial}{\partial z_i^{n_l-1}}\sum_{k=1}^{S_{n_l-1}}f(z_k^{n_l-1}) \cdot W_{jk}^{n_l-1}\right) \ &= \sum_{j=1}^{S_{n_l}} \delta_j^{(n_l)} \cdot W_{ji}^{n_l-1} \cdot f'(z_i^{n_l-1}) = \left(\sum_{j=1}^{S_{n_l}}W_{ji}^{n_l-1}\delta_j^{(n_l)}\right)f'(z_i^{n_l-1}) \end{align}$$

将上式中的$n_l-1$与$n_l$的关系替换为$l$与$l+1$的关系,就可以得到:$\delta^{(l)}i = \left( \sum{j=1}^{s_{l+1}} W^{(l)}_{ji} \delta^{(l+1)}_j \right) f'(z^{(l)}_i)$ 以上逐次从后向前求导的过程即为“反向传导”的本意所在。 计算我们需要的偏导数,计算方法如下:

$$ \begin{align} \frac{\partial}{\partial W_{ij}^{(l)}} J(W,b; x, y) &= a^{(l)}j \delta_i^{(l+1)} \ \frac{\partial}{\partial b{i}^{(l)}} J(W,b; x, y) &= \delta_i^{(l+1)}. \end{align}$$

最后,我们用矩阵-向量表示法重写以上算法。我们使用“$\bullet$” 表示向量乘积运算符,也称作阿达马乘积。若$a = b \bullet c$,则$a_i = b_ic_i$。在上一个教程中我们扩展了$f(\cdot)$的定义,使其包含向量运算,这里我们也对偏导数$f'(\cdot)$也做了同样的处理(于是又有$f'([z_1, z_2, z_3]) = [f'(z_1), f'(z_2), f'(z_3)] )$。

那么,反向传播算法可表示为以下几个步骤: 进行前馈传导计算,利用前向传导公式,得到$L_2, L_3, \ldots$直到输出层$L_{n_l}$的激活值。 对输出层(第$n_l$层),计算:

$$\begin{align} \delta^{(n_l)} = - (y - a^{(n_l)}) \bullet f'(z^{(n_l)}) \end{align}$$ 对于$l = n_l-1, n_l-2, n_l-3, \ldots, 2$的各层,计算: $$\begin{align} \delta^{(l)} = \left((W^{(l)})^T \delta^{(l+1)}\right) \bullet f'(z^{(l)}) \end{align}$$ 计算最终需要的偏导数值: $$\begin{align} \nabla_{W^{(l)}} J(W,b;x,y) &= \delta^{(l+1)} (a^{(l)})^T, \\ \nabla_{b^{(l)}} J(W,b;x,y) &= \delta^{(l+1)}. \end{align}$$

实现中应注意:在以上的第2步和第3步中,我们需要为每一个$i$值计算其$f'(z^{(l)}_i)$。假设$f(z)$是sigmoid函数,并且我们已经在前向传导运算中得到了$a^{(l)}_i$。那么,使用我们早先推导出的$f'(z)$表达式,就可以计算得到$f'(z^{(l)}_i) = a^{(l)}_i (1- a^{(l)}_i)$。

最后,我们将对梯度下降算法做个全面总结。在下面的伪代码中,$\Delta W^{(l)}$是一个与矩阵$W^{(l)}$维度相同的矩阵,$\Delta b^{(l)}$是一个与$b^{(l)}$维度相同的向量。注意这里 “$\Delta W^{(l)}$” 是一个矩阵,而不是“$\Delta$与$W^{(l)}$相乘”。下面,我们实现批量梯度下降法中的一次迭代:

  1. 对于所有$l$,令$\Delta W^{(l)} := 0 , \Delta b^{(l)} := 0$(设置为全零矩阵或全零向量)

  2. 对于$i = 1$到$m$,

    a. 使用反向传播算法计算$\nabla_{W^{(l)}} J(W,b;x,y)$和$\nabla_{b^{(l)}} J(W,b;x,y)$。

    b. 计算$\Delta W^{(l)} := \Delta W^{(l)} + \nabla_{W^{(l)}} J(W,b;x,y)$。

    c. 计算$\Delta b^{(l)} := \Delta b^{(l)} + \nabla_{b^{(l)}} J(W,b;x,y)$。

  3. 更新权重参数: $$\begin{align} W^{(l)} &= W^{(l)} - \alpha \left[ \left(\frac{1}{m} \Delta W^{(l)} \right) \right] \ b^{(l)} &= b^{(l)} - \alpha \left[\frac{1}{m} \Delta b^{(l)}\right] \end{align}$$ 现在,我们可以重复梯度下降法的迭代步骤来减小代价函数$J(W,b)$的值,进而求解我们的神经网络。

神经网络优化

交叉熵代价函数(The cross-entropy cost function

  1. 神经网络学习很慢的含义?

    学习慢 => 偏导数$∂C/∂w$和$∂C/∂b$值小。

  2. 交叉熵的基本定义

    引入交叉熵代价函数就是为了解决学习慢的问题。交叉熵代价函数的定义如下: $$E=-\frac{1}{n}\sum_xy\ln a-(1-y)\ln(1-a)$$

将交叉熵看作代价函数,是基于它的以下两个特性:

(1). 它是非负的。

(2). 如果对于所有的训练输入$x$,神经元实际的输出接近目标值,那么交叉熵将接近0。 相比于二次代价函数,交叉熵还有一个特性可以避免学习速度下降的问题。

  1. 为什么交叉熵代价函数代价函数可以解决学习慢的问题?

因为交叉熵函数关于权重和偏置的偏导数的表达式中不存在$σ′(z)$这样的项,从而避免了学习缓慢。具体分析如下: 二次函数关于权重和偏置的偏导数分别是: $$\begin{align} \frac{\partial E}{∂w}&=(a-y) \sigma^′(z)x \ \frac{\partial E}{∂b}&=(a-y) \sigma^′(z) \end{align}$$ 而$σ$函数的图像在神经元的输出接近$1$的时候,曲线变得相当平,所以$σ′(z)$就很小了。上述公式也告诉我们$∂C/∂w$和 $∂C/∂b$值会非常小。这其实就是学习缓慢的原因所在。

交叉熵函数关于权重和偏置的偏导数分别是: $$\begin{align} \frac{\partial E}{∂w_j}&=\frac{1}{n}\sum_xx_j((a-y) \sigma(z)) \ \frac{\partial E}{∂b}&=\frac{1}{n}\sum_x((a-y)\sigma(z)) \end{align}$$ 上述公式表明权重学习的速度受到$σ(z)-y$,也就是输出中的误差的控制。同时交叉熵函数还避免了像在二次代价函数中类似$σ^′(z)$导致的学习缓慢。

  1. 学习率的选择

不同的代价函数应该搭配不同的学习率。

  1. 在什么时候用交叉熵来替换二次代价函数?

如果在输出神经元是S 型神经元时,交叉熵一般都是更好的选择。 如果输出神经元是线性的那么二次代价函数不再会导致学习速度下降的问题。在此情形下,二次代价函数就是一种合适的选择。

柔性最大值(softmax)

另外一种解决学习缓慢问题的方法。

柔性最大值的想法其实就是为神经网络定义一种新式的输出层。

  1. 基本原理

    (1). 首先计算带权输入 $$Z_j^L=\sum_k w_{jk}^La_k^{L-1}+b_j^L$$

    (2). 不在带权输入z上使用S型函数来获得输出,而是使用softmax函数来获得输出。

    $$a_j^L = \frac{e^{z_j^L}}{\sum_ke^{z_k^L}} \cdots\cdots(1)$$ 其中,分母中的求和是在所有的输出神经元上进行的。另外一个特性:根据定义,输出的激活值加起来正好为1。

    $$\sum_ja_j^L = \frac{\sum_je^{z_j^L}}{\sum_ke^{z_k^L}}\cdots\cdots(2)$$ 由公式(1)(2),我们看到柔性最大值层的输出是一些相加为1正数的集合。换言之,柔性最大值层的输出可以被看做是一个概率分布。在很多问题中,使用softmax是很方便的。比如在MNIST分类问题中,我们可以将输出层第j个神经元的激活值解释成网络估计正确数字分类为j的概率。

  2. softmax如何解决学习缓慢的问题? 先定义一个对数似然(log-likelihood)代价函数。对数似然函数满足我们期待的代价函数的条件。对数似然代价函数关于权重和偏置的偏导数分别是:这些方程其实和之前的交叉熵得到的类似。只是之前的是平均值。正如前面的分析,这些表达式确保我们不会遇到学习缓慢的问题。事实上,把一个具有对数似然代价的柔性最大值输出层,看作与一个具有交叉熵代价的S型输出层非常相似,这是很有用的。

  3. 应该使用一个具有交叉熵代价的S 型输出层,还是一个具有对数似然代价的柔性最大值输出层呢? 实际上,在很多应用场景中,这两种方式的效果都不错。 柔性最大值加上对数似然的组合更加适用于那些需要将输出激活值解释为概率的场景。

过度拟合(Overfitting)

  1. 检测过度拟合

我们在每个迭代期的最后都计算在validation_data 上的分类准确率。一旦分类准确率已经饱和,就停止训练。这个策略被称为提前停止。

  1. 降低过度拟合

(1). 一般来说,最好的降低过度拟合的方式之一就是增加训练样本的量。有了足够的训练数据,就算是一个规模非常大的网络也不大容易过度拟合。不幸的是,训练数据其实是很难或者很昂贵的资源,所以这不是一种太切实际的选择。

(2). 降低网络规模。但是更深层更大的网络潜在有更强的学习能力。

(3). 规范化。即使对于固定的神经网络和固定的训练集, 仍然可以减少overfitting。

正则化/规范化(regularization)

  1. 基本原理

规范化有很多技术,这里给出一种最为常用的规范化手段—— 有时候被称为权重衰减(weight decay)或者L2 规范化。 L2 规范化的想法是增加一个额外的项到代价函数上,这个项叫做规范化项。 $$ J(W,b)= \left[ \frac{1}{m} \sum_{i=1}^m \left( \frac{1}{2} \left| h_{W,b}(x^{(i)}) - y^{(i)} \right|^2 \right) \right] + \frac{\lambda}{2} \sum_{l=1}^{n_l-1} ; \sum_{i=1}^{s_l} ; \sum_{j=1}^{s_{l+1}} \left( W^{(l)}_{ji} \right)^2 $$

以上关于$J(W,b)$定义中的第一项是一个均方差项。第二项是一个规则化项(也叫权重衰减项),其目的是减小权重的幅度,防止过度拟合。

[注:通常权重衰减的计算并不使用偏置项$b^{(l)}_i$,比如我们在$J(W, b)$的定义中就没有使用。一般来说,将偏置项包含在权重衰减项中只会对最终的神经网络产生很小的影响。如果你在斯坦福选修过CS229(机器学习)课程,或者在YouTube上看过课程视频,你会发现这个权重衰减实际上是课上提到的贝叶斯规则化方法的变种。在贝叶斯规则化方法中,我们将高斯先验概率引入到参数中计算MAP(极大后验)估计(而不是极大似然估计)。]

权重衰减参数$\lambda$用于控制公式中两项的相对重要性。在此重申一下这两个复杂函数的含义:$J(W,b;x,y)$是针对单个样例计算得到的方差代价函数;$J(W,b)$是整体样本代价函数,它包含权重衰减项。

含有权重衰减项的出整体代价函数$J(W,b)$的偏导数: $$ \begin{align} \frac{\partial}{\partial W_{ij}^{(l)}} J(W,b) &= \left[ \frac{1}{m} \sum_{i=1}^m \frac{\partial}{\partial W_{ij}^{(l)}} J(W,b; x^{(i)}, y^{(i)}) \right] + \lambda W_{ij}^{(l)} \ \frac{\partial}{\partial b_{i}^{(l)}} J(W,b) &= \frac{1}{m}\sum_{i=1}^m \frac{\partial}{\partial b_{i}^{(l)}} J(W,b; x^{(i)}, y^{(i)}) \end{align}$$ 以上两行公式稍有不同,第一行比第二行多出一项,是因为权重衰减是作用于$W$而不是$b$。

含有权重衰减项的权重参数更新: $$\begin{align} W^{(l)} &= W^{(l)} - \alpha \left[ \left(\frac{1}{m} \Delta W^{(l)} \right) + \lambda W^{(l)}\right] \ b^{(l)} &= b^{(l)} - \alpha \left[\frac{1}{m} \Delta b^{(l)}\right] \end{align}$$ 规范化的效果是让网络倾向于学习小一点的权重。 规范化可以当做一种寻找小的权重和最小化原始的代价函数之间的折中。由$λ$的取值决定,$λ$越小,就偏向于最小化原始代价函数,反之,倾向于小的权重。

  1. 好处

(1)减轻过度拟合和提高分类准确率。

(2)规范化的网络能够提供更容易复制的结果。无规范化的网络会偶然被限制住,不同的运行会给出相差很大的结果。

  1. 为何规范化可以帮助减轻过度拟合?

规范化的神经网络常常能够比非规范化的泛化能力更强,这只是一种实验事实(empirical fact)。目前还没有一整套具有说服力的理论解释。仅仅是一些不完备的启发式规则或者经验。

  1. 正则化的其他技术

    (1)L1 规范化:是在未规范化的代价函数上加上一个权重绝对值的和。

    (2)弃权(Dropout):从随机(临时)地删除网络中的一半的隐藏神经元开始,同时让输入层和输出层的神经元保持不变。

    (3)人为增加训练样本

权重初始化(Weight initialization)

理解这部分需要先弄明白正态分布(高斯分布)、均值、标准差、方差的意义。

结论:假设我们有一个有$n$个输入权重的神经元,我们会使用均值$u=0$,标准差$\epsilon= 1/sqrt(n)$的正态随机分布初始化这些权重。

原因:若这样初始化的话,那么大部分带权输入$z$的取值都在1和-1之间,隐藏神经元的输出$σ(z)$就不太会接近1或者0。也就是神经元没有饱和,学习过程不会被减慢。

参考资料

UFLDL教程-神经网络

UFLDL教程-反向传导算法

Improving the way neural networks learn

神经网络与深度学习(4):改进神经网络的学习方法