吴恩达机器学习:神经网络 | 反向传播算法

上一周咱们学习了 神经网络 | 多分类问题。咱们分别使用 逻辑回归神经网络 来解决多分类问题,并了解到在特征数很是多的状况下,神经网络是更为有效的方法。这周的课程会给出训练 神经网络 所使用的 代价函数,并使用 反向传播 算法来计算梯度。笔者会给出 反向传播 算法中重要的思路和推导,但不会包含全部的计算步骤。git

点击 课程视频 你就能不间断地学习 Ng 的课程,关于课程做业的 Python 代码已经放到了 Github 上,点击 课程代码 就能去 Github 查看( 没法访问 Github 的话能够点击 Coding 查看 ),代码中的错误和改进欢迎你们指出。github

如下是 Ng 机器学习课程第四周的笔记。算法

代价函数

假设咱们的多分类问题有 K 个分类,神经网络共有 L 层,每一层的神经元个数为 s_l,那么神经网络的 代价函数 为:网络

J(\Theta)= -\frac{1}{m}\sum\limits_{i=1}^{m}\sum\limits_{k=1}^{K}\Big(y_k^{(i)}log\big(h_\Theta(x^{(i)})\big)_k+(1-y_k^{(i)})log\big(1-\big(h_\Theta(x^{(i)})\big)_k\big)\Big) \\
+ \frac{\lambda}{2m}\sum\limits_{l=1}^{L-1}\sum\limits_{i=1}^{s_l}\sum\limits_{j=1}^{s_{l+1}}\big(\Theta_{ji}^{(l)}\big)^2

其中的第二项为 正则化 项,是网络中全部权值的平方和。第一项与逻辑回归中的 代价函数 相似,但这里咱们须要累加全部输出神经元的偏差。app

梯度计算

为了可以使用 梯度降低 算法来训练网络,咱们须要计算代价函数的梯度。一种很直观的方法就是使用数值计算,对于某个 \Theta_{ij},给它加上减去一个很小的量 \epsilon 来计算梯度:机器学习

\frac{\partial J(\theta)}{\partial\theta_j} \approx \frac{J(\theta_1,\cdots,\theta_j+\epsilon,\cdots,\theta_n)-J(\theta_1,\cdots,\theta_j-\epsilon,\cdots,\theta_n)}{2\epsilon}

但稍微分析一下算法的复杂度就能知道,这样的方法十分缓慢。对于每一组数据,咱们须要计算全部权值的梯度,**总的计算次数 = 训练数据个数 x 网络权值个数 x 前向传播计算次数 **。在一般状况下这样的复杂度是没法接受的,因此咱们仅使用这个方法来验证 反向传播 算法计算的梯度是否正确。ide

链式法则

为了可以理解以后对于 反向传播 公式的推导,咱们首先要了解一个关于多元复合函数求导的 链式法则。对于多元函数 z=f(u,v),其中 u=h(x,y)v=g(x,y),那么:函数

\frac{\partial z}{\partial x} = \frac{\partial z}{\partial u}\frac{\partial u}{\partial x} + \frac{\partial z}{\partial v}\frac{\partial v}{\partial x} \\
\frac{\partial z}{\partial y} = \frac{\partial z}{\partial u}\frac{\partial u}{\partial y} + \frac{\partial z}{\partial v}\frac{\partial v}{\partial y}

链式法则 告诉咱们有多个层次的多元复合函数,下一层次的导数能够由上一层次推得。学习

上图中笔者有意多加了一层,这里 pu,v 的函数, qu,v 的函数, zp,q 的函数。对于要计算的 \frac{\partial z}{\partial x}\frac{\partial z}{\partial y},上式仍成立,缘由是咱们能够把 z 看做 u,v 的函数。这至关于咱们把:

\frac{\partial z}{\partial x} = \frac{\partial z}{\partial p} \frac{\partial p}{\partial u} \frac{\partial u}{\partial x} +
\frac{\partial z}{\partial p} \frac{\partial p}{\partial v} \frac{\partial v}{\partial x} +
\frac{\partial z}{\partial q} \frac{\partial q}{\partial u} \frac{\partial u}{\partial x} +
\frac{\partial z}{\partial q} \frac{\partial q}{\partial v} \frac{\partial v}{\partial x}

简化为了只与上一层相关,利用上一层计算完成的结果 \frac{\partial z}{\partial u}\frac{\partial z}{\partial v} 而不用从头算起:.net

\frac{\partial z}{\partial x} = \frac{\partial z}{\partial u}\frac{\partial u}{\partial x} + \frac{\partial z}{\partial v}\frac{\partial v}{\partial x}

通常的,对于函数 y,若是它能看作 z_1,z_2 \cdots,z_n 的函数,而 z_it 的函数,则:

\frac{\partial y}{\partial t} = \sum\limits_{i=1}^{n} \frac{\partial y}{\partial z_i} \frac{\partial z_i}{\partial t}

神经网络就是一个层次不少的多元函数,咱们能够隐约从 链式法则 中感受到反向传播的意味。

公式推导

为了施展 反向传播 的魔法,咱们首要要引入一个中间变量 \delta,定义为:

\delta_j^{l} = \frac{\partial J}{\partial z_j^{l}}

其中 l 为第几层,j 表示第 l 层的第几个神经元,z 为上次课程提到的中间变量( 为了让式子看上去更清晰,反向传播 中的公式上标不使用括号 )。\delta 被称为第 l 层第 j 个神经元的偏差。反向传播 就是先计算每一层每一个神经元的偏差,而后经过偏差来获得梯度的。

首先来看输出层的偏差:

\delta^L_j = \frac{\partial J}{\partial z^L_j}

对它使用 链式法则 获得:

\delta^L_j = \sum\limits_{k=1}^{K} \frac{\partial J}{\partial a^L_k} \frac{\partial a^L_k}{\partial z^L_j}

而只有当 k==j 时,右边部分才不为 0,因此:

\delta^L_j = \frac{\partial J}{\partial a^L_j} \frac{\partial a^L_j}{\partial z^L_j} = \frac{\partial J}{\partial a^L_j} g'(z_j^L)=a_j^L-y_j^L\tag{1}

对于其它层的偏差:

\delta^l_j = \frac{\partial J}{\partial z^l_j}

使用 链式法则

\delta^l_j = \sum\limits_{k=1}^{s_{l+1}} \frac{\partial J}{\partial z_k^{l+1}} \frac{\partial z_k^{l+1}}{\partial z^l_j} = \sum\limits_{k=1}^{s_{l+1}} \delta^{l+1}_k \frac{\partial z_k^{l+1}}{\partial z^l_j}

而其中:

z_k^{l+1} = \sum\limits_{p=1}^{s_l} \Theta_{kp}^{l} g(z_p^l)+b_k^{l}

求偏导得:

\frac{\partial z^{l+1}_k}{\partial z^l_j} = \Theta_{kj}^{l} g'(z^l_j)

因此:

\delta^l_j = \sum\limits_{k=1}^{s_{l+1}} \Theta_{kj}^{l} \delta^{l+1}_k g'(z^l_j) = \sum\limits_{k=1}^{s_{l+1}} \Theta_{kj}^{l} \delta^{l+1}_k a_j^l (1-a_j^l) \tag{2}

最后一样使用 链式法则 来计算:

\frac{\partial J}{\Theta_{ij}^{l}} = \sum\limits_{k=1}^{s_{l+1}} \frac{\partial J}{\partial z_k^{l+1}} \frac{\partial z_k^{l+1}}{\partial \Theta_{ij}^{l}} = \sum\limits_{k=1}^{s_{l}} \delta^{l+1}_k \frac{\partial z_k^{l+1}}{\partial \Theta_{ij}^{l}}

因为:

z_k^{l+1} = \sum\limits_{p=1}^{s_l} \Theta_{kp}^{l} g(z_p^l)+b_k^{l}

只有当 k=ip=j 时留下一项:

\frac{\partial J}{\Theta_{ij}^{l}} = g(z_j^l) \delta^{l+1}_i = a_j^l \delta^{l+1}_i \tag{3}

反向传播

有了 (1) (2) (3) 式,就能够来完成 反向传播 算法了( 须要注意的是刚才所推导的式子都是针对一组训练数据而言的 )。

  1. 对于全部的 l, i, j 初始化 \Delta_{ij}^l = 0
  2. 对于 m 组训练数据,k1 取到 m
  • a^1 = x^{(k)}
  • 前向传播,计算各层激活向量 a^{l}
  • 使用 (1) 式,计算输出层偏差 \delta^L
  • 使用 (2) 式,计算其它层偏差 \delta^{L-1},\delta^{L-2},...,\delta^{2}
  • 使用 (3) 式,累加 \Delta_{ij}^l\Delta_{ij}^l:=\Delta_{ij}^l+a_j^l\delta_i^{l+1}
  1. 计算梯度矩阵:
D^{l}_{ij} =
\begin{cases}
\dfrac{1}{m}\Delta^{l}_{ij} + \dfrac{\lambda}{m}\Theta^{l}_{ij} & \mbox{if $j \neq 0$} \\
\dfrac{1}{m}\Delta_{ij}^{l} & \mbox{if $j=0$}
\end{cases}
  1. 更新权值 \Theta^l := \Theta^l+ \alpha D^l

权值初始化

最后提一下权值的初始化。对于神经网络,不能像以前那样使用相同的 0 值来初始化,这会致使每层的 逻辑单元 都相同。所以咱们使用随机化的初始化方法,使得 -\delta \leq \Theta_{ij}^{l} \leq \delta

So~,这周学完了 神经网络 和它的学习算法,你们有没有以为很神奇呢?

相关文章
相关标签/搜索