Skip to content

Commit

Permalink
Format and fine tune.
Browse files Browse the repository at this point in the history
  • Loading branch information
zhanggyb committed Mar 21, 2016
1 parent fc8229a commit 4008efa
Show file tree
Hide file tree
Showing 3 changed files with 368 additions and 351 deletions.
93 changes: 53 additions & 40 deletions chap5.tex
Expand Up @@ -4,8 +4,8 @@ \chapter{深度神经网络为何很难训练}
\label{ch:WhyHardToTrain}

假设你是一名工程师,接到一项从头开始设计计算机的任务。某天,你在工作室工作,设计
逻辑电路,构建{\serif AND}门,{\serif OR}门等等时,老板带着坏消息进来:客户刚刚
添加了一个奇特的设计需求:整个计算机的线路的深度必须只有两层:
逻辑电路,构建{\serif AND}门,{\serif OR}门等等时,老板带着坏消息进来:客户刚刚添
加了一个奇特的设计需求:整个计算机的线路的深度必须只有两层:
\begin{center}
\includegraphics{shallow_circuit}
\end{center}
Expand All @@ -15,9 +15,9 @@ \chapter{深度神经网络为何很难训练}
老板说:“我也认为他们疯了,但是客户的需求比天大,我们要满足它。”

实际上,在某种程度上看,他们的客户并没有太疯狂。假设你可以使用某种特殊的逻辑门,
它让你对任意多的输入做{\serif AND}运算。同样也能使用多输入的{\serif NAND}门 ——
可以对多个输入做{\serif AND}运算并取负的门。有了这类特殊的门,构建出来的两层深度
的电路可以计算任何函数
它让你对任意多的输入做{\serif AND}运算。同样也能使用多输入的{\serif NAND}门~——~可
以对多个输入做{\serif AND}运算并取负的门。有了这类特殊的门,构建出来的两层深度的
电路可以计算任何函数

但是仅仅因为某件事是理论上可能的,并不代表这是一个好的想法。在实践中,在解决线路
设计问题(或者大多数的其他算法问题)时,我们通常考虑如何解决子问题,然后逐步地集
Expand Down Expand Up @@ -128,9 +128,9 @@ \section{消失的梯度问题}
('0', '1', '2', ..., 9)。

让我们训练 30 个完整的\epochs{},使用\minibatch{}大小为 10, 学习率 $\eta = 0.1$
规范化参数 $\lambda = 5.0$。在训练时,我们也会在 \lstinline!validation_data!
监控分类的准确度\footnote{注意网络可能需要花费几分钟来训练,要看你机器的速度。所以如果你
正在运行代码,你可能愿意继续阅读并稍后回来,而不是等待代码完成执行。}:
规范化参数 $\lambda = 5.0$。在训练时,我们也会在 \lstinline!validation_data! 上监
控分类的准确度\footnote{注意网络可能需要花费几分钟来训练,要看你机器的速度。所以
如果你正在运行代码,你可能愿意继续阅读并稍后回来,而不是等待代码完成执行。}:
\begin{lstlisting}[language=Python]
>>> net.SGD(training_data, 30, 10, 0.1, lmbda=5.0,
... evaluation_data=validation_data, monitor_evaluation_accuracy=True)
Expand Down Expand Up @@ -188,7 +188,9 @@ \section{消失的梯度问题}
为了让图里简单,我只展示出来最上方隐藏层上的 $6$ 个神经元。这里忽略了输入层神经元,
因为他们并不包含需要学习的权重或者偏置。同样输出层神经元也忽略了,因为这里我们做
的是层层之间的比较,所以比较相同数量的两层更加合理啦。在网络初始化后立即得到训练
前期的结果如下\footnote{绘制的数据图形由程序 \href{https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/fig/generate_gradient.py}{\lstinline!generate_gradient.py!}
前期的结果如下\footnote{绘制的数据图形由程
\href{https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/fig/generate_gradient.py}{\lstinline!generate_gradient.py!}
生成。同样的程序也用来生成本节后面引用的结果。}:
\begin{center}
\includegraphics{initial_gradient}
Expand All @@ -208,10 +210,10 @@ \section{消失的梯度问题}
实比第一层要快。

如果我们添加更多的隐藏层呢?如果我们有三个隐藏层,比如说在一个 $[784, 30, 30,
10]$ 的网络中,那么对应的学习速度就是 $0.012, 0.060, 0.283$这里前面的隐藏
层学习速度还是要低于最后的隐藏层。假设我们增加另一个包含 30 个隐藏神经元的隐藏层。
那么,对应的学习速度就是:$0.003, 0.017, 0.070, 0.285$。还是一样的模式:前面的
层学习速度低于后面的层
10]$ 的网络中,那么对应的学习速度就是 $0.012, 0.060, 0.283$这里前面的隐藏层学习
速度还是要低于最后的隐藏层。假设我们增加另一个包含 30 个隐藏神经元的隐藏层。那么,
对应的学习速度就是:$0.003, 0.017, 0.070, 0.285$。还是一样的模式:前面的层学习速
度低于后面的层

现在我们已经看到了训练开始时的学习速度,这是刚刚初始化之后的情况。那么这个速度会
随着训练的推移发生什么样的变化呢?让我们看看只有两个隐藏层。学习速度变化如下:
Expand Down Expand Up @@ -247,11 +249,16 @@ \section{消失的梯度问题}
时候梯度倾向于变小。这意味着在前面的隐藏层中的神经元学习速度要慢于后面的隐藏层。
这儿我们只在一个网络中发现了这个现象,其实在多数的神经网络中存在着更加根本的导致
这个现象出现的原因。这个现象也被称作是\emph{消失的梯度问题\index{消失的梯度问
题}(vanishing gradient problem)}\footnote{参见 \href{http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7321}{Gradient flow in recurrent
nets: the difficulty of learning long-term dependencies},作者为 Sepp Hochreiter,
Yoshua Bengio, Paolo Frasconi, 和 Jürgen Schmidhuber (2001)。这篇论文
研究了递归神经网络,但是其本质现象和我们正在研究的前馈网络中的是一样的。还可看看 Sepp Hochreiter
的早期的学位论文,\href{http://www.idsia.ch/~juergen/SeppHochreiter1991ThesisAdvisorSchmidhuber.pdf}{Untersuchungen zu dynamischen neuronalen Netzen} (1991,德语)。}。
题}(vanishing gradient
problem)}\footnote{参见
\href{http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7321}{Gradient
flow in recurrent nets: the difficulty of learning long-term dependencies},
作者为 Sepp Hochreiter,Yoshua Bengio, Paolo Frasconi, 和 Jürgen
Schmidhuber (2001)。这篇论文研究了递归神经网络,但是其本质现象和我们正在研究
的前馈网络中的是一样的。还可看看 Sepp Hochreiter的早期的学位论
文,
\href{http://www.idsia.ch/~juergen/SeppHochreiter1991ThesisAdvisorSchmidhuber.pdf}{Untersuchungen
zu dynamischen neuronalen Netzen} (1991,德语)。}。

为何消失的梯度问题会出现呢?我们可以通过什么方式避免它?还有在训练深度神经网络时
如何处理好这个问题?实际上,这个问题是可以避免的,尽管替代方法并不是那么有效,同
Expand All @@ -274,15 +281,16 @@ \section{消失的梯度问题}
络,我们需要弄清楚如何解决消失的梯度问题。

\section{什么导致了消失的梯度问题?深度神经网络中的梯度不稳定性}
\label{sec:what_is_causing_the_vanishing_gradient_problem_unstable_gradients_in_deep_neural_nets}

为了弄清楚为何会出现消失的梯度,来看看一个极简单的深度神经网络:每一层都只有一个
单一的神经元。下图就是有三层隐藏层的神经网络:
\begin{center}
\includegraphics{tikz37}
\end{center}

这里,$w_1, w_2, ...$ 是权重,而 $b_1, b_2, ...$ 是偏置,$C$ 则是某个代价函数。回
顾一下,从第 $j$ 个神经元的输出 $a_j = \sigma(z_j)$,其中 $\sigma$ 是通常
这里,$w_1, w_2, \ldots$ 是权重,而 $b_1, b_2, \ldots$ 是偏置,$C$ 则是某个代价函
数。回顾一下,从第 $j$ 个神经元的输出 $a_j = \sigma(z_j)$,其中 $\sigma$ 是通常
\hyperref[sigmoid_neurons]{S 型激活函数},而 $z_j = w_j * a_{j-1} + b_j$ 是神
经元的带权输入。我已经在最后表示出了代价函数 $C$ 来强调代价是网络输出 $a_4$ 的函
数:如果实际输出越接近目标输出,那么代价会变低;相反则会变高。
Expand All @@ -302,8 +310,8 @@ \section{什么导致了消失的梯度问题?深度神经网络中的梯度
的每个项置于了对应的位置。所以网络本身就是表达式的解读。

你可以直接认可这个表达式,直接跳到该表达式如何关联于小时的梯度问题的。这对理解没
有影响,因为实际上上面的表达式只是前面对于BP 的讨论的特例。但是也包含了一个表达式
正确的解释,所以去看看那个解释也是很有趣的(也可能更有启发性吧)。
有影响,因为实际上上面的表达式只是前面对于反向传播的讨论的特例。但是也包含了一个
表达式正确的解释,所以去看看那个解释也是很有趣的(也可能更有启发性吧)。

假设我们对偏置 $b_1$ 进行了微小的调整 $\Delta b_1$。这会导致网络中剩下的元素一系
列的变化。首先会对第一个隐藏元输出产生一个 $\Delta a_1$ 的变化。这样就会导致第二
Expand Down Expand Up @@ -444,10 +452,10 @@ \subsection*{问题}
(3)数值上说明上述表达式在 $|w| ~= 6.9$ 时候去的最高值约
$0.45$。所以即使每个条件都满足,我们仍然有一个狭窄的输入激活区间,这样来避免消
失的梯度问题。
\item \textbf{幺神经元:}\label{identity_neuron} 考虑一个单一输入的神经元,$x$对应的权重 $w_1$,偏
$b$,输出上的权重 $w_2$。证明,通过合理选择权重和偏差,我们可以确保 $w_2
\sigma(w_1*x +b)~=x$ 其中
$x \in [0, 1]$。这样的神经元可用来作为幺元使用,输出和输入相同(成比例
\item \textbf{幺神经元:}\label{identity_neuron} 考虑一个单一输入的神经元,$x$
对应的权重 $w_1$,偏差 $b$,输出上的权重 $w_2$。证明,通过合理选择权重和偏差,
我们可以确保 $w_2 \sigma(w_1*x +b)~=x$
其中$x \in [0, 1]$。这样的神经元可用来作为幺元使用,输出和输入相同(成比例
)。\emph{提示:可以重写 $x = 1/2 + \Delta$,可以假设 $w_1$ 很小,和在 $w_1 *
\Delta$ 使用泰勒级数展开}。
\end{itemize}
Expand Down Expand Up @@ -486,20 +494,25 @@ \section{其它深度学习的障碍}
究集中在更好地理解在训练深度神经网络时遇到的挑战。这里我不会给出一个详尽的总结,
仅仅想要给出一些论文,告诉你人们正在寻觅探究的问题。

首先,在 2010 年 Glorot 和 Bengio\footnote{\href{http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf}{Understanding the difficulty of
training deep feedforward neural networks},作者为 Xavier Glorot 和 Yoshua Bengio
(2010)。还可看看 \href{http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf}{Efficient
BackProp} 论文中前面的关于 S 型函数的讨论,作者为 Yann LeCun, Léon Bottou, Genevieve Orr 和 Klaus-Robert Müller
(1998)。} 发现证据表明 sigmoid 函数的选择会导致训练网络的问题。特别地,他们发
现 sigmoid 函数会导致最终层上的激活函数在训练中会聚集在 $0$,这也导致了学习的缓慢。
他们的工作中提出了一些取代 sigmoid 函数的激活函数选择,使得不会被这种聚集性影响性
能。

第二个例子,在 2013 年 Sutskever, Martens, Dahl 和 Hinton\footnote{\href{http://www.cs.toronto.edu/~hinton/absps/momentum.pdf}{On the
importance of initialization and momentum in deep learning},作者为 Ilya Sutskever,
James Martens, George Dahl 和 Geoffrey Hinton (2013)。} 研究了深度学习使用随机
权重初始化和基于 $momentum$$SGD$ 方法。两种情形下,好的选择可以获得较大的差异
的训练效果。
首先,
在 2010 年 Glorot 和
Bengio\footnote{\href{http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf}{Understanding
the difficulty of training deep feedforward neural networks},作者为 Xavier
Glorot 和 Yoshua Bengio(2010)。还可看
\href{http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf}{Efficient
BackProp} 论文中前面的关于 S 型函数的讨论,作者为 Yann LeCun, Léon
Bottou, Genevieve Orr 和 Klaus-Robert Müller(1998)。} 发现证据表明 sigmoid
函数的选择会导致训练网络的问题。特别地,他们发现 sigmoid 函数会导致最终层上的激活
函数在训练中会聚集在 $0$,这也导致了学习的缓慢。他们的工作中提出了一些取
代 sigmoid 函数的激活函数选择,使得不会被这种聚集性影响性能。

第二个例子,在 2013 年 Sutskever, Martens,
Dahl 和
Hinton\footnote{\href{http://www.cs.toronto.edu/~hinton/absps/momentum.pdf}{On
the importance of initialization and momentum in deep learning},作者为 Ilya
Sutskever,James Martens, George Dahl 和 Geoffrey Hinton (2013)。} 研究了深
度学习使用随机权重初始化和基于 momentum 的 $SGD$ 方法。两种情形下,好的选择可以获
得较大的差异的训练效果。

这些例子告诉我们,“什么让训练深度网络非常困难”这个问题相当复杂。本章,我们已经
集中于深度神经网络中基于梯度的学习方法的不稳定性。结果表明了激活函数的选择,权重
Expand Down

0 comments on commit 4008efa

Please sign in to comment.