Commit b7a2d363 by 孟霞

合并分支 'mengxia' 到 'caorunzhe'

Mengxia

查看合并请求 !178
parents 12cb5f33 739a7e94
......@@ -154,6 +154,14 @@ F(x)=\int_{-\infty}^x f(x)\textrm{d}x
\label{eq:2-6}
\end{eqnarray}
\parinterval 链式法则经常被用于对事件序列的建模。比如,事件A依赖于事件B,事件B依赖于事件C,应用链式法有:
\begin{eqnarray}
\funp{P}(A,B,C) & = & \funp{P}(A \mid B,C)\funp{P}(B \mid C)\funp{P}(C) \nonumber \\
& = & \funp{P}(A \mid B)\funp{P}(B \mid C)\funp{P}(C)
\label{eq:chain-rule-example}
\end{eqnarray}
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
%----------------------------------------------------------------------------------------
......
......@@ -54,7 +54,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{早期的人工神经网络和第一次寒冬}
\subsubsection{1. 早期的人工神经网络和第一次寒冬}
\parinterval 最初,神经网络设计的初衷是用计算模型来模拟生物大脑中神经元的运行机理,这种想法哪怕是现在看来也是十分超前的。例如,目前很多机构关注的概念\ \dash \ ``类脑计算''就是希望研究人脑的运行机制及相关的计算机实现方法。然而模拟大脑这件事并没有想象中的那么简单,众所周知,生物学中对人脑机制的研究是十分困难的,我们对人脑的运行机制尚不明确又何谈模拟呢?因而,神经网络技术一直在摸索着前行,发展到现在,其计算过程与人脑的运行机制已经大相径庭。
......@@ -66,7 +66,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{神经网络的第二次高潮和第二次寒冬}
\subsubsection{2. 神经网络的第二次高潮和第二次寒冬}
\parinterval 虽然第一代神经网络受到了打击,但是20世纪80年代,第二代人工神经网络开始萌发新的生机。在这个发展阶段,生物属性已经不再是神经网络的唯一灵感来源,在{\small\bfnew{连接主义}}\index{连接主义}(Connectionism)\index{Connectionism}{\small\bfnew{分布式表示}}\index{分布式表示}(Distributed representation)\index{Distributed representation}两种思潮的影响下,神经网络方法再次走入了人们的视线。
......@@ -88,7 +88,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{深度学习和神经网络方法的崛起}
\subsubsection{3. 深度学习和神经网络方法的崛起}
\parinterval 21世纪初,随着深度学习浪潮席卷世界,人工神经网络又一次出现在人们的视野中。深度学习的流行源于2006年Hinton等人成功训练了一个深度信念网络(Deep Belief Network),在深度神经网络方法完全不受重视的情况下,大家突然发现深度神经网络完全是一个魔鬼般的存在,可以解决很多当时其他方法无法解决的问题。神经网络方法终于在一次又一次的被否定后,迎来了它的春天。随之针对神经网络和深度学习的一系列研究前赴后继地展开了,延续至今。
......@@ -127,7 +127,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{端到端学习和表示学习}
\subsubsection{1. 端到端学习和表示学习}
\parinterval 端到端学习使机器学习不再像以往传统的特征工程方法一样需要经过繁琐的数据预处理、特征选择、降维等过程,而是直接利用人工神经网络自动从简单特征中提取、组合更复杂的特征,大大提升了模型能力和工程效率。以图\ref{fig:5-2}中的图像分类为例,在传统方法中,图像分类需要很多阶段的处理。首先,需要提取一些手工设计的图像特征,在将其降维之后,需要利用SVM等分类算法对其进行分类。与这种多阶段的流水线似的处理流程相比,端到端深度学习只训练一个神经网络,输入就是图片的像素表示,输出直接是分类类别。
......@@ -171,7 +171,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{深度学习的效果}
\subsubsection{2. 深度学习的效果}
\parinterval 相比于传统的基于特征工程的方法,基于深度学习的模型更加方便、通用,在系统性能上也普遍更优。这里以语言建模任务为例。语言建模的目的是开发一个模型来描述词串出现的可能性(见第二章)。这个任务已经有着很长时间的历史。表\ref{tab:5-1}给出了不同方法在标准的PTB上的困惑度结果 \footnote{困惑度越低标明语言建模的效果越好。} 。传统的$ n$-gram语言模型由于面临维度灾难和数据稀疏问题,最终语言模型的性能并不是很好。而在深度学习模型中,通过引入循环神经网络等结构,所得到的语言模型可以更好地描述序列生成的问题。而最新的基于Transformer架构的语言模型将PPL从最初的178.0下降到了惊人的35.7。可见深度学习为这个任务所带来的进步是巨大的。
......@@ -217,7 +217,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{标量、向量和矩阵}
\subsubsection{1. 标量、向量和矩阵}
\vspace{-0.5em}
\parinterval {\small\sffamily\bfseries{标量}}\index{标量}(Scalar)\index{Scalar}:标量亦称``无向量'',是一种只具有数值大小而没有方向的量,通俗地说,一个标量就是一个单独的数,这里特指实数\footnote{严格意义上,标量可以是复数等其他形式。这里为了方便讨论,仅以实数为对象。}。一般用小写斜体表示标量。比如,对于$ a=5 $$ a $就是一个标量。
......@@ -252,7 +252,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{矩阵的转置}
\subsubsection{2. 矩阵的转置}
\parinterval {\small\sffamily\bfseries{转置}}\index{转置}(Transpose)\index{Transpose}是矩阵的重要操作之一。矩阵的转置可以看作是将矩阵以对角线为镜像进行翻转:假设$ \mathbf a $$ m $$ n $列的矩阵,第$ i $行、第$ j $ 列的元素是$ a_{ij} $,即:$ \mathbf a={(a_{ij})}_{m\times n} $,把$ m\times n $矩阵$ \mathbf a $的行换成同序数的列得到一个$ n\times m $矩阵,则得到$ \mathbf a $的转置矩阵,记为$ \mathbf a^{\rm T} $,其中$ a_{ji}^{\rm T}=a_{ij} $。例如:
\begin{eqnarray}
......@@ -266,7 +266,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{矩阵加法和数乘}
\subsubsection{3. 矩阵加法和数乘}
\parinterval 矩阵加法又被称作{\small\sffamily\bfseries{按元素加法}}\index{按元素加法}(Element-wise Addition)\index{Element-wise Addition}。它是指两个矩阵把其相对应元素加在一起的运算,通常的矩阵加法被定义在两个形状相同的矩阵上。两个$ m\times n $矩阵$ \mathbf a $$ \mathbf b $的和,标记为$ \mathbf a + \mathbf b $,它也是个$ m\times n $矩阵,其内的各元素为其相对应元素相加后的值。如果矩阵$ \mathbf c = \mathbf a + \mathbf b $,则$ c_{ij} = a_{ij} + b_{ij} $。公式\ref{eq:5-4}展示了矩阵之间进行加法的计算过程。
\begin{eqnarray}
......@@ -336,7 +336,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{矩阵乘法和矩阵点乘}
\subsubsection{4. 矩阵乘法和矩阵点乘}
\parinterval 矩阵乘法是矩阵运算中最重要的操作之一,为了与矩阵点乘区分,通常也把矩阵乘法叫做矩阵叉乘。假设$ \mathbf a $$ m\times p $的矩阵,$ \mathbf b $$ p\times n $的矩阵,对$ \mathbf a $$ \mathbf b $作矩阵乘法的结果是一个$ m\times n $的矩阵$ \mathbf c $,其中矩阵$ \mathbf c $中第$ i $行、第$ j $列的元素可以表示为:
\begin{eqnarray}
......@@ -400,7 +400,7 @@
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{线性映射}
\subsubsection{5. 线性映射}
\parinterval {\small\sffamily\bfseries{线性映射}}\index{线性映射}( Linear Mapping)\index{Linear Mapping}{\small\sffamily\bfseries{线性变换}}\index{线性变换}(Linear Transformation)\index{Linear Transformation}是从一个向量空间V到另一个向量空间W的映射函数$ f:v\rightarrow w$,且该映射函数保持加法运算和数量乘法运算,即对于空间V中任何两个向量$ \mathbf u $$ \mathbf v $以及任何标量$ c $,有:
\begin{eqnarray}
......@@ -444,7 +444,7 @@ f(c\mathbf v)&=&cf(\mathbf v)
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{范数}
\subsubsection{6. 范数}
\parinterval 工程领域,经常会使用被称为{\small\bfnew{范数}}\index{范数}(Norm)\index{Norm}的函数衡量向量大小,范数为向量空间内的所有向量赋予非零的正长度或大小。对于一个$n$维向量$ \mathbf x $,一个常见的范数函数为$ l_p $ 范数,通常表示为$ {\Vert{\mathbf x}\Vert}_p $ ,其中$p\ge 0$,是一个标量形式的参数。常用的$ p $的取值有$ 1 $$ 2 $$ \infty $等。范数的计算公式为:
\begin{eqnarray}
......@@ -524,7 +524,7 @@ l_p(\mathbf x) & = & {\Vert{\mathbf x}\Vert}_p \nonumber \\
%----------------------------------------------------------------------------------------
\vspace{-0.5em}
\subsubsection{感知机\ \dash \ 最简单的人工神经元模型}
\subsubsection{1. 感知机\ \dash \ 最简单的人工神经元模型}
\vspace{0.5em}
\parinterval 感知机是人工神经元的一种实例,在上世纪50-60年代被提出后,对神经网络研究产生了深远的影响。感知机模型如图\ref {fig:5-5}所示,其输入是一个$n$维二值向量$ \mathbf x=(x_0,x_1,\dots,x_n) $,其中$ x_i=0 $$ 1 $。权重$ \mathbf w=(w_0,w_1,\dots,w_n) $,每个输入变量对应一个权重$ w_i $(实数)。偏置$ b $是一个实数变量($ -\sigma $)。输出也是一个二值结果,即$ y=0 $$ 1 $$ y $值的判定由输入的加权和是否大于(或小于)一个阈值$ \sigma $决定(公式\ref{eq:5-19}):
......@@ -577,7 +577,7 @@ x_0\cdot w_0+x_1\cdot w_1+x_2\cdot w_2 & = & 0\cdot 1+0\cdot 1+1\cdot 1 \nonumbe
%----------------------------------------------------------------------------------------
\vspace{-1em}
\subsubsection{神经元内部权重}
\subsubsection{2. 神经元内部权重}
\parinterval 在上面的例子中,连接权重代表着每个输入因素对最终输出结果的重要程度,为了得到令人满意的决策,需要不断调整权重。如果你是守财奴,则会对票价看得更重一些,这样你会用不均匀的权重计算每个因素的影响,比如:$ w_0=0.5 $$ w_1=2 $$ w_2=0.5 $,此时感知机模型如图\ref{fig:5-7}所示。在这种情况下,女友很希望和你一起去看音乐会,但是剧场很远而且票价500元,会导致你不去看音乐会,因为
\begin{eqnarray}
......@@ -602,7 +602,7 @@ x_0\cdot w_0+x_1\cdot w_1+x_2\cdot w_2 & = & 0\cdot 1+0\cdot 1+1\cdot 1 \nonumbe
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{神经元的输入\ \dash \ 离散 vs 连续}
\subsubsection{3. 神经元的输入\ \dash \ 离散 vs 连续}
\parinterval 在遭受了女友一万点伤害之后,你意识到决策考虑的因素(即输入)不应该只是非0即1,而应该把``程度''考虑进来,于是你改变了三个输入的形式:
......@@ -637,7 +637,7 @@ x_0\cdot w_0+x_1\cdot w_1+x_2\cdot w_2 & = & 0\cdot 1+0\cdot 1+1\cdot 1 \nonumbe
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{神经元内部的参数学习}
\subsubsection{4. 神经元内部的参数学习}
\parinterval 一次成功的音乐会之后,你似乎掌握了一个真理:其他什么都不重要,女友的喜好最重要,所以你又将决策模型的权重做出了调整:最简单的方式就是$ w_0=w_1=0 $,同时令$ w_2>0 $,相当于只考虑$ x_2 $的影响而忽略其他因素,于是你得到了如图\ref {fig:5-9}所示的决策模型:
......@@ -680,7 +680,7 @@ x_0\cdot w_0+x_1\cdot w_1+x_2\cdot w_2 & = & 0\cdot 1+0\cdot 1+1\cdot 1 \nonumbe
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{线性变换和激活函数}
\subsubsection{1. 线性变换和激活函数}
\parinterval 为了建立多层神经网络,首先需要把前面提到的简单的神经元进行扩展,把多个神经元组成一``层''神经元。比如,很多实际问题需要同时有多个输出,这时可以把多个相同的神经元并列起来,每个神经元都会有一个单独的输出,这就构成一``层'',形成了单层神经网络。单层神经网络中的每一个神经元都对应着一组权重和一个输出,可以把单层神经网络中的不同输出看作一个事物不同角度的描述。
......@@ -812,7 +812,7 @@ x_0\cdot w_0+x_1\cdot w_1+x_2\cdot w_2 & = & 0\cdot 1+0\cdot 1+1\cdot 1 \nonumbe
%----------------------------------------------------------------------------------------
\vspace{-0.5em}
\subsubsection{单层神经网络$\rightarrow$多层神经网络}
\subsubsection{2. 单层神经网络$\rightarrow$多层神经网络}
\parinterval 单层神经网络由线性变换和激活函数两部分构成,但在实际问题中,单层网络并不能很好地拟合复杂函数。因此很自然地想到将单层网络扩展到多层神经网络,即深层神经网络。将一层神经网络的最终输出向量作为另一层神经网络的输入向量,通过这种方式可以将多个单层神经网络连接在一起。
......@@ -950,7 +950,7 @@ x_0\cdot w_0+x_1\cdot w_1+x_2\cdot w_2 & = & 0\cdot 1+0\cdot 1+1\cdot 1 \nonumbe
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{\ 张量}
\subsubsection{1. 张量}
\parinterval 对于神经网络中的某层神经元$ \mathbf y=f(\mathbf x\cdot \mathbf w+\mathbf b) $,其中$ \mathbf w $是权重矩阵,例如$ \begin{pmatrix} 1 & 2\\ 3 & 4\end{pmatrix} $$ \mathbf b $ 是偏置向量,例如$ (1,3) $。在这里,输入$ \mathbf x $和输出$ \mathbf y $,可以不是简单的向量或是矩阵形式,而是深度学习中更加通用的数学量\ \dash \ {\small\bfnew{张量}}\index{张量}(Tensor)\index{Tensor},比如下式中的几种情况都可以看作是深度学习中定义数据的张量:
\begin{eqnarray}
......@@ -979,7 +979,7 @@ x_0\cdot w_0+x_1\cdot w_1+x_2\cdot w_2 & = & 0\cdot 1+0\cdot 1+1\cdot 1 \nonumbe
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{张量的矩阵乘法}
\subsubsection{2. 张量的矩阵乘法}
\parinterval 对于一个单层神经网络,$ \mathbf y=f(\mathbf x\cdot \mathbf w+\mathbf b) $中的$ \mathbf x\cdot \mathbf w $表示对输入$ \mathbf x $进行线性变换,其中$ \mathbf x $是输入张量,$ \mathbf w $是权重矩阵。$ \mathbf x\cdot \mathbf w $表示的是矩阵乘法,需要注意的是这里是矩阵乘法而不是张量乘法。
......@@ -1017,7 +1017,7 @@ x_0\cdot w_0+x_1\cdot w_1+x_2\cdot w_2 & = & 0\cdot 1+0\cdot 1+1\cdot 1 \nonumbe
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{张量的单元操作}
\subsubsection{3. 张量的单元操作}
\vspace{0.5em}
\parinterval 对于神经网络中的某层神经元$ \mathbf y=f(\mathbf x\cdot \mathbf w+\mathbf b) $,也包含有其他张量单元操作:1)加法:$ \mathbf s+\mathbf b $,其中张量$ \mathbf s=\mathbf x\cdot \mathbf w $;2)激活函数:$ f(\cdot) $。具体来说:
......@@ -1299,7 +1299,7 @@ y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^{[1]}+\mathbf b^{[1]})\c
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{梯度下降}
\subsubsection{1. 梯度下降}
\parinterval 梯度下降法是一种常用的优化方法,非常适用于目标函数可微分的问题。它的基本思想是:给定函数上的第一个点,找到使函数值变化最大的方向,然后前进一``步'',这样模型就可以朝着更大(或更小)的函数值以最快的速度移动\footnote{梯度下降的一种实现是{\scriptsize\bfnew{最速下降}}(Steepest Descent)。该方法的每一步移动都选取合适的步长,进而使目标函数能得到最大程度的增长(或下降)。}。具体来说,梯度下降通过迭代更新参数$ \mathbf w $,不断沿着梯度的反方向让参数$ \mathbf w $朝着损失函数更小的方向移动:如果$ J(\mathbf w) $$ \mathbf w $可微分,则$ \frac{\partial J(\mathbf w)}{\partial \mathbf w} $将指向$ J(\mathbf w) $$ \mathbf w $处变化最大的方向,这里将其称之为梯度方向。$ \mathbf w $沿着梯度方向更新,新的$ \mathbf w $可以使函数更接近极值,其过程如图\ref{fig:5-43}所示。
......@@ -1327,7 +1327,7 @@ y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^{[1]}+\mathbf b^{[1]})\c
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{批量梯度下降\index{批量梯度下降}(Batch Gradient Descent)\index{Batch Gradient Descent}}}
\noindent {\small\sffamily\bfseries{(1)批量梯度下降\index{批量梯度下降}(Batch Gradient Descent)\index{Batch Gradient Descent}}}
\vspace{0.5em}
\parinterval 批量梯度下降是梯度下降方法中最原始的形式,这种梯度下降方法在每一次迭代时使用所有的样本进行参数更新。参数优化的目标函数是
......@@ -1345,7 +1345,7 @@ J(\mathbf w)&=&\frac{1}{n}\sum_{i=1}^{n}{L(\mathbf x_i,\mathbf {\widetilde y}_i;
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{随机梯度下降\index{随机梯度下降}(Stochastic Gradient Descent)\index{Stochastic Gradient Descent}}}
\noindent {\small\sffamily\bfseries{(2)随机梯度下降\index{随机梯度下降}(Stochastic Gradient Descent)\index{Stochastic Gradient Descent}}}
\vspace{0.5em}
\parinterval 随机梯度下降(简称SGD)不同于批量梯度下降,每次迭代只使用一个样本对参数进行更新。SGD的目标函数是
......@@ -1363,7 +1363,7 @@ J(\mathbf w)&=&L(\mathbf x_i,\mathbf {\widetilde y}_i;\mathbf w)
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{小批量梯度下降\index{小批量梯度下降}(Mini-Batch Gradient Descent)\index{Mini-Batch Gradient Descent}}}
\noindent {\small\sffamily\bfseries{(3)小批量梯度下降\index{小批量梯度下降}(Mini-Batch Gradient Descent)\index{Mini-Batch Gradient Descent}}}
\vspace{0.5em}
\parinterval 为了综合批量梯度下降和随机梯度下降的优缺点,在实际应用中一般采用这两个算法的折中\ \dash \ 小批量梯度下降。其思想是:每次迭代计算一小部分训练数据的损失函数,并对参数进行更新。这一小部分数据被称为一个批次(mini-batch或者batch)。小批量梯度下降的参数优化的目标函数如下:
......@@ -1378,7 +1378,7 @@ J(\mathbf w)&=&\frac{1}{m}\sum_{i=j}^{j+m-1}{L(\mathbf x_i,\mathbf {\widetilde y
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{梯度获取}
\subsubsection{2. 梯度获取}
\parinterval 梯度下降算法的一个核心是要得到目标函数相对于参数的梯度。下面将介绍三种常见的求梯度方法:数值微分、符号微分和自动微分,深度学习实现过程中多是采用自动微分方法计算梯度\cite{baydin2017automatic}
......@@ -1387,7 +1387,7 @@ J(\mathbf w)&=&\frac{1}{m}\sum_{i=j}^{j+m-1}{L(\mathbf x_i,\mathbf {\widetilde y
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{数值微分\index{数值微分}(Numerical Differentiation)\index{Numerical Differentiation}}}
\noindent {\small\sffamily\bfseries{(1)数值微分\index{数值微分}(Numerical Differentiation)\index{Numerical Differentiation}}}
\vspace{0.5em}
\parinterval 数学上,梯度的求解其实就是求函数偏导的问题。导数是用极限来定义的,如下:
......@@ -1410,7 +1410,7 @@ J(\mathbf w)&=&\frac{1}{m}\sum_{i=j}^{j+m-1}{L(\mathbf x_i,\mathbf {\widetilde y
%
%----------------------------------------------------------------------------------------
\noindent {\small\sffamily\bfseries{ 符号微分\index{符号微分}(Symbolic Differentiation)\index{Symbolic Differentiation}}}
\noindent {\small\sffamily\bfseries{(2)符号微分\index{符号微分}(Symbolic Differentiation)\index{Symbolic Differentiation}}}
\vspace{0.5em}
\parinterval 顾名思义,符号微分就是通过建立符号表达式求解微分的方法:借助符号表达式和求导公式,推导出目标函数关于自变量的微分表达式,最后再带入具体数值得到微分结果。例如,对于表达式$ L(\mathbf w)=\mathbf x\cdot \mathbf w+2\mathbf w^2 $,可以手动推导出微分表达式$ \frac{\partial L(\mathbf w)}{\partial \mathbf w}=\mathbf x+4\mathbf w $,最后将具体数值$ \mathbf x = {(\begin{array}{cc} 2 & -3\end{array})} $$ \mathbf w = {(\begin{array}{cc} -1 & 1\end{array})} $带入后,得到微分结果$\frac{\partial L(\mathbf w)}{\partial \mathbf w}= {(\begin{array}{cc} 2 & -3\end{array})}+4{(\begin{array}{cc} -1 & 1\end{array})}= {(\begin{array}{cc} -2 & 1\end{array})}$
......@@ -1446,7 +1446,7 @@ $+2x^2+x+1)$ & \ \ $(x^4+2x^3+2x^2+x+1)$ & $+6x+1$ \\
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{自动微分\index{自动微分}(Automatic Differentiation)\index{Automatic Differentiation}}}
\noindent {\small\sffamily\bfseries{(3)自动微分\index{自动微分}(Automatic Differentiation)\index{Automatic Differentiation}}}
\vspace{0.5em}
\parinterval 自动微分是一种介于数值微分和符号微分的方法:将符号微分应用于最基本的算子,如常数、幂函数、指数函数、对数函数、三角函数等,然后代入数值,保留中间结果,最后再应用于整个函数。通过这种方式,将复杂的微分变成了简单的步骤,这些步骤完全自动化,而且容易进行存储和计算。
......@@ -1491,7 +1491,7 @@ $+2x^2+x+1)$ & \ \ $(x^4+2x^3+2x^2+x+1)$ & $+6x+1$ \\
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{基于梯度的方法的变种和改进}\label{sec:5.4.2.3}
\subsubsection{3. 基于梯度的方法的变种和改进}\label{sec:5.4.2.3}
\parinterval 参数优化通常基于梯度下降算法,即在每个更新步骤$ t $,沿梯度方向更新参数:
\begin{eqnarray}
......@@ -1517,7 +1517,7 @@ $+2x^2+x+1)$ & \ \ $(x^4+2x^3+2x^2+x+1)$ & $+6x+1$ \\
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{Momentum \index{Momentum}}}
\noindent {\small\sffamily\bfseries{(1)Momentum \index{Momentum}}}
\vspace{0.5em}
\parinterval Momentum梯度下降算法的参数更新公式如下\footnote{在梯度下降算法的几种改进方法的公式中,其更新对象是某个具体参数而非参数矩阵,因此不再使用加粗样式}
......@@ -1536,7 +1536,7 @@ w_{t+1}&=&w_t-\alpha v_t
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{AdaGrad \index{AdaGrad}}}
\noindent {\small\sffamily\bfseries{(2)AdaGrad \index{AdaGrad}}}
\vspace{0.5em}
\parinterval 在神经网络的学习中,学习率的设置很重要。学习率过小, 会导致学习花费过多时间;反过来,学习率过大,则会导致学习发散,甚至造成模型的``跑偏''。在深度学习实现过程中,有一种被称为学习率{\small\bfnew{衰减}}\index{衰减}(Decay)\index{Decay}的方法,即最初设置较大的学习率,随着学习的进行,使学习率逐渐减小,这种方法相当于将``全体''参数的学习率值一起降低。AdaGrad梯度下降算法进一步发展了这个思想\cite{duchi2011adaptive}
......@@ -1555,7 +1555,7 @@ w_{t+1}&=&w_t-\eta \frac{1}{\sqrt{z_t}}\cdot \frac{\partial L}{\partial w_t}
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{RMSprop \index{RMSprop}}}
\noindent {\small\sffamily\bfseries{(3)RMSprop \index{RMSprop}}}
\vspace{0.5em}
\parinterval RMSprop算法是一种自适应学习率的方法\cite{tieleman2012rmsprop},它是对AdaGrad算法的一种改进,可以避免AdaGrad算法中学习率不断单调下降以至于过早衰减的缺点。
......@@ -1576,7 +1576,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}}\cdot \frac{\partial L}{\partial w
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\noindent {\small\sffamily\bfseries{Adam \index{Adam} }}
\noindent {\small\sffamily\bfseries{(4)Adam \index{Adam} }}
\vspace{0.5em}
\parinterval Adam梯度下降算法是在RMSProp算法的基础上进行改进的,可以将其看成是带有动量项的RMSProp算法\cite{kingma2014adam}。该算法在自然语言处理领域非常流行。Adam 算法的参数更新公式如下,
......@@ -1632,7 +1632,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{易于优化的激活函数}
\subsubsection{1. 易于优化的激活函数}
\parinterval 网络训练过程中,如果每层网络的梯度都小于1,各层梯度的偏导数会与后面层传递而来的梯度相乘得到本层的梯度,并向前一层传递。该过程循环进行,最后导致梯度指数级地减小,这就产生了梯度消失现象。这种情况会导致神经网络层数较浅的部分梯度接近0。一般来说,产生很小梯度的原因是使用了类似于Sigmoid这样的激活函数,当输入的值过大或者过小的时候这类函数曲线会趋于直线,梯度近似为零。针对这个问题,主要的解决办法是使用更加易于优化的激活函数,比如,使用ReLU代替Sigmoid和Tanh作为激活函数。
......@@ -1675,7 +1675,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{梯度裁剪}
\subsubsection{2. 梯度裁剪}
\parinterval 网络训练过程中,如果参数的初始值过大,而且每层网络的梯度都大于1,反向传播过程中,各层梯度的偏导数都会比较大,会导致梯度指数级地增长直至超出浮点数表示的范围,这就产生了梯度爆炸现象。如果发生这种情况,模型中离输入近的部分比离输入远的部分参数更新得更快,使网络变得非常不稳定。在极端情况下,模型的参数值变得非常大,甚至于溢出。针对梯度爆炸的问题,常用的解决办法为{\small\sffamily\bfseries{梯度裁剪}}\index{梯度裁剪}(Gradient Clipping)\index{Gradient Clipping}
......@@ -1691,10 +1691,12 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{稳定性训练}
\subsubsection{3. 稳定性训练}
\parinterval 为了使神经网络模型训练更加稳定,通常还会考虑其他策略。
\parinterval {\red{考虑是否弄成小标题}}
\parinterval (1){\small\bfnew{批量归一化}}\index{批量归一化}(Batch Normalization)\index{Batch Normalization}
\parinterval 批量归一化,顾名思义,是以进行学习时的小批量样本为单位进行归一化\cite{ioffe2015batch}。具体而言,就是对神经网络隐层输出的每一个维度,沿着批次的方向进行均值为0、方差为1的归一化。在深层神经网络中,每一层网络都可以使用批量归一化操作。这样使神经网络任意一层的输入不至于过大或过小,从而防止隐层中异常值导致模型状态的巨大改变。
......@@ -1806,7 +1808,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{输出层的反向传播}
\subsubsection{1. 输出层的反向传播}
\parinterval 反向传播是由输出层开始计算梯度,之后逆向传播到每一层网络,直至到达输入层。这里首先讨论输出层的反向传播机制。输出层(即第$ K $层)可以被描述为:
\begin{eqnarray}
......@@ -1909,7 +1911,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{隐藏层的反向传播}
\subsubsection{2. 隐藏层的反向传播}
\parinterval 对于第$ k $个隐藏层,有:
\begin{eqnarray}
......@@ -1970,7 +1972,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{程序实现}
\subsubsection{3. 程序实现}
\parinterval 在了解了反向传播的原理之后,实现反向传播就变得非常容易了。实际上,现在主流的深度学习框架都支持自动微分。为了进一步说明反向传播的过程,这里使用NiuTensor工具构建两个简单的实例,并分别尝试手动编写反向传播代码和使用NiuTensor自带的自动微分模块。
......@@ -2045,7 +2047,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{基于前馈神经网络的语言模型}
\subsubsection{1. 基于前馈神经网络的语言模型}
\parinterval 最具代表性的神经语言模型是Bengio等人提出的{\small\sffamily\bfseries{前馈神经网络语言模型}}\index{前馈神经网络语言模型}(Feed-forward Neural Network Language Model\index{Feed-forward Neural Network Language Model},简称FNNLM)。这种语言模型的目标是用神经网络计算$ {\rm P}(w_m|w_{m-n+1}\dots w_{m-1}) $,之后将多个$n$-gram的概率相乘得到整个序列的概率\cite{bengio2003a}
......@@ -2106,7 +2108,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{基于循环神经网络的语言模型}
\subsubsection{2. 基于循环神经网络的语言模型}
\parinterval FNNLM模型固然有效,但是和传统的$n$-gram语言模型一样需要依赖有限上下文假设,也就是$ w_i $的生成概率只依赖于之前的$ n-1 $个单词。很自然的一个想法是引入更大范围的历史信息,这样可以捕捉单词间的长距离依赖。
......@@ -2143,7 +2145,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{其他类型的语言模型}
\subsubsection{3. 其他类型的语言模型}
\parinterval 通过引入记忆历史的能力,RNNLM缓解了$n$-gram模型中有限上下文的局限性,但依旧存在一些问题。随着序列变长,不同单词之间信息传递路径变长,信息传递的效率变低。对于长序列,很难通过很多次的循环单元操作保留很长的历史信息。过长的序列还容易引起梯度消失和梯度爆炸问题(详见\ref{sec:5.4.4}节),增加模型训练的难度。
......@@ -2157,7 +2159,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{语言模型的评价}
\subsubsection{4. 语言模型的评价}
\parinterval 在使用语言模型时,往往需要知道模型的质量。{\small\sffamily\bfseries{困惑度}}\index{困惑度}(Perplexity\index{Perplexity},PPL)是一种衡量语言模型的好坏的指标。对于一个真实的词序列$ w_1\dots w_m $,困惑度被定义为
\begin{eqnarray}
......@@ -2179,7 +2181,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{One-hot编码}
\subsubsection{1. One-hot编码}
\parinterval {\small\sffamily\bfseries{One-hot编码}}\index{One-hot编码}(也称{\small\sffamily\bfseries{独热编码}}\index{独热编码})是传统的单词表示方法。One-hot编码把单词表示为词汇表大小的0-1向量,其中只有该词所对应的那一项是1,而其余所有项都是零。举个简单的例子,假如有一个词典,里面包含10k个单词,并进行编号。那么每个单词都可以表示为一个10k维的One-hot向量,它仅在对应编号那个维度为1,其他维度都为0,如图\ref{fig:5-64}所示。
......@@ -2198,7 +2200,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{分布式表示}
\subsubsection{2. 分布式表示}
\parinterval 神经语言模型中使用的是一种{\small\sffamily\bfseries{分布式表示}}\index{分布式表示}(Distributed Representation)\index{Distributed Representation}。在神经语言模型里,每个单词不再是完全正交的0-1向量,而是在多维实数空间中的一个点,具体表现为一个实数向量。很多时候,也会把单词的这种分布式表示叫做{\small\sffamily\bfseries{词嵌入}}\index{词嵌入}(Word Embedding)\index{Word Embedding}
......@@ -2268,7 +2270,7 @@ Jobs was the CEO of {\red{\underline{apple}}}.
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\subsubsection{简单的上下文表示模型}
\subsubsection{1. 简单的上下文表示模型 \red{这就一小节,是去掉小标题还是后续补充其他内容?}}
\parinterval 回忆一下神经语言模型的结构,它需要在每个位置预测单词生成的概率。这个概率是由若干层神经网络进行计算后,通过输出层得到的。实际上,在送入输出层之前,系统已经得到了这个位置的一个向量(隐藏层的输出),因此可以把它看作是含有一部分上下文信息的表示结果。以RNN为例,图\ref{fig:5-68}展示了一个由四个词组成的句子,这里使用了一个两层循环神经网络对其进行建模。可以看到,对于第三个位置,RNN已经积累了从第1个单词到第3个单词的信息,因此可以看作是单词1-3(``乔布斯\ 就职\ 于'')的一种表示;另一方面,第4个单词的词嵌入可以看作是``苹果''自身的表示。这样,可以把第3 个位置RNN的输出和第4个位置的词嵌入进行合并,就得到了第4个位置上含有上下文信息的表示结果。从另一个角度说,这里得到了``苹果''的一种新的表示,它不仅包含苹果这个词自身的信息,也包含它前文的信息。
......@@ -2283,6 +2285,8 @@ Jobs was the CEO of {\red{\underline{apple}}}.
\parinterval 在自然语言处理中,{\small\sffamily\bfseries{句子表示模型}}\index{句子表示模型}是指把输入的句子进行分布式表示。不过表示的形式不一定是一个单独的向量。现在广泛使用的句子表示模型可以被描述为:给定一个输入的句子$ \{ w_1,\dots ,w_m\} $,得到一个表示序列$ \{ \mathbf h_1,\dots ,\mathbf h_m\} $,其中$ h_i $是句子在第$ i $个位置的表示结果。$ \{ \mathbf h_1,\dots ,\mathbf h_m\} $就被看作是{\small\sffamily\bfseries{句子的表示}}\index{句子的表示},它可以被送入下游模块。比如,在机器翻译任务中,可以用这种模型表示源语言句子,然后通过这种表示结果进行目标语译文的生成;在序列标注(如词性标注)任务中,可以对输入的句子进行表示,然后在这个表示之上构建标签预测模块。很多自然语言处理任务都可以用句子表示模型进行建模,因此句子的表示模型也是应用最广泛的深度学习模型之一。而学习这种表示的过程也被称作{\small\sffamily\bfseries{表示学习}}\index{表示学习}(Representation Learning)\index{Representation Learning}
\parinterval{\red{(下一段应该会删掉)}}
\parinterval 句子表示模型有两种训练方法。最简单的方法是把它作为目标系统中的一个模块进行训练,比如把句子表示模型作为机器翻译系统的一部分。也就是,并不单独训练句子表示模型,而是把它作为一个内部模块放到其他系统中。另一种方法是把句子表示作为独立的模块,用外部系统进行训练,之后把训练好的表示模型放入目标系统中,再进行微调。这种方法构成了一种新的范式:预训练+微调(pre-training + fine-tuning)。图\ref{fig:5-69}对比了这两种不同的方法。
%----------------------------------------------
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论