机器学习笔记5 神经网络2 参数学习

Andrew Ng cs229 Machine Learning 笔记

成本函数(Cost Function)

以下是我们会用到的一些变量:

  • $L$表示神经网络的层数
  • $s_l$表示第$l$层的神经单元数(不包括偏差(bias)单元)
  • $K$表示输出单元数(分类数)

当有多个输出类别时,采用$h_\Theta(x)_k$表示第$k$个输出的假设结果。

神经网络的成本函数是logistic回归中的成本函数更普遍的一种形式。

logistic回归中的成本函数为:

$$J(\theta) = -\frac{1}{m} \left[ \sum_{i=1}^m y^{(i)}\log(h_{\theta}) + (1-y^{(i)}) \log(1-h_{\theta}(x^{(i)})) \right] + \frac{\lambda}{2m} \sum_{j=1}^n \theta_j^2$$

神经网络的成本函数稍微复杂一点:

$$\begin{gather*} J(\Theta) = - \frac{1}{m} \left[ \sum_{i=1}^m \sum_{k=1}^K y^{(i)}_k \log ((h_\Theta (x^{(i)}))_k) + (1 - y^{(i)}_k)\log (1 - (h_\Theta(x^{(i)}))_k)\right] + \frac{\lambda}{2m}\sum_{l=1}^{L-1} \sum_{i=1}^{s_l} \sum_{j=1}^{s_{l+1}} ( \Theta_{j,i}^{(l)})^2 \end{gather*}$$

和logistic回归相比,第一个方括号内多了一层累加求和,即对多类输出节点的成本函数进行累加,会遍历所有的输出节点。

正则化的部分则是将每一层的参数都考虑了进去(包括偏差单元相关的参数值)。和logistic回归一样,每一项都进行了平方。

注意:

  • 双层累加中对于输出层所有单元的logistic回归的成本函数进行求和
  • 三层累加中则是对于整个神经网络中单独的$\Theta$参数的平方进行求和
  • 三层累加中的$i$和训练集中的$i$并不一样

向后传播(Backpropagation)算法

向后传播是神经网络中表示最小化成本函数的术语,就像logistic回归和线性回归中的梯度下降(gradient descent)一样。

我们的目标是计算:

$$\min_\Theta J(\Theta)$$

即我们想最小化成本函数$J$,得到最优化参数$\Theta$。

观察我们用于计算$J(\Theta)$偏导的等式:

$$\dfrac{\partial}{\partial \Theta_{i,j}^{(l)}}J(\Theta)$$

在向后传播中我们需要对每个节点计算:

$$\delta_j^{(l)} \text{=第} l \text{层的节点}j \text{的误差}$$

回忆一下,$a_j^{(i)}$表示第$l$层的节点$j$的激活结果。对于最后一层,误差的计算为:

$$\large \delta^{(L)} = a^{(L)} - y$$

其中,$L$表示层数,$a^{(L)}$是最后一层激活单元的向量化表示。因此对于最后一层,误差的计算就是简单的真实结果和预测结果的差值。

为了得到除了最后一层以外其他层的误差值,我们采用以下等式从右往左地向后计算:

$$\delta^{(l)} = ((\Theta^{(l)})^T \delta^{(l+1)})\ .*\ g'(z^{(l)})$$

也就是用$\Theta$去乘后一层的误差值,再对每一个元素乘上$g’$,也就是激活函数$g$输入值为$z^{(l)}$时的导数。

$g’$也可以写成:

$$g'(z^{(l)}) = a^{(l)}\ .*\ (1 - a^{(l)})$$

那么,对于内部节点来说,完整的向后传播计算等式为:

$$\delta^{(l)} = ((\Theta^{(l)})^T \delta^{(l+1)})\ .*\ a^{(l)}\ .*\ (1 - a^{(l)})$$

其中,证明比较复杂,不过实现向后传播的算法也不用知道证明的细节。

对于每个训练样本$t$,可以采用激活值和误差值来计算偏导项:

$$\dfrac{\partial J(\Theta)}{\partial \Theta_{i,j}^{(l)}} = \frac{1}{m}\sum_{t=1}^m a_j^{(t)(l)} {\delta}_i^{(t)(l+1)}$$

上述式子忽略了正则项,后面会再详细说明。

注意,其中$\delta^{l+1}$和$a^{l+1}$都是有$s_{l+1}$个元素的向量。类似地,$a^{(l)}$是有$s_l$个元素的向量。这两个向量相乘会产生和$\Theta^{(l)}$同样维度的$s_{l+1} * s_l$的矩阵。这个计算过程也就是得到了$\Theta^{(l)}$中每个元素的梯度项。

现在,将以上过程串起来,我们得到整个向后传播算法:

  • 给定训练集$\lbrace (x^{(1)}, y^{(1)}) \cdots (x^{(m)}, y^{(m)})\rbrace$
  • 设$\lbrace (x^{(1)}, y^{(1)}) \cdots (x^{(m)}, y^{(m)})\rbrace \forall (l,i,j)$
  • 对于每个训练集 $\text{for } t = 1 \text{ to } m$:
    • $a^{(1)} := x^{(t)}$
    • 采用向前传播算法计算$a^{(l)}, l = 2,3,…,l$
    • 计算$\delta^{(L)} = a^{(L)} - y^{(t)}$
    • 计算$\delta^{(L-1)}, \delta^{(L-2)},\dots,\delta^{(2)}$
      $$\delta^{(l)} = ((\Theta^{(l)})^T \delta^{(l+1)}) .* a^{(l)} .* (1 - a^{(l)})$$
    • $\Delta^{(l)}_{i,j} := \Delta^{(l)}_{i,j} + a_j^{(l)} \delta_i^{(l+1)}$,向量运算表示为:
      $$\Delta^{(l)} := \Delta^{(l)} + \delta^{(l+1)}(a^{(l)})^T$$
  • $D^{(l)}_{i,j} := \dfrac{1}{m}\left(\Delta^{(l)}_{i,j} + \lambda\Theta^{(l)}_{i,j}\right)$s
  • $D^{(l)}_{i,j} := \dfrac{1}{m}\Delta^{(l)}_{i,j}$

$D^{(l)}_{i,j}$即最后我们所求的偏导。

向后传播的直观理解

成本函数为:

$$ \begin{gather*} J(\theta) = - \frac{1}{m} \left[ \sum_{t=1}^m \sum_{k=1}^K y^{(t)}_k \ \log (h_\theta (x^{(t)}))_k + (1 - y^{(t)}_k)\ \log (1 - h_\theta(x^{(t)})_k)\right] + \frac{\lambda}{2m}\sum_{l=1}^{L-1} \sum_{i=1}^{s_l} \sum_{j=1}^{s_l+1} ( \theta_{j,i}^{(l)})^2 \end{gather*} $$

如果我们只考虑一个训练样本$(t=1)$,并且忽略正则项,那么成本函数为:

$$cost(t) =y^{(t)} \ \log (h_\theta (x^{(t)})) + (1 - y^{(t)})\ \log (1 - h_\theta(x^{(t)}))$$

直观上可以将以上的等式近似看作:

$$cost(t) \approx (h_\theta(x^{(t)})-y^{(t)})^2$$

$\delta_j^{(l)}$是$a_j^{(l)}$的误差。

严格来说,$\delta$值实际上是成本函数的偏导:

$$\delta_j^{(l)} = \dfrac{\partial}{\partial z_j^{(l)}} cost(t)$$

注意偏导是成本函数切线的斜率,斜率越陡峭越不准确。

梯度检查(Gradient Checking)

梯度检查能够保证我们的向后传播算法的正确性。

我们可以用以下方法近似地估算成本函数的偏导:

$$\dfrac{\partial}{\partial\Theta}J(\Theta) \approx \dfrac{J(\Theta + \epsilon) - J(\Theta - \epsilon)}{2\epsilon}$$

$\Theta$是很多个矩阵构成,可以对$\Theta_j$的偏导进行以下估算:

$$\dfrac{\partial}{\partial\Theta_j}J(\Theta) \approx \dfrac{J(\Theta_1, \dots, \Theta_j + \epsilon, \dots, \Theta_n) - J(\Theta_1, \dots, \Theta_j - \epsilon, \dots, \Theta_n)}{2\epsilon}$$

$\epsilon$的取值必须较小,才能得到接近真实的值。但如果$\epsilon$的值太小,计算可能会有精度问题而无法得到正确值。Andrew给的经验值时$\epsilon = 10^{-4}$。

如果可以验证梯度近似值和$\delta$大致相等,那么向后传播算法是正确的。在真正计算中不需要计算梯度近似值,因为其计算非常慢。

随机初始化

在神经网络中,不能将$\theta$权重初始化为0,否则在向后传播时,所有的节点会重复更新一样的值。

因此需要随机初始化权重:

将$\Theta_{ij}^{(l)}$赋为$[-\epsilon,\epsilon]$范围内的一个随机数:

$$\epsilon = \dfrac{\sqrt{6}}{\sqrt{\mathrm{Loutput} + \mathrm{Linput}}}$$
$$\Theta^{(l)} = 2 \epsilon \; \mathrm{rand}(\mathrm{Loutput}, \mathrm{Linput} + 1) - \epsilon$$

其中,$Loutput$和$Linput+1$是$\Theta$参数的维度。这里的$\epsilon$和梯度检查中的$\epsilon$没有关系。

神经网络总结

首先,选择神经网络的结构,确定神经网络的层数和每层的隐藏单元的个数。

  • 输入层单元数等于特征$x^(i)$的维度
  • 输出层的单元数等于分类个数
  • 默认设置:1个隐藏层。如果有多于1个隐藏层,则隐藏层的单元个数都一样多。

训练神经网络

  1. 随机初始化权重
  2. 实现向前传播计算$h_{\theta}(x^{(i)})$
  3. 实现成本函数
  4. 实现向后传播计算偏导值
  5. 采用梯度检查来确认向后传播的正确性后,再取消梯度检查。
  6. 采用梯度下降或其他已有的最优化函数来最小化成本函数,得到$\theta$权重值。

对于每个训练样本都循环采用向前和向后传播算法:

for i = 1:m,
   Perform forward propagation and backpropagation using example (x(i),y(i))
   (Get activations a(l) and delta terms d(l) for l = 2,...,L