Commit 68f1ed1a by 曹润柘

合并分支 'caorunzhe' 到 'master'

Caorunzhe

查看合并请求 !179
parents 29a523a8 ec78a66b
......@@ -60,16 +60,16 @@
{
\node [anchor=north west] (seg4) at ([xshift=-1.0em,yshift=0.4em]seg3.south west) {...};
\node [anchor=east,ugreen] (p1seg1) at ([xshift=0.5em]seg1.west) {P(};
\node [anchor=west,ugreen] (p2seg1) at ([xshift=-0.5em]seg1.east) {)=.1};
\node [anchor=west,ugreen] (p2seg1) at ([xshift=-0.5em]seg1.east) {)=0.1};
\node [anchor=east,ugreen] (p1seg2) at ([xshift=0.5em]seg2.west) {P(};
\node [anchor=west,ugreen] (p2seg2) at ([xshift=-0.5em]seg2.east) {)=.6};
\node [anchor=west,ugreen] (p2seg2) at ([xshift=-0.5em]seg2.east) {)=0.6};
\node [anchor=east,ugreen] (p1seg3) at ([xshift=0.5em]seg3.west) {P(};
\node [anchor=west,ugreen] (p2seg3) at ([xshift=-0.5em]seg3.east) {)=.2};
\node [anchor=west,ugreen] (p2seg3) at ([xshift=-0.5em]seg3.east) {)=0.2};
}
{
\node [anchor=east,draw,dashed,red,thick,minimum width=12.6em,minimum height=1.4em] (final) at (p2seg2.east) {};
\node [anchor=west,red] (finallabel) at ([xshift=2.7em]sentlabel.east) {输出概率最大的结果};
\node [anchor=east,draw,dashed,red,thick,minimum width=13em,minimum height=1.4em] (final) at (p2seg2.east) {};
\node [anchor=west,red] (finallabel) at ([xshift=3.1em]sentlabel.east) {输出概率最大的结果};
%\node [anchor=north east,red] (finallabel2) at ([yshift=0.5em]finallabel.south east) {的结果};
\draw [->,thick,red] ([xshift=0.0em,yshift=-0.5em]final.north east) ..controls +(east:0.3) and +(south:0.0).. ([xshift=1.0em]finallabel.south);
}
......
......@@ -22,7 +22,7 @@
\parinterval 语言分析部分将以汉语为例介绍词法和句法分析的基本概念。它们都是自然语言处理中的经典问题,而且在机器翻译中也会经常被使用。同样,本章会介绍这两个任务的定义和求解问题的思路。
\parinterval 语言建模是机器翻译中最常用的一种技术,它主要用于句子的生成和流畅度评价。本章会以传统统计语言模型为例,对语言建模的相关概念进行介绍。但是,这里并不深入探讨语言模型技术,在后面的章节中还会单独对神经网络语言模型等前沿技术进行讨论。\\ \\ \\
\parinterval 语言建模是机器翻译中最常用的一种技术,它主要用于句子的生成和流畅度评价。本章会以传统统计语言模型为例,对语言建模的相关概念进行介绍。但是,这里并不深入探讨语言模型技术,在后面的章节中还会单独对神经网络语言模型等前沿技术进行讨论。
%----------------------------------------------------------------------------------------
% NEW SECTION
......@@ -30,7 +30,7 @@
\section{问题概述 }
\parinterval 很多时候机器翻译系统被看作是孤立的``黑盒''系统(图 \ref {fig:2-1} (a))。将一段文本作为输入送入机器翻译系统之后,系统输出翻译好的译文。但是真实的机器翻译系统非常复杂,因为系统看到的输入和输出的实际上只是一些符号串,这些符号并没有任何意义,因此需要进一步对这些符号串进行处理才能更好的使用它们,比如,需要定义翻译中最基本的单元是什么?符号串是否还有结构信息?如何用数学工具刻画这些基本单元和结构?
\parinterval 很多时候机器翻译系统被看作是孤立的``黑盒''系统(图 \ref {fig:2-1} (a))。将一段文本作为输入送入机器翻译系统之后,系统输出翻译好的译文。但是真实的机器翻译系统非常复杂,因为系统看到的输入和输出实际上只是一些符号串,这些符号并没有任何意义,因此需要进一步对这些符号串进行处理才能更好的使用它们。比如,需要定义翻译中最基本的单元是什么?符号串是否具有结构信息?如何用数学工具刻画这些基本单元和结构?
%----------------------------------------------
\begin{figure}[htp]
......@@ -51,21 +51,21 @@
\end{figure}
%-------------------------------------------
\parinterval\ref{fig:2-1} (b)展示了一个机器翻译系统的输入和输出形式。可以看到,输入的中文串``猫喜欢吃鱼''被加工成一个新的结构(图\ref {fig:2-2})。直觉上,这个结构有些奇怪,因为上面多了很多新的符号,而且还有一些线将不同符号进行连接。实际上这就是语言分析中对句子常用的结构表示 —— 短语结构树。从原始的词串转化为图\ref {fig:2-2} 的样子,有两个步骤:
\parinterval\ref{fig:2-1} (b)展示了一个机器翻译系统的输入和输出形式。可以看到,输入的中文串``猫喜欢吃鱼''被加工成一个新的结构(图\ref {fig:2-2})。直觉上,这个结构有些奇怪,因为上面多了很多新的符号,而且还有一些线将不同符号进行连接。实际上这就是语言分析中对句子常用的结构表示 —— 短语结构树。从原始的词串转化为图\ref {fig:2-2} 的样子,有两个步骤:
\begin{itemize}
\vspace{0.5em}
\item {\small\bfnew{分词}}\index{分词}(Segmentation)\index{Segmentation}:这个过程会把词串进行切分,切割成最小的单元。因为只有知道了什么是待处理字符串的最小单元,机器翻译系统才能对其进行表示、分析和生成。
\vspace{0.5em}
\item {\small\bfnew{句法分析}}\index{句法分析}(Parsing)\index{Parsing}:这个过程会对分词的结果进行进一步分析,得到句子的句法结构,这种结构是对句子的进一步抽象。比如,NP+VP就可以表示由名词短语(NP)和动词短语(VP)构成的主谓结构。利用这些信息,机器翻译可以更加准确的对语言的结构进行分析和生成。
\item {\small\bfnew{句法分析}}\index{句法分析}(Parsing)\index{Parsing}:这个过程会对分词的结果进行进一步分析,得到句子的句法结构。这种结构是对句子的进一步抽象,比如,NP+VP就可以表示由名词短语(NP)和动词短语(VP)构成的主谓结构。利用这些信息,机器翻译可以更加准确地对语言的结构进行分析和生成。
\vspace{0.5em}
\end{itemize}
\parinterval 类似,机器翻译输出的结果也可以包含同样的信息。甚至系统输出英文译文之后,还有一个额外的步骤来把部分英文单词的大小写恢复出来,比如,上例中句首单词Cats的首字母要大写。
\parinterval 类似,机器翻译输出的结果也可以包含同样的信息。甚至系统输出英文译文之后,还有一个额外的步骤来把部分英文单词的大小写恢复出来,比如,上例中句首单词Cats的首字母要大写。
\parinterval 一般来说,在送入机器翻译系统前需要对文字序列进行处理和加工,这个过程被称为{\small\sffamily\bfseries{预处理}}\index{预处理}(Pre-processing)\index{Pre-processing}。同理,在机器翻译模型输出译文后进行的处理被称作{\small\sffamily\bfseries{后处理}}\index{后处理}(Post-processing)\index{Post-processing}。这两个过程对机器翻译性能影响很大,比如,在神经机器翻译里,不同的分词策略可能会造成翻译性能的天差地别。
\parinterval 值得注意的是,有些观点认为,不论是分词还是句法分析,对于机器翻译来说并不要求符合人的认知和语言学约束。换句话说,机器翻译所使用的``单词''和``结构''本身并不是为了符合人类的解释,它们更直接目的是为了进行翻译。从系统开发的角度,有时候即使进行一些与人类的语言习惯有差别的处理,仍然会带来性能的提升,比如在神经机器翻译中,在传统分词的基础上进一步使用双字节编码(Byte Pair Encoding,BPE)子词切分会使得机器翻译性能大幅提高。当然,自然语言处理中语言学信息的使用一直是学界关注的焦点。甚至关于语言学结构对机器翻译是否有作用这个问题也有争论。但是不能否认的是,无论是语言学的知识,还是计算机自己学习到的知识,对机器翻译都是有价值的。在后续章节会看到,这两种类型的知识对机器翻译帮助很大 \footnote[1]{笔者并不认同语言学结构对机器翻译的帮助有限,相反机器翻译需要更多的人类先验知识的指导。当然,这个问题不是这里讨论的重点。}
\parinterval 值得注意的是,有些观点认为,不论是分词还是句法分析,对于机器翻译来说并不要求符合人的认知和语言学约束。换句话说,机器翻译所使用的``单词''和``结构''本身并不是为了符合人类的解释,它们更直接目的是为了进行翻译。从系统开发的角度,有时候即使一些与人类的语言习惯有差别的处理,仍然会带来性能的提升,比如在神经机器翻译中,在传统分词的基础上进一步使用双字节编码(Byte Pair Encoding,BPE)子词切分会使得机器翻译性能大幅提高。当然,自然语言处理中语言学信息的使用一直是学界关注的焦点。甚至关于语言学结构对机器翻译是否有作用这个问题也有争论。但是不能否认的是,无论是语言学的知识,还是计算机自己学习到的知识,对机器翻译都是有价值的。在后续章节会看到,这两种类型的知识对机器翻译帮助很大 \footnote[1]{笔者并不认同语言学结构对机器翻译的帮助有限,相反机器翻译需要更多的人类先验知识的指导。当然,这个问题不是这里讨论的重点。}
\parinterval 剩下的问题是如何进行句子的切分和结构的分析。思路有很多,一种常用的方法是对问题进行概率化,用统计模型来描述问题并求解之。比如,一个句子切分的好坏,并不是非零即一的判断,而是要估计出这种切分的可能性大小,最终选择可能性最大的结果进行输出。这也是一种典型的用统计建模的方式来描述自然语言处理问题的方法。
......@@ -87,7 +87,7 @@
\subsection{随机变量和概率}
\parinterval 在自然界中,很多{\small\bfnew{事件}}\index{事件}(Event)\index{Event}是否会发生是不确定的。例如,明天会下雨、掷一枚硬币是正面朝上、扔一个骰子的点数是5$\cdots\cdots$这类事件可能会发生也可能不会发生。通过大量的重复试验,能发现其具有某种规律性的事件叫做{\small\sffamily\bfseries{随机事件}}\index{随机事件}
\parinterval {\small\sffamily\bfseries{随机变量}}\index{随机变量}(Random Variable)\index{Random Variable}是对随机事件发生可能状态的描述,是随机事件的数量表征。设$\Omega = \{ \omega \}$为一个随机试验的样本空间,$X=X(\omega)$就是定义在样本空间$\omega$上的单值实数函数,即$X=X(\omega)$为随机变量,记为$X$。随机变量是一种能随机选取数值的变量,常用大写的英文字母或希腊字母表示,其取值通常用小写字母来表示。例如,用$A$ 表示一个随机变量,用$a$表示变量$A$的一个取值。根据随机变量可以选取的值,可以将其划分为离散变量和连续变量。
\parinterval {\small\sffamily\bfseries{随机变量}}\index{随机变量}(Random Variable)\index{Random Variable}是对随机事件发生可能状态的描述,是随机事件的数量表征。设$\Omega = \{ \omega \}$为一个随机试验的样本空间,$X=X(\omega)$就是定义在样本空间$\Omega$上的单值实数函数,即$X=X(\omega)$为随机变量,记为$X$。随机变量是一种能随机选取数值的变量,常用大写的英文字母或希腊字母表示,其取值通常用小写字母来表示。例如,用$A$ 表示一个随机变量,用$a$表示变量$A$的一个取值。根据随机变量可以选取的值的某些性质,可以将其划分为离散变量和连续变量。
\parinterval 离散变量是指在其取值区间内可以被一一列举,总数有限并且可计算的数值变量。例如,用随机变量$X$代表某次投骰子出现的点数,点数只可能取1$\sim$6这6个整数,$X$就是一个离散变量。
......@@ -97,6 +97,8 @@
\parinterval 在实际问题中,往往需要得到随机变量的概率值。但是,真实的概率值可能是无法准确知道的,这时就需要对概率进行{\small\sffamily\bfseries{估计}}\index{估计},得到的结果是概率的{\small\sffamily\bfseries{估计值}}\index{估计值}(Estimate)\index{Estimate}。在概率论中,一个很简单的方法是利用相对频度作为概率的估计值。如果$\{x_1,x_2,\dots,x_n \}$是一个试验的样本空间,在相同情况下重复试验$N$次,观察到样本$x_i (1\leq{i}\leq{n})$的次数为$n (x_i )$,那么$x_i$在这$N$次试验中的相对频率是$\frac{n(x_i )}{N}$。当$N$越来越大时,相对概率也就越来越接近真实概率$\textrm{P}(x_i)$,即$\lim_{N \to \infty}\frac{n(x_i )}{N}=\textrm{P}(x_i)$。 实际上,很多概率模型都等同于相对频度估计,比如,对于一个服从多项式分布的变量的极大似然估计就可以用相对频度估计实现。
\parinterval 概率函数是用函数形式给出离散变量每个取值发生的概率,其实就是将变量的概率分布转化为数学表达形式。如果把$A$看做一个离散变量,$a$看做变量$A$的一个取值,那么$\textrm{P}(A)$被称作变量$A$的概率函数,$\textrm{P}(A=a)$被称作$A = a$的概率值,简记为$\textrm{P}(a)$。例如,在相同条件下掷一个骰子50次,用$A$表示投骰子出现的点数这个离散变量,$a_i$表示点数的取值,$\textrm{P}_i$表示$A=a_i$的概率值。下表为$A$的概率分布,给出了$A$的所有取值及其概率。
%--------------------------------------------------------------------
\begin{table}[htp]
\centering
......@@ -110,9 +112,15 @@
\end{table}
%--------------------------------------------------------------------
\parinterval 概率函数是用函数形式给出离散变量每个取值发生的概率,其实就是将变量的概率分布转化为数学表达形式。如果把$A$看做一个离散变量,$a$看做变量$A$的一个取值,那么$\textrm{P}(A)$被称作变量$A$的概率函数,$\textrm{P}(A=a)$被称作$A = a$的概率值,简记为$\textrm{P}(a)$。例如,在相同条件下掷一个骰子50次,用$A$表示投骰子出现的点数这个离散变量,$a_i$表示点数的取值,$\textrm{P}_i$表示$A=a_i$的概率值。表\ref{tab:2-1}$A$的概率分布,给出了$A$的所有取值及其概率。
\parinterval 除此之外,概率函数$\textrm{P}(\cdot)$还具有非负性、归一性等特点,非负性是指,所有的概率函数$\textrm{P}(\cdot)$都必须是大于等于0的数值,概率函数中不可能出现负数,即$\forall{x},\textrm{P}{(x)}\geq{0}$。归一性,又称规范性,简单的说就是所有可能发生的事件的概率总和为1,即$\sum_{x}\textrm{P}{(x)}={1}$
\parinterval 对于离散变量$A$$\textrm{P}(A=a)$是个确定的值,可以表示事件$A=a$的可能性大小;而对于连续变量,求在某个定点处的概率是无意义的,只能求其落在某个取值区间内的概率。因此,用{\small\sffamily\bfseries{概率分布函数}}\index{概率分布函数}$F(x)${\small\sffamily\bfseries{概率密度函数}}\index{概率密度函数}$f(x)$来统一描述随机变量取值的分布情况(如图\ref{fig:2-3})。概率分布函数$F(x)$表示取值小于等于某个值的概率,是概率的累加(或积分)形式。假设$A$是一个随机变量,$a$是任意实数,将函数$F(a)=\textrm{P}\{A\leq a\}$$-\infty<a<\infty $定义为$A$的分布函数。通过分布函数,可以清晰地表示任何随机变量的概率。
\parinterval 除此之外,概率函数$\textrm{P}(\cdot)$还具有非负性、归一性等特点,非负性是指,所有的概率函数$\textrm{P}(\cdot)$都必须是大于等于0的数值,概率函数中不可能出现负数:$\forall{x},\textrm{P}{(x)}\geq{0}$。归一性,又称规范性,简单的说就是所有可能发生的事件的概率总和为1,即$\sum_{x}\textrm{P}{(x)}={1}$
\parinterval 概率密度函数反映了变量在某个区间内的概率变化快慢,概率密度函数的值是概率的变化率,该连续变量的概率也就是对概率密度函数求积分得到的结果。设$f(x) \geq 0$是连续变量$X$的概率密度函数,$X$的分布函数就可以用如下公式定义:
\begin{eqnarray}
F(x)=\int_{-\infty}^x f(x)dx
\label{eq:2-1}
\end{eqnarray}
%----------------------------------------------
\begin{figure}[htp]
......@@ -122,25 +130,15 @@
\label{fig:2-3}
\end{figure}
%-------------------------------------------
\vspace{-1em}
\parinterval 对于离散变量$A$$\textrm{P}(A=a)$是个确定的值,可以表示事件$A=a$的可能性大小;而对于连续变量,求在某个定点处的概率是无意义的,只能求其落在某个取值区间内的概率。因此,用{\small\sffamily\bfseries{概率分布函数}}\index{概率分布函数}$F(x)${\small\sffamily\bfseries{概率密度函数}}\index{概率密度函数}$f(x)$来统一描述随机变量取值的分布情况(如图\ref{fig:2-3})。概率分布函数$F(x)$表示取值小于某个值的概率,是概率的累加(或积分)形式。假设$A$是一个随机变量,$a$是任意实数,将函数$F(a)=\textrm{P}\{A\leq a\}$$-\infty<a<\infty $定义为$A$的分布函数。通过分布函数,可以清晰地表示任何随机变量的概率。
\parinterval 概率密度函数反映了变量在某个区间内的概率变化快慢,概率密度函数的值是概率的变化率,该连续变量的概率也就是对概率密度函数求积分得到的结果。设$f(x) \geq 0$是连续变量$X$的概率密度函数,$X$的分布函数就可以用如下公式定义:
\begin{eqnarray}
F(X)=\int_{-\infty}^x f(x)dx
\label{eq:2-1}
\end{eqnarray}
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
%----------------------------------------------------------------------------------------
\subsection{联合概率、条件概率和边缘概率}
\parinterval {\small\sffamily\bfseries{联合概率}}\index{联合概率}(Joint Probability)\index{Joint Probability}是指多个事件同时发生,每个随机变量满足各自条件的概率,表示为$\textrm{P}(AB)${\small\sffamily\bfseries{条件概率}}\index{条件概率}(Conditional Probability)\index{Conditional Probability}是指$A$$B$为任意的两个事件,在事件$A$已出现的前提下,事件$B$出现的概率,使用$\textrm{P}(B \mid A)$表示。通常来说,$\textrm{P}(B \mid A) \neq \textrm{P}(B)$
\parinterval {\small\sffamily\bfseries{联合概率}}\index{联合概率}(Joint Probability)\index{Joint Probability}是指多个事件共同发生,每个随机变量满足各自条件的概率,表示为$\textrm{P}(AB)$$\textrm{P}(A\cap{B})${\small\sffamily\bfseries{条件概率}}\index{条件概率}(Conditional Probability)\index{Conditional Probability}是指$A$$B$为任意的两个事件,在事件$A$已出现的前提下,事件$B$出现的概率,使用$\textrm{P}(B \mid A)$表示
\parinterval 贝叶斯法则是条件概率计算时的重要依据,条件概率可以表示为
\parinterval 贝叶斯法则(见\ref{sec:2.2.3}小节)是条件概率计算时的重要依据,条件概率可以表示为
\begin{eqnarray}
\textrm{P}{(B|A)} & = & \frac{\textrm{P}(A\cap{B})}{\textrm{P}(A)} \nonumber \\
& = & \frac{\textrm{P}(A)\textrm{P}(B|A)}{\textrm{P}(A)} \nonumber \\
......@@ -148,7 +146,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\label{eq:2-2}
\end{eqnarray}
\parinterval {\small\sffamily\bfseries{边缘概率}}\index{边缘概率}(marginal probability)\index{marginal probability}是和联合概率对应的,它指的是$\textrm{P}(X=a)$$\textrm{P}(Y=b)$,即仅与单个随机变量有关的概率称为边缘概率。对于离散随机变量$X$$Y$,如果知道$\textrm{P}(X,Y)$,则边缘概率$\textrm{P}(X)$可以通过求和的方式得到。对于$\forall x \in X $,有
\parinterval {\small\sffamily\bfseries{边缘概率}}\index{边缘概率}(marginal probability)\index{marginal probability}是和联合概率对应的,它指的是$\textrm{P}(X=a)$$\textrm{P}(Y=b)$,即仅与单个随机变量有关的概率。对于离散随机变量$X$$Y$,如果知道$\textrm{P}(X,Y)$,则边缘概率$\textrm{P}(X)$可以通过求和的方式得到。对于$\forall x \in X $,有
\begin{eqnarray}
\textrm{P}(X=x)=\sum_{y} \textrm{P}(X=x,Y=y)
\label{eq:2-3}
......@@ -156,7 +154,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\parinterval 对于连续变量,边缘概率$\textrm{P}(X)$需要通过积分得到,如下式所示
\begin{eqnarray}
\textrm{P}(X)=\int \textrm{P}(x,y)dy
\textrm{P}(X=x)=\int \textrm{P}(x,y)dy
\label{eq:2-4}
\end{eqnarray}
......@@ -180,7 +178,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\label{fig:2-4}
\end{figure}
%-------------------------------------------
\vspace{-1.3em}
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
%----------------------------------------------------------------------------------------
......@@ -201,15 +199,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\end{eqnarray}
\parinterval 下面的例子有助于更好的理解链式法则,如图\ref{fig:2-5}所示,$A$$B$$C$$D$\\ $E$分别代表五个事件,其中,$A$只和$B$有关,$C$只和$B$$D$有关,$E$只和$C$有关,$B$$D$不依赖其他任何事件。则$\textrm{P}(A,B,C,D,E)$的表达式如下式:
\begin{eqnarray}
& & \textrm{P}(A,B,C,D,E) \nonumber \\
&=&\textrm{P}(E \mid A,B,C,D) \cdot \textrm{P}(A,B,C,D) \nonumber \\
&=&\textrm{P}(E \mid A,B,C,D) \cdot \textrm{P}(D \mid A,B,C) \cdot \textrm{P}(A,B,C) \nonumber \\
&=&\textrm{P}(E \mid A,B,C,D) \cdot \textrm{P}(D \mid A,B,C) \cdot \textrm{P}(C \mid A,B) \cdot \textrm{P}(A,B) \nonumber \\
&=&\textrm{P}(E \mid A,B,C,D) \cdot \textrm{P}(D \mid A,B,C) \cdot \textrm{P}(C \mid A,B) \cdot \textrm{P}(B \mid A) \cdot \textrm{P}(A)
\label{eq:2-7}
\end{eqnarray}
\vspace{-2em}
%----------------------------------------------
\begin{figure}[htp]
\centering
......@@ -219,7 +209,15 @@ F(X)=\int_{-\infty}^x f(x)dx
\label{fig:2-5}
\end{figure}
%-------------------------------------------
\vspace{2.5em}
\begin{eqnarray}
& & \textrm{P}(A,B,C,D,E) \nonumber \\
&=&\textrm{P}(E \mid A,B,C,D) \cdot \textrm{P}(A,B,C,D) \nonumber \\
&=&\textrm{P}(E \mid A,B,C,D) \cdot \textrm{P}(D \mid A,B,C) \cdot \textrm{P}(A,B,C) \nonumber \\
&=&\textrm{P}(E \mid A,B,C,D) \cdot \textrm{P}(D \mid A,B,C) \cdot \textrm{P}(C \mid A,B) \cdot \textrm{P}(A,B) \nonumber \\
&=&\textrm{P}(E \mid A,B,C,D) \cdot \textrm{P}(D \mid A,B,C) \cdot \textrm{P}(C \mid A,B) \cdot \textrm{P}(B \mid A) \cdot \textrm{P}(A)
\label{eq:2-7}
\end{eqnarray}
\parinterval 根据图\ref {fig:2-5} 易知$E$只和$C$有关,所以$\textrm{P}(E \mid A,B,C,D)=\textrm{P}(E \mid C)$$D$不依赖于其他事件,所以$\textrm{P}(D \mid A,B,C)=\textrm{P}(D)$$C$只和$B$$D$有关,所以$\textrm{P}(C \mid A,B)=\textrm{P}(C \mid B)$$B$不依赖于其他事件,所以$\textrm{P}(B \mid A)=\textrm{P}(B)$。最终化简可得:
\begin{eqnarray}
......@@ -231,9 +229,9 @@ F(X)=\int_{-\infty}^x f(x)dx
% NEW SUB-SECTION
%----------------------------------------------------------------------------------------
\subsection{贝叶斯法则}
\subsection{贝叶斯法则}\label{sec:2.2.3}
\parinterval 首先介绍一下全概率公式:{\small\bfnew{全概率公式}}\index{全概率公式}(Law of Total Probability)\index{Law of Total Probability}是概率论中重要的公式,它可以将一个复杂事件发生的概率分解成不同情况的小事件发生概率的和。这里先介绍一个概念——划分。若集合$S$的一个划分事件为$\{B_1,...,B_n\}$是指它们满足$\bigcup_{i=1}^n B_i=S \textrm{}B_iB_j=\varnothing , i,j=1,...,n,i\neq j$。设$\{B_1,...,B_n\}$$S$的一个划分,则事件$A$的全概率公式可以被描述为:
\parinterval 首先介绍一下全概率公式:{\small\bfnew{全概率公式}}\index{全概率公式}(Law of Total Probability)\index{Law of Total Probability}是概率论中重要的公式,它可以将一个复杂事件发生的概率分解成不同情况的小事件发生概率的和。这里先介绍一个概念——划分。集合$S$的一个划分事件为$\{B_1,...,B_n\}$是指它们满足,$\bigcup_{i=1}^n B_i=S \textrm{}B_iB_j=\varnothing , i,j=1,...,n,i\neq j$。此时事件$A$的全概率公式可以被描述为:
\begin{eqnarray}
\textrm{P}(A)=\sum_{k=1}^n \textrm{P}(A \mid B_k)\textrm{P}(B_k)
......@@ -261,7 +259,6 @@ F(X)=\int_{-\infty}^x f(x)dx
& = &{0.36}
\label{eq:2-10}
\end{eqnarray}
\vspace{-2em}
\parinterval {\small\sffamily\bfseries{贝叶斯法则}}\index{贝叶斯法则}(Bayes' rule)\index{Bayes' rule}是概率论中的一个经典公式,通常用于已知$\textrm{P}(A \mid B)$$\textrm{P}(B \mid A)$。可以表述为:设$\{B_1,...,B_n\}$$S$的一个划分,$A$为事件,则对于$i=1,...,n$,有如下公式
\begin{eqnarray}
......@@ -276,9 +273,8 @@ F(X)=\int_{-\infty}^x f(x)dx
& = & \frac { \textrm{P}(A \mid B)\textrm{P}(B) } {\textrm{P}(A \mid B)\textrm{P}(B)+\textrm{P}(A \mid \bar{B}) \textrm{P}(\bar{B})}
\label{eq:2-12}
\end{eqnarray}
\vspace{-1.5em}
\parinterval 贝叶斯公式常用于根据已知的结果来推断使之发生的各因素的可能性。\\ \\
\parinterval 贝叶斯公式常用于根据已知的结果来推断使之发生的各因素的可能性。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -319,7 +315,6 @@ F(X)=\int_{-\infty}^x f(x)dx
\label{fig:2-6}
\end{figure}
%-------------------------------------------
\vspace{0.5em}
\parinterval 自信息处理的是变量单一取值的情况。若量化整个概率分布中的不确定性或信息量,可以用信息熵,记为$\textrm{H}(x)$。其公式如下:
\begin{eqnarray}
......@@ -336,7 +331,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\subsubsection{KL距离}
\parinterval 如果同一个随机变量$X$上有两个独立的概率分布P$(x)$和Q$(x)$,那么可以使用KL距离(``Kullback-Leibler''散度)来衡量这两个分布的不同,这种度量就是{\small\bfnew{相对熵}}\index{相对熵}(Relative Entropy)\index{Relative Entropy}。其公式如下:
\parinterval 如果同一个随机变量$X$上有两个概率分布P$(x)$和Q$(x)$,那么可以使用KL距离(``Kullback-Leibler''散度)来衡量这两个分布的不同,这种度量就是{\small\bfnew{相对熵}}\index{相对熵}(Relative Entropy)\index{Relative Entropy}。其公式如下:
\begin{eqnarray}
\textrm{D}_{\textrm{KL}}(\textrm{P}\parallel \textrm{Q}) & = & \sum_{x \in \textrm{X}} [ \textrm{P}(x)\log \frac{\textrm{P}(x) }{ \textrm{Q}(x) } ] \nonumber \\
& = & \sum_{x \in \textrm{X} }[ \textrm{P}(x)(\log\textrm{P}(x)-\log \textrm{Q}(x))]
......@@ -350,6 +345,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\item 非负性,即$\textrm{D}_{\textrm{KL}} (\textrm{P} \parallel \textrm{Q}) \ge 0$,等号成立条件是$\textrm{P}$$\textrm{Q}$相等。
\vspace{0.5em}
\item 不对称性,即$\textrm{D}_{\textrm{KL}} (\textrm{P} \parallel \textrm{Q}) \neq \textrm{D}_{\textrm{KL}} (\textrm{Q} \parallel \textrm{P})$,所以$\textrm{KL}$距离并不是常用的欧式空间中的距离。为了消除这种不确定性,有时也会使用$\textrm{D}_{\textrm{KL}} (\textrm{P} \parallel \textrm{Q})+\textrm{D}_{\textrm{KL}} (\textrm{Q} \parallel \textrm{P})$作为度量两个分布差异性的函数。
\vspace{0.5em}
\end{itemize}
%----------------------------------------------------------------------------------------
......@@ -407,7 +403,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\end{definition}
%-------------------------------------------
\parinterval 从语言学的角度来看,普遍认为词是可以单独运用的、包含意义的基本单位。这样可以使用有限的词组合出无限的句子,这也正体现出自然语言的奇妙之处。
\parinterval 从语言学的角度来看,人们普遍认为词是可以单独运用的、包含意义的基本单位。这样可以使用有限的词组合出无限的句子,这也正体现出自然语言的奇妙之处。
\parinterval 不过,机器翻译并不仅仅局限在语言学定义的单词。比如,神经机器翻译中广泛使用的BPE子词切分方法(见第七章),可以被理解为将词的一部分也进行切开,也就是得到词片段送给机器翻译系统使用。比如,对如下英文字符串,可以得到如下切分结果
\vspace{0.5em}
......@@ -441,7 +437,6 @@ F(X)=\int_{-\infty}^x f(x)dx
\parinterval 但是,基于词典的分词方法很``硬''。这是因为自然语言非常灵活,经常出现歧义,用词典定义的合法单词之间有重叠的交叉型歧义就很难解决。图\ref{fig:2-9} 就给出了上面例子中的交叉型歧义,从词典中查看,``实现''和``现在''都是合法的单词,但是在句子中二者有重叠,因此词典无法告诉我们哪个结果是正确的。
\setlength{\belowcaptionskip}{-0.5em}
%----------------------------------------------
\begin{figure}[htp]
\centering
......@@ -473,7 +468,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\begin{itemize}
\vspace{0.5em}
\item {\small\bfnew{训练}}\index{训练}(Training)\index{Training}。利用标注数据,对统计模型的参数进行学习。\\
\item {\small\bfnew{训练}}\index{训练}(Training)\index{Training}。利用标注数据,对统计模型的参数进行学习。
\vspace{0.5em}
\item {\small\bfnew{推断}}\index{推断}(Inference)\index{Inference}。利用学习到的模型和参数,对新的句子进行切分。
\vspace{0.5em}
......@@ -490,6 +485,7 @@ F(X)=\int_{-\infty}^x f(x)dx
%-------------------------------------------
\parinterval\ref{fig:2-10} 给出了一个基于统计建模的汉语分词实例。左侧是标注数据,其中每个句子是已经经过人工标注的分词结果(单词用斜杠分开)。之后,建立一个统计模型,记为$\textrm{P}(\cdot)$。模型通过在标注数据上的学习来对问题进行描述,即学习$\textrm{P}(\cdot)$。最后,对于新的未分词的句子,使用模型$\textrm{P}(\cdot)$对每个可能的切分方式进行概率估计,之后选择概率最高的切分结果输出。
\vspace{-0.5em}
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
......@@ -497,7 +493,8 @@ F(X)=\int_{-\infty}^x f(x)dx
\subsubsection{掷骰子游戏}
\parinterval 上述过程的核心在于从数据中学习一种对分词现象的统计描述,即学习函数$\textrm{P}(\cdot)$。如何让计算机利用分词好的数据学习到分词的知识呢?可以先看一个有趣的实例(图\ref{fig:2-11}),用生活中比较常见的掷骰子来说,掷一个骰子,玩家猜一个数字,猜中就算赢,按照一般的常识,随便选一个数字,获胜的概率是一样的,即所有选择的获胜概率仅是$1/6$。因此这个游戏玩家很难获胜,除非运气很好。假设进行一次游戏,玩家随便选了一个数字,比如是1,投掷30骰子,得到命中$7/30 > 1/6$,还不错。
\parinterval 上述过程的核心在于从数据中学习一种对分词现象的统计描述,即学习函数$\textrm{P}(\cdot)$。如何让计算机利用分词好的数据学习到分词的知识呢?可以先看一个有趣的实例(图\ref{fig:2-11}),用生活中比较常见的掷骰子来说,掷一个骰子,玩家猜一个数字,猜中就算赢,按照一般的常识,随便选一个数字,获胜的概率是一样的,即所有选择的获胜概率仅是$1/6$。因此这个游戏玩家很难获胜,除非运气很好。假设进行一次游戏,玩家随便选了一个数字,比如是1,投掷30次骰子,得到命中$7/30 > 1/6$,还不错。
\vspace{-0.5em}
%----------------------------------------------
\begin{figure}[htp]
......@@ -509,7 +506,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\end{figure}
%-------------------------------------------
\vspace{0.5em}
\vspace{-0.5em}
\parinterval 似乎玩家的胜利只能来源于运气。不过,请注意,这里的假设``随便选一个数字''本身就是一个概率模型,它对骰子的六个面的出现做了均匀分布假设。
\begin{eqnarray}
\textrm{P(``1'')}=\textrm{P(``2'')}=...=\textrm{P(``5'')}=\textrm{P(``6'')}=1/6
......@@ -517,7 +514,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\end{eqnarray}
\vspace{-0.5em}
\parinterval 但是这个游戏没有人规定骰子是均匀的(有些被坑了的感觉)。但是如果骰子的六个面不均匀呢?我们可以用一种更加``聪明''的方式定义一种新的模型,即定义骰子的每一个面都以一定的概率出现,而不是相同的概率。描述如公式\ref{eq:2-18},这里,$\theta_1 \sim \theta_5$可以被看作是模型的参数,因此这个模型的自由度是5。对于这样的模型,参数确定了,模型也就确定了。
\parinterval 但是这个游戏没有人规定骰子是均匀的(有些被坑了的感觉)。如果骰子的六个面不均匀呢?我们可以用一种更加``聪明''的方式定义一种新的模型,即定义骰子的每一个面都以一定的概率出现,而不是相同的概率。描述如下:
\begin{eqnarray}
\textrm{P(``1'')} &=&\theta_1 \nonumber \\
\textrm{P(``2'')} &=&\theta_2 \nonumber \\
......@@ -528,7 +525,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\label{eq:2-18}
\end{eqnarray}
\parinterval 但是,新的问题来了,在定义骰子每个面的概率后,如何求出具体的值呢?一种常用的方法是,从大量实例中学习模型参数,这个方法也是常说的{\small\bfnew{参数估计}}\index{参数估计}(Parameter Estimation)\index{Parameter Estimation}。可以将这个不均匀的骰子先实验性的掷很多次,这可以被看作是独立同分布的若干次采样,比如$X$ 次,发现``1'' 出现$X_1$ 次,``2'' 出现$X_2$ 次,以此类推,得到了各个面出现的次数。假设掷骰子中每个面出现的概率符合多项式分布,通过简单的概率论知识可以知道每个面出现概率的极大似然估计为:
\noindent 这里,$\theta_1 \sim \theta_5$可以被看作是模型的参数,因此这个模型的自由度是5。对于这样的模型,参数确定了,模型也就确定了。但是,新的问题来了,在定义骰子每个面的概率后,如何求出具体的值呢?一种常用的方法是,从大量实例中学习模型参数,这个方法也是常说的{\small\bfnew{参数估计}}\index{参数估计}(Parameter Estimation)\index{Parameter Estimation}。可以将这个不均匀的骰子先实验性的掷很多次,这可以被看作是独立同分布的若干次采样,比如$X$ 次,发现``1'' 出现$X_1$ 次,``2'' 出现$X_2$ 次,以此类推,得到了各个面出现的次数。假设掷骰子中每个面出现的概率符合多项式分布,通过简单的概率论知识可以知道每个面出现概率的极大似然估计为:
\begin{eqnarray}
\textrm{P(``i'')}=\frac {X_i}{X}
\label{eq:2-19}
......@@ -545,11 +542,8 @@ F(X)=\int_{-\infty}^x f(x)dx
\end{figure}
%-------------------------------------------
\vspace{0.5em}
\parinterval 于是,我们看到了一个有倾向性的模型(图 \ref{fig:2-13}):在这样的预先实验基础上,可以知道如果再次玩掷骰子游戏的话,选则数字``4''获胜的可能性是最大的。
\parinterval 通过上面这个掷骰子的游戏,可以得到一个道理:{\small\sffamily\bfseries{上帝是不公平的}}。因为在``公平''的世界中,没有任何一个模型可以学到有价值的事情。从机器学习的角度来看,所谓的``不公平''实际上这是客观事物中蕴含的一种{\small\sffamily\bfseries{偏置}}\index{偏置}(Bias)\index{Bias},也就是很多事情天然就有对某些情况有倾向。而图像处理、自然语言处理等问题中绝大多数都存在着偏置。比如,我们翻译一个英文单词的时候,它最可能的翻译结果往往就是那几个词。设计统计模型的目的正是要学习这种偏置,之后利用这种偏置对新的问题做出足够好的决策。
%----------------------------------------------
\begin{figure}[htp]
\centering
......@@ -558,7 +552,8 @@ F(X)=\int_{-\infty}^x f(x)dx
\label{fig:2-13}
\end{figure}
%-------------------------------------------
\vspace{-0.5em}
\parinterval 通过上面这个掷骰子的游戏,可以得到一个道理:{\small\sffamily\bfseries{上帝是不公平的}}。因为在``公平''的世界中,没有任何一个模型可以学到有价值的事情。从机器学习的角度来看,所谓的``不公平''实际上这是客观事物中蕴含的一种{\small\sffamily\bfseries{偏置}}\index{偏置}(Bias)\index{Bias},也就是很多事情天然就有对某些情况有倾向。而图像处理、自然语言处理等问题中绝大多数都存在着偏置。比如,我们翻译一个英文单词的时候,它最可能的翻译结果往往就是那几个词。设计统计模型的目的正是要学习这种偏置,之后利用这种偏置对新的问题做出足够好的决策。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
......@@ -627,7 +622,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\label{eq:2-20}
\end{eqnarray}
}
\vspace{0.5em}
\parinterval 以``确实现在数据很多''这个实例来说,如果把这句话按照``确实/现在/数据/很/多''这样的方式进行切分,这个句子切分的概率P(``确实/现在/数据/很/多'')可以通过每个词出现概率相乘的方式进行计算。
\begin{eqnarray}
......@@ -640,10 +635,6 @@ F(X)=\int_{-\infty}^x f(x)dx
这个假设也是自然语言处理中1-gram语言模型假设,即当前词的生成与任何历史都无关。当然,独立性假设并不能完美描述客观世界的问题,但是它大大化简了问题的复杂度。
\parinterval 最后再整体看一下分词系统的学习和使用过程。如图\ref {fig:2-17}所示,我们利用大量人工标注好的分词数据,通过统计学习方法获得一个统计模型$\textrm{P}(\cdot)$,给定任意分词结果$W=w_1 w_2...w_m$,都能通过$\textrm{P}(W)=\textrm{P}(w_1) \cdot \textrm{P}(w_2 ) \cdot ... \cdot \textrm{P}(w_m)$计算这种切分的概率值。
\parinterval 经过充分训练的统计模型$\textrm{P}(\cdot)$就是得到的分词模型。对于输入的新句子$S$,通过这个模型找到最佳的分词结果$W^*$输出。假设输入句子$S$是``确实现在数据很多'',可以通过列举获得不同切分方式的概率,其中概率最高的切分方式,就是系统的目标输出。
%----------------------------------------------
\begin{figure}[htp]
\centering
......@@ -653,7 +644,10 @@ F(X)=\int_{-\infty}^x f(x)dx
\end{figure}
%-------------------------------------------
\vspace{0.5em}
\parinterval 最后再整体看一下分词系统的学习和使用过程。如图\ref {fig:2-17}所示,我们利用大量人工标注好的分词数据,通过统计学习方法获得一个统计模型$\textrm{P}(\cdot)$,给定任意分词结果$W=w_1 w_2...w_m$,都能通过$\textrm{P}(W)=\textrm{P}(w_1) \cdot \textrm{P}(w_2 ) \cdot ... \cdot \textrm{P}(w_m)$计算这种切分的概率值。
\parinterval 经过充分训练的统计模型$\textrm{P}(\cdot)$就是得到的分词模型。对于输入的新句子$S$,通过这个模型找到最佳的分词结果$W^*$输出。假设输入句子$S$是``确实现在数据很多'',可以通过列举获得不同切分方式的概率,其中概率最高的切分方式,就是系统的目标输出。
\parinterval 这种分词方法也被称作基于1-gram语言模型的分词,或全概率分词,使用标注好的分词数据进行学习,获得分词模型。这种方法最大的优点是整个学习过程(模型训练过程)和推导过程(处理新句子进行切分的过程)都是全自动进行的。这种方法虽然简单,但是其效率很高,因此被广泛应用在工业界系统里。
\parinterval 当然,真正的分词系统还需要解决很多其他问题,比如使用动态规划等方法高效搜索最优解以及如何处理未见过的词等等,由于本节的重点是介绍中文分词的基础方法和统计建模思想,因此无法覆盖所有中文分词的技术内容,有兴趣的读者可以参考\ref{sec2:summary}节的相关文献做进一步深入研究。
......@@ -663,10 +657,9 @@ F(X)=\int_{-\infty}^x f(x)dx
%----------------------------------------------------------------------------------------
\sectionnewpage
\vspace{-0.5em}
\section{$n$-gram语言模型 }
\parinterval 在基于统计的汉语分词模型中,我们通过``大题小做''的技巧,利用独立性假设把整个句子的单词切分概率转化为每个单个词出现概率的乘积。这里,每个单词也被称作1-gram(或uni-gram),而1-gram概率的乘积实际上也是在度量词序列出现的可能性(记为$\textrm{P}(w_1 w_2...w_m)$)。这种计算整个单词序列概率$\textrm{P}(w_1 w_2...w_m)$的方法被称为统计语言模型。1-gram语言模型是最简单的一种语言模型,它没有考虑任何的上下文。很自然的一个问题是:能否考虑上下文信息构建更强大的语言模型,进而得到更准确的分词结果。下面将进一步介绍更加通用的$n$-gram语言模型,它在机器翻译及其他自然语言处理任务中有更加广泛的应用。\\ \\
\parinterval 在基于统计的汉语分词模型中,我们通过``大题小做''的技巧,利用独立性假设把整个句子的单词切分概率转化为每个单个词出现概率的乘积。这里,每个单词也被称作1-gram(或uni-gram),而1-gram概率的乘积实际上也是在度量词序列出现的可能性(记为$\textrm{P}(w_1 w_2...w_m)$)。这种计算整个单词序列概率$\textrm{P}(w_1 w_2...w_m)$的方法被称为统计语言模型。1-gram语言模型是最简单的一种语言模型,它没有考虑任何的上下文。很自然的一个问题是:能否考虑上下文信息构建更强大的语言模型,进而得到更准确的分词结果。下面将进一步介绍更加通用的$n$-gram语言模型,它在机器翻译及其他自然语言处理任务中有更加广泛的应用。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -684,7 +677,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\end{definition}
%-------------------------------------------
\parinterval 直接求$\textrm{P}(w_1 w_2...w_m)$并不简单,因为如果把整个词串$w_1 w_2...w_m$作为一个变量,模型的参数量会非常大。$w_1 w_2...w_m$$|V|^m$种可能性,这里$|V|$表示词汇表大小。显然,当$m$ 增大的时候会使模型复杂度会急剧增加,甚至都无法进行存储和计算。既然把$w_1 w_2...w_m$作为一个变量不好处理,就可以考虑对这个序列的生成过程进行分解。使用链式法则,很容易得到
\parinterval 直接求$\textrm{P}(w_1 w_2...w_m)$并不简单,因为如果把整个词串$w_1 w_2...w_m$作为一个变量,模型的参数量会非常大。$w_1 w_2...w_m$$|V|^m$种可能性,这里$|V|$表示词汇表大小。显然,当$m$ 增大时,模型的复杂度会急剧增加,甚至都无法进行存储和计算。既然把$w_1 w_2...w_m$作为一个变量不好处理,就可以考虑对这个序列的生成过程进行分解。使用链式法则,很容易得到
\begin{eqnarray}
\textrm{P}(w_1 w_2...w_m)=\textrm{P}(w_1)\textrm{P}(w_2|w_1)\textrm{P}(w_3|w_1 w_2)...\textrm{P}(w_m|w_1 w_2...w_{m-1})
\label{eq:2-22}
......@@ -694,7 +687,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\parinterval 换一个角度看,$\textrm{P}(w_m|w_1 w_2...w_{m-1})$体现了一种基于``历史''的单词生成模型,也就是把前面生成的所有单词作为``历史'',并参考这个``历史''生成当前单词。但是这个``历史''的长度和整个序列长度是相关的,也是一种长度变化的历史序列。为了化简问题,一种简单的想法是使用定长历史,比如,每次只考虑前面$n-1$个历史单词来生成当前单词,这就是$n$-gram语言模型。这个模型的数学描述如下:
\begin{eqnarray}
\textrm{P}(w_m|w_{m-n+1}...w_{m-1})=\textrm{P}(w_m|w_1 w_2...w_{m-1})
\textrm{P}(w_m|w_1 w_2...w_{m-1}) \approx \textrm{P}(w_m|w_{m-n+1}...w_{m-1})
\label{eq:2-23}
\end{eqnarray}
......@@ -716,24 +709,25 @@ F(X)=\int_{-\infty}^x f(x)dx
}
\end{center}
\parinterval 可以看到,1-gram语言模型只是$n$-gram语言模型的一种特殊形式。$n$-gram的优点在于,它所使用的历史信息是有限的,即$n-1$个单词。这种性质也反映了经典的马尔可夫链的思想\cite{liuke-markov-2004}\cite{resnick1992adventures}有时也被称作马尔可夫假设或者马尔可夫属性。因此$n$-gram也可以被看作是变长序列上的一种马尔可夫模型,比如,2-gram语言模型对应着1阶马尔可夫模型,3-gram语言模型对应着2阶马尔可夫模型,以此类推。
\parinterval 可以看到,1-gram语言模型只是$n$-gram语言模型的一种特殊形式。$n$-gram的优点在于,它所使用的历史信息是有限的,即$n-1$个单词。这种性质也反映了经典的马尔可夫链的思想\cite{liuke-markov-2004}\cite{resnick1992adventures}有时也被称作马尔可夫假设或者马尔可夫属性。因此$n$-gram也可以被看作是变长序列上的一种马尔可夫模型,比如,2-gram语言模型对应着1阶马尔可夫模型,3-gram语言模型对应着2阶马尔可夫模型,以此类推。
\parinterval 那么,如何计算$\textrm{P}(w_m|w_{m-n+1} ... w_{m-1})$呢?有很多种选择,比如:
\begin{itemize}
\vspace{0.5em}
\item {\small\bfnew{极大似然估计}}\index{极大似然估计}直接利用词序列在训练数据中出现的频度计算出$\textrm{P}(w_m|w_{m-n+1}$\\$... w_{m-1})$
\item {\small\bfnew{极大似然估计}}\index{极大似然估计}直接利用词序列在训练数据中出现的频度计算出$\textrm{P}(w_m|w_{m-n+1}$\\$... w_{m-1})$
\begin{eqnarray}
\textrm{P}(w_m|w_{m-n+1}...w_{m-1})=\frac{\textrm{count}(w_{m-n+1}...w_m)}{\textrm{count}(w_{m-n+1}...w_{m-1})}
\label{eq:2-24}
\vspace{0.5em}
\end{eqnarray}
其中,$\textrm{count}(\cdot)$是在训练数据中统计频次的函数。
\vspace{0.5em}
\item {\small\bfnew{人工神经网络方法}}\index{人工神经网络方法}:构建一个人工神经网络估计$\textrm{P}(w_m|w_{m-n+1} ... w_{m-1})$的值,比如,可以构建一个前馈神经网络来对$n$-gram进行建模。
\vspace{0.5em}
\vspace{0.3em}
\item {\small\bfnew{人工神经网络方法}}\index{人工神经网络方法}。构建一个人工神经网络估计$\textrm{P}(w_m|w_{m-n+1} ... w_{m-1})$的值,比如,可以构建一个前馈神经网络来对$n$-gram进行建模。
\end{itemize}
\vspace{0.3em}
\parinterval 极大似然估计方法和前面介绍的统计分词中的方法是一致的,它的核心是使用$n$-gram出现的频度进行参数估计,因此也是自然语言处理中一类经典的$n$-gram方法。基于人工神经网络的方法在近些年也非常受关注,它直接利用多层神经网络对问题的输入$(w_{m-n+1}...w_{m-1})$和输出$\textrm{P}(w_m|w_{m-n+1} ... w_{m-1})$进行建模,而模型的参数通过网络中神经元之间连接的权重进行体现。严格意义上了来说,基于人工神经网络的方法并不算基于$n$-gram的方法,或者说它并没有显性记录$n$-gram的生成概率,也不依赖$n$-gram的频度进行参数估计。为了保证内容的连贯性,本章将仍以传统$n$-gram语言模型为基础进行讨论,基于人工神经网络的方法将会在第五章和第六章进行详细介绍。
......@@ -761,7 +755,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\label{eq:2-26}
\end{eqnarray}
\parinterval 显然,这个结果是不能接受的。因为即使语料中没有 ``确实''和``现在''两个词连续出现,但是这种搭配也是客观存在的。这时简单的用极大似然估计得到概率却是0,导致整个切分结果的概率为0。 更常见的问题是那些根本没有出现在词表中的词,称为{\small\sffamily\bfseries{未登录词}}\index{未登录词}(Out-of-Vocabulary Word,OOV Word)\index{Out-of-Vocabulary Word,OOV Word},比如一些生僻词,可能模型训练阶段从来没有看到过,这时模型仍然会给出0 概率。图\ref{fig:2-18}展示了一个真实语料库中词语出现频度的分布,可以看到绝大多数词都是低频词。
\parinterval 显然,这个结果是不能接受的。因为即使语料中没有 ``确实''和``现在''两个词连续出现,这种搭配也是客观存在的。这时简单的用极大似然估计得到概率却是0,导致整个切分结果的概率为0。 更常见的问题是那些根本没有出现在词表中的词,称为{\small\sffamily\bfseries{未登录词}}\index{未登录词}(Out-of-Vocabulary Word,OOV Word)\index{Out-of-Vocabulary Word,OOV Word},比如一些生僻词,可能模型训练阶段从来没有看到过,这时模型仍然会给出0 概率。图\ref{fig:2-18}展示了一个真实语料库中词语出现频度的分布,可以看到绝大多数词都是低频词。
%----------------------------------------------
\begin{figure}[htp]
......@@ -785,6 +779,7 @@ F(X)=\int_{-\infty}^x f(x)dx
\parinterval {\small\bfnew{加法平滑}}\index{加法平滑}(Additive Smoothing)\index{Additive Smoothing}是一种简单的平滑技术。本小节首先介绍这一方法,希望通过它了解平滑算法的思想。通常情况下,系统研发者会利用采集到的语料库来模拟真实的全部语料库。当然,没有一个语料库能覆盖所有的语言现象。常见的一个问题是,使用的语料无法涵盖所有的词汇。因此,直接依据这样语料所获得的统计信息来获取语言模型就会产生偏差。假设依据某语料$C$ (从未出现`` 确实 现在''二元语法),评估一个已经分好词的句子$S$ =``确实/现在/物价/很/高''的概率。当计算``确实/现在''的概率时,$\textrm{P}(S) = 0$。显然这个结果是不合理的。
\parinterval 加法平滑方法假设每个$n$-gram出现的次数比实际统计次数多$\theta$次,$0 \le \theta\le 1$。这样,计算概率的时候分子部分不会为0。重新计算$\textrm{P}(\textrm{现在}|\textrm{确实})$,可以得到:
\begin{eqnarray}
\textrm{P}(\textrm{现在}|\textrm{确实}) & = & \frac{\theta + \textrm{count}(\textrm{确实/现在})}{\sum_{w}^{|V|}(\theta + \textrm{count}(\textrm{确实/}w))} \nonumber \\
& = & \frac{\theta + \textrm{count}(\textrm{确实/现在})}{\theta{|V|} + \textrm{count}(\textrm{确实})}
......@@ -850,14 +845,13 @@ N & = & \sum_{r=0}^{\infty}{r^{*}n_r} \nonumber \\
\parinterval 这里使用一个例子来说明这个方法是如何对事件出现的可能性进行平滑的。仍然考虑在加法平滑法中统计单词的例子,根据古德-图灵方法进行修正如表\ref{tab:2-21}所示。
\vspace{0.5em}
%------------------------------------------------------
\begin{table}[htp]{
\begin{center}
\caption{单词出现频次及古德-图灵平滑结果}
{
\begin{tabular}{l|lll}
\rule{0pt}{10pt} $r$ & $n_r$ & $n^*$ & $\textrm{P}_r$\\ \hline
\rule{0pt}{10pt} $r$ & $n_r$ & $r^*$ & $\textrm{P}_r$\\ \hline
\rule{0pt}{10pt} 0 & 14 & 0.21 & 0.018 \\
\rule{0pt}{10pt} 1 & 3 & 0.67 & 0.056 \\
\rule{0pt}{10pt} 2 & 1 & 3 & 0.25 \\
......@@ -959,7 +953,6 @@ c_{\textrm{KN}}(\cdot) = \left\{\begin{array}{ll}
%----------------------------------------------------------------------------------------
\sectionnewpage
\vspace{-0.5em}
\section{句法分析(短语结构分析)}
\parinterval 通过前面两节的内容,已经了解什么叫做``词''、如何对分词问题进行统计建模。同时也了解了如何对词序列的生成进行概率描述。无论是分词还是语言模型都是句子浅层词串信息的一种表示。对于一个自然语言句子来说,它更深层次的结构信息可以通过句法信息来描述,而句法信息也是机器翻译和自然语言处理其他任务中常用的知识之一。
......@@ -980,14 +973,13 @@ c_{\textrm{KN}}(\cdot) = \left\{\begin{array}{ll}
\end{figure}
%---------------------------
\vspace{0.3em}
\parinterval\ref{fig:2-20}右侧展示的是另一种句法结构,被称作依存句法树。依存句法树表示了句子中单词和单词之间的依存关系。比如,从这个例子可以了解,``猫''依赖``喜欢'',``吃''依赖``喜欢'',``鱼''依赖``吃''。
\parinterval 短语结构树和依存句法树的结构和功能有很大不同。短语结构树的叶子节点是单词,中间节点是词性或者短语句法标记。在短语结构分析中,通常把单词称作{\small\bfnew{终结符}}\index{终结符}(Terminal)\index{Terminal},把词性称为{\small\bfnew{预终结符}}\index{预终结符}(Pre-terminal)\index{Pre-terminal},而把其他句法标记称为{\small\bfnew{非终结符}}\index{非终结符}(Non-terminal)\index{Non-terminal}。依存句法树没有预终结符和非终结符,所有的节点都是句子里的单词,通过不同节点间的连线表示句子中各个单词之间的依存关系。每个依存关系实际上都是有方向的,头和尾分别指向``接受''和``发出''依存关系的词。依存关系也可以进行分类,图\ref{fig:2-20}中我们对每个依存关系的类型都进行了标记,这也被称作是有标记的依存分析。如果不生成这些标记,这样的句法分析被称作无标记的依存分析。
\parinterval 虽然短语结构树和依存树的句法表现形式有很大不同,但是它们在某些条件下能相互转化。比如,可以使用启发性规则将短语结构树自动转化为依存树。从应用的角度,依存分析由于形式更加简单,而且直接建模词语之间的依赖,因此在自然语言处理领域中受到很多关注。在机器翻译中,无论是哪种句法树结构,都已经被证明会对机器翻译系统产生帮助。特别是短语结构树,在机器翻译中的应用历史更长,研究更为深入,因此本节将会以短语结构分析为例介绍句法分析的相关概念。
\parinterval 而句法分析到底是什么呢?简单的理解,句法分析就是在小学语文课程中学习的句子成分的分析,以及对句子中各个成分内部、外部关系的判断。更规范一些的定义,可以参照维基百科和百度百科的句法分析的解释。
\parinterval 而句法分析到底是什么呢?简单的理解,句法分析就是在小学语文课程中学习的句子成分的分析,以及对句子中各个成分内部、外部关系的判断。更规范一些的定义,可以参照百度百科维基百科的句法分析的解释。
%-------------------------------------------
\vspace{-0.0em}
......@@ -1005,15 +997,16 @@ c_{\textrm{KN}}(\cdot) = \left\{\begin{array}{ll}
\begin{itemize}
\vspace{0.5em}
\item 形式化的文法:描述语言结构的定义,由文法规则组成
\item 形式化的文法:描述语言结构的定义,由文法规则组成
\vspace{0.5em}
\item 符号串:在本节中,符号串就是指词串,由前面提到的分词系统生成
\item 符号串:在本节中,符号串就是指词串,由前面提到的分词系统生成
\vspace{0.5em}
\item 分析:使用形式文法对符号串进行分析的具体方法,在这里指实现分析的计算机算法
\item 分析:使用形式文法对符号串进行分析的具体方法,在这里指实现分析的计算机算法
\vspace{0.5em}
\end{itemize}
\parinterval 以上三点是实现一个句法分析器的要素。本节的后半部分会对相关的概念和技术方法进行介绍。
\vspace{-0.5em}
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -1065,7 +1058,6 @@ S=\{\textrm{IP}\} \nonumber
最后,文法的规则集定义图\ref{fig:2-21}所示(其中$r_i$为规则的编号)
%\setlength{\belowcaptionskip}{-1em}
%----------------------------------------------
\begin{figure}[htp]
\centering
......@@ -1133,8 +1125,7 @@ s_0 \overset{r_1}{\Rightarrow} s_1 \overset{r_2}{\Rightarrow} s_2 \overset{r_3}{
\end{figure}
%-------------------------------------------
\vspace{0.5em}
\parinterval 通常,可以把推导简记为$d=r_1 \circ r_2 \circ ... \circ r_n$,其中$ \circ $表示规则的组合。显然,$d$也对应了树形结构,也就是句法分析结果。从这个角度看,推导就是描述句法分析树的一种方式。此外,规则的推导也把规则的使用过程与生成的字符串对应起来。一个推导所生成的字符串,也被称作文法所产生的一个{\small\bfnew{句子}}\index{句子}(Sentence)\index{Sentence}。而一个文法所能生成的所有句子是这个文法所对应的{\small\bfnew{语言}}\index{语言}(Language)\index{Language}
\parinterval 通常,可以把推导简记为$d=r_1 \circ r_2 \circ ... \circ r_n$,其中$ \circ $表示规则的组合。显然,$d$也对应了树形结构,也就是句法分析结果。从这个角度看,推导就是描述句法分析树的一种方式。此外,规则的推导也把规则的使用过程与生成的字符串对应起来。一个推导所生成的字符串,也被称作文法所产生的一个{\small\bfnew{句子}}\index{句子}(Sentence)\index{Sentence}。而一个文法所能生成的所有句子的集合是这个文法所对应的{\small\bfnew{语言}}\index{语言}(Language)\index{Language}
\parinterval 但是,句子和规则的推导并不是一一对应的。同一个句子,往往有很多推导的方式,这种现象被称为{\small\bfnew{歧义}}\index{歧义}(Ambiguity)\index{Ambiguity}。甚至同一棵句法树,也可以对应不同的推导。图\ref{fig:2-23} 给出同一棵句法树所对应的两种不同的规则推导。
......@@ -1148,11 +1139,12 @@ s_0 \overset{r_1}{\Rightarrow} s_1 \overset{r_2}{\Rightarrow} s_2 \overset{r_3}{
\end{figure}
%-------------------------------------------
\vspace{0.5em}
\parinterval 显然,规则顺序的不同会导致句法树的推导这一确定的过程变得不确定。因此,需要进行{\small\bfnew{消歧}}\index{消歧}(Disambiguation)\index{Disambiguation}。这里,可以使用启发式方法:要求规则使用都服从最左优先原则,这样得到的推导被称为{\small\bfnew{最左优先推导}}\index{最左优先推导}(Left-most Derivation)\index{Left-most Derivation}。图\ref{fig:2-23}中的推导1 就是符合最左优先原则的推导。
\parinterval 这样,对于一个上下文无关文法,每一棵句法树都有唯一的最左推导与之对应。于是,句法分析可以被描述为:对于一个句子找到能够生成它的最佳推导,这个推导所对应的句法树就是这个句子的句法分析结果。
\parinterval 不过问题又回来了,怎样才能知道什么样的推导或者句法树是``最佳''的呢?如图\ref{fig:2-24}所示,对于语言学专家,他们可以很确定的分辨出哪些句法树是正确的,哪些句法树是错误。甚至普通人也可以通过一些课本中学到的知识产生一些模糊的判断。而计算机如何进行判别呢?沿着前面介绍的统计建模的思想,计算机可以得出不同句法树出现的概率,进而选择概率最高的句法树作为输出,而这正是统计句法分析所做的事情。
%-------------------------------------------
\begin{figure}[htp]
\centering
......@@ -1162,8 +1154,6 @@ s_0 \overset{r_1}{\Rightarrow} s_1 \overset{r_2}{\Rightarrow} s_2 \overset{r_3}{
\end{figure}
%-------------------------------------------
\parinterval 不过问题又回来了,怎样才能知道什么样的推导或者句法树是``最佳''的呢?对于语言学专家来说,可以很确定的分辨出哪些句法树是正确的,哪些句法树是错误。甚至对于普通人,也通过一些课本中学到知识产生一些模糊的判断。而计算机如何进行判别呢?沿着前面介绍的统计建模的思想,计算机可以得出不同句法树出现的概率,进而选择概率最高的句法树作为输出,而这正是统计句法分析所做的事情
\parinterval 在统计句法分析中,需要对每个推导进行统计建模,于是定义一个模型$\textrm{P}( \cdot )$,对于任意的推导$d$,都可以用$\textrm{P}(d)$计算出推导$d$的概率。这样,给定一个输入句子,我们可以对所有可能的推导用$\textrm{P}(d)$计算其概率值,并选择概率最大的结果作为句法分析的结果输出(图\ref{fig:2-25})。
%-------------------------------------------
......@@ -1234,6 +1224,7 @@ r_6: & & \textrm{VP} \to \textrm{VV}\ \textrm{NN} \nonumber
\parinterval 这也对应了词串``吃\ 鱼''的生成过程。首先,从起始非终结符VP开始,使用规则$r_6$生成两个非终结符VV和NN;进一步,分别使用规则$r_3$$r_4$从VV和NN进一步生成单词``吃''和``鱼''。整个过程的概率等于三条规则概率的乘积。
\parinterval 新的问题又来了,如何得到规则的概率呢?这里仍然可以从数据中学习文法规则的概率。假设有人工标注的数据,它包括很多人工标注句法树的句法,称之为{\small\bfnew{树库}}\index{树库}(Treebank)\index{Treebank}。然后,对于规则$\textrm{r}:\alpha \to \beta$可以使用极大似然估计:
\begin{eqnarray}
\textrm{P}(r) = \frac{\text{规则$r$在树库中出现的次数}}{\alpha \text{在树库中出现的次数}}
\label{eq:2-49}
......@@ -1250,9 +1241,8 @@ r_6: & & \textrm{VP} \to \textrm{VV}\ \textrm{NN} \nonumber
\end{figure}
%-------------------------------------------
\vspace{0.5em}
\parinterval\ref{fig:2-27}展示了基于统计的句法分析的流程。首先,通过树库上的统计,获得各个规则的概率,这样就得到了一个上下文无关句法分析模型$\textrm{P}( \cdot )$。对于任意句法分析结果$d=r_1 \circ r_2 \circ ... \circ r_n$,都能通过如下公式计算其概率值:
\setlength{\belowdisplayskip}{1pt}
\begin{equation}
\textrm{P}(d)= \prod_{i=1}^{n}\textrm{P}(r_i)
\end{equation}
......@@ -1266,7 +1256,6 @@ r_6: & & \textrm{VP} \to \textrm{VV}\ \textrm{NN} \nonumber
\end{figure}
%-------------------------------------------
\vspace{1em}
\parinterval 在获取统计分析模型后,就可以使用模型对任意句子进行分析,计算每个句法分析树的概率,并输出概率最高的树作为句法分析的结果。
%----------------------------------------------------------------------------------------
......@@ -1274,7 +1263,6 @@ r_6: & & \textrm{VP} \to \textrm{VV}\ \textrm{NN} \nonumber
%----------------------------------------------------------------------------------------
\sectionnewpage
\vspace{0.5em}
\section{小结及深入阅读} \label{sec2:summary}
\parinterval 本章重点介绍了如何对自然语言处理问题进行统计建模,并从数据中自动学习统计模型的参数,最终使用学习到的模型对新的问题进行处理。之后,本章将这种思想应用到三个自然语言处理任务中,包括:中文分词、语言建模、句法分析,它们也和机器翻译有着紧密的联系。通过系统化的建模,可以发现:经过适当的假设和化简,统计模型可以很好的描述复杂的自然语言处理问题。相关概念和方法也会在后续章节的内容中被广泛使用。
......@@ -1284,9 +1272,9 @@ r_6: & & \textrm{VP} \to \textrm{VV}\ \textrm{NN} \nonumber
\begin{adjustwidth}{1em}{}
\begin{itemize}
\vspace{0.5em}
\item 在建模方面,本章介绍的三个任务均采用的是基于人工先验知识进行模型设计的思路。也就是,问题所表达的现象被``一步一步''生成出来。这是一种典型的生成式建模思想,它把要解决的问题看作一些观测结果的隐含变量(比如,句子是观测结果,分词结果是隐含在背后的变量),之后通过对隐含变量生成观测结果的过程进行建模,以达到对问题进行数学描述的目的。这类模型一般需要依赖一些独立性假设,假设的合理性对最终的性能有较大影响。相对于{\small\sffamily\bfseries{生成模型}}\index{生成模型}(Generative Model)\index{Generative Model},另一类方法{\small\sffamily\bfseries{判别模型}}\index{判别模型}(Discriminative Model)\index{Discriminative Model},它直接描述了从隐含变量生成观测结果的过程,这样对问题的建模更加直接,同时这类模型可以更加灵活的引入不同的特征。判别模型在自然语言处理中也有广泛应用\cite{shannon1948mathematical}\cite{ng2002discriminative}。 在本书的第四章也会使用到判别式模型。
\item 在建模方面,本章介绍的三个任务均采用的是基于人工先验知识进行模型设计的思路。也就是,问题所表达的现象被``一步一步''生成出来。这是一种典型的生成式建模思想,它把要解决的问题看作一些观测结果的隐含变量(比如,句子是观测结果,分词结果是隐含在背后的变量),之后通过对隐含变量生成观测结果的过程进行建模,以达到对问题进行数学描述的目的。这类模型一般需要依赖一些独立性假设,假设的合理性对最终的性能有较大影响。相对于{\small\sffamily\bfseries{生成模型}}\index{生成模型}(Generative Model)\index{Generative Model},另一类方法{\small\sffamily\bfseries{判别模型}}\index{判别模型}(Discriminative Model)\index{Discriminative Model},它直接描述了从隐含变量生成观测结果的过程,这样对问题的建模更加直接,同时这类模型可以更加灵活的引入不同的特征。判别模型在自然语言处理中也有广泛应用\cite{shannon1948mathematical}\cite{ng2002discriminative}。 在本书的第四章也会使用到判别式模型。
\vspace{0.5em}
\item 从现在自然语言处理的前沿看,基于端到端学习的深度学习方法在很多任务中都取得了领先的性能。但是,本章并没有涉及深度学习及相关方法,这是由于笔者认为:对问题的建模是自然语言处理的基础,对问题的本质刻画并不会因为方法的改变而改变。因此,本章的内容没有太多陷入到更加复杂的模型和算法设计中,相反,我们希望关注对基本问题的理解和描述。不过,一些前沿方法仍可以作为参考,包括:基于条件随机场和双向长短时记忆模型的序列标注模型\cite{lafferty2001conditional}\cite{huang2015bidirectional}\cite{ma2016end}、神经语言模型\cite{bengio2003neural}\cite{mikolov2010recurrent}、神经句法分析模型\cite{chen2014fast}\cite{zhu2015long}
\item 从现在自然语言处理的前沿看,基于端到端学习的深度学习方法在很多任务中都取得了领先的性能。但是,本章并没有涉及深度学习及相关方法,这是由于笔者认为:对问题的建模是自然语言处理的基础,对问题的本质刻画并不会因为方法的改变而改变。因此,本章的内容没有太多陷入到更加复杂的模型和算法设计中,相反,我们希望关注对基本问题的理解和描述。不过,一些前沿方法仍可以作为参考,包括:基于条件随机场和双向长短时记忆模型的序列标注模型\cite{lafferty2001conditional}\cite{huang2015bidirectional}\cite{ma2016end}、神经语言模型\cite{bengio2003neural}\cite{mikolov2010recurrent}、神经句法分析模型\cite{chen2014fast}\cite{zhu2015long}
\vspace{0.5em}
\item 此外,本章并没有对模型的推断方法进行深入介绍。比如,对于一个句子如何有效的找到概率最大的分词结果?显然,简单枚举是不可行的。对于这类问题比较简单的解决方法是使用动态规划\cite{huang2008advanced}。如果使用动态规划的条件不满足,可以考虑使用更加复杂的搜索策略,并配合一定剪枝方法。实际上,无论是$n$-gram语言模型还是简单的上下文无关文法都有高效的推断方法。比如,$n$-gram语言模型可以被视为概率有限状态自动机,因此可以直接使用成熟的自动机工具。对于更复杂的句法分析问题,可以考虑使用移进-规约方法来解决推断问题\cite{aho1972theory}
\vspace{0.5em}
......
......@@ -690,7 +690,7 @@ g(\mathbf{s},\mathbf{t}) \equiv \prod_{j,i \in \widehat{A}}{\textrm{P}(s_j,t_i)}
\vspace{0.5em}
\item 根据译文$\mathbf{t}$选择源文$\mathbf{s}$的长度$m$,用$\textrm{P}(m|\mathbf{t})$表示;
\vspace{0.5em}
\item 当确定源语言句子的长度$m$后,循环每个位置$j$逐次生成每个源语言单词$s_j$,也就是$\prod_{j=1}^m$计算的内容;
\item 当确定源语言句子的长度$m$后,循环每个位置$j$逐次生成每个源语言单词$s_j$,也就是$\prod_{j=1}^m \cdot$计算的内容;
\vspace{0.5em}
\item 对于每个位置$j$,根据译文$\mathbf{t}$、源文长度$m$、已经生成的源语言单词$s_1^{j-1}$和对齐$a_1^{j-1}$,生成第$j$个位置的对齐结果$a_j$,用$\textrm{P}(a_j|a_1^{j-1},s_1^{j-1},m,\mathbf{t})$表示;
\vspace{0.5em}
......@@ -790,7 +790,7 @@ g(\mathbf{s},\mathbf{t}) \equiv \prod_{j,i \in \widehat{A}}{\textrm{P}(s_j,t_i)}
\label{eq:3-23}
\end{eqnarray}
\parinterval 在公式\ref{eq:3-23}中,需要遍历所有的词对齐,即$ \sum_{\mathbf{a}}{\cdot}$。但这种表示不够直观,因此可以把这个过程重新表示为下形式:
\parinterval 在公式\ref{eq:3-23}中,需要遍历所有的词对齐,即$ \sum_{\mathbf{a}}{\cdot}$。但这种表示不够直观,因此可以把这个过程重新表示为下形式:
\begin{eqnarray}
\textrm{P}(\mathbf{s}|\mathbf{t})={\sum_{a_1=0}^{l}\cdots}{\sum_{a_m=0}^{l}\frac{\varepsilon}{(l+1)^m}}{\prod_{j=1}^{m}f(s_j|t_{a_j})}
\label{eq:3-24}
......
%%%------------------------------------------------------------------------------------------------------------
\begin{figure}
\subfigure[softplus]{
\centering
\begin{minipage}{.2\textwidth}
\begin{tikzpicture}
\draw[->](-1.2,0)--(1.2,0)node[left,below,font=\tiny]{$x$};
\draw[->](0,-1.2)--(0,1.2)node[right,font=\tiny]{$y$};
\foreach \x in {-1.0,-0.5,0.0,0.5,1.0}{\draw(\x,0)--(\x,0.05)node[below,outer sep=2pt,font=\tiny]at(\x,0){\x};}
\foreach \y in {1.0,0.5}{\draw(0,\y)--(0.05,\y)node[left,outer sep=2pt,font=\tiny]at(0,\y){\y};}
\draw[color=red ,domain=-1.2:1]plot(\x,{ln(1+(exp(\x))});
\node[black,anchor=south] at (0,1.2) {\small $y = ln(1+e^x)$};
\end{tikzpicture}
\end{minipage}%
}
\hfill
\subfigure[sigmoid]{
\centering
\begin{minipage}{.2\textwidth}
\begin{tikzpicture}
\draw[->](-1.2,0)--(1.2,0)node[left,below,font=\tiny]{$x$};
\draw[->](0,-1.2)--(0,1.2)node[right,font=\tiny]{$y$};
\draw[dashed](-1.2,1)--(1.2,1);
\foreach \x in {-1,-0.5,0,0.5,1}{\draw(\x,0)--(\x,0.05)node[below,outer sep=2pt,font=\tiny]at(\x,0){
\pgfmathparse{(\x)*5}
\pgfmathresult};}
\foreach \y in {0.5,1.0}{\draw(0,\y)--(0.05,\y)node[left,outer sep=2pt,font=\tiny]at(0,\y){\y};}
\draw[color=red,domain=-1.2:1.2]plot(\x,{1/(1+(exp(-5*\x)))});
\node[black,anchor=south] at (0,1.2) {\small $y = \frac{1}{1+e^{-x}}$};
\end{tikzpicture}
\end{minipage}%
}
\hfill
\subfigure[tanh]{
\centering
\begin{minipage}{.2\textwidth}
\begin{tikzpicture}
\draw[->](-1.2,0)--(1.2,0)node[left,below,font=\tiny]{$x$};
\draw[->](0,-1.2)--(0,1.2)node[right,font=\tiny]{$y$};
\draw[dashed](-1.2,1)--(1.2,1);
\draw[dashed](-1.2,-1)--(1.2,-1);
\foreach \x in {-1.0,-0.5,0.0,0.5,1.0}{\draw(\x,0)--(\x,0.05)node[below,outer sep=2pt,font=\tiny]at(\x,0){\x};}
\foreach \y in {0.5,1.0}{\draw(0,\y)--(0.05,\y)node[left,outer sep=2pt,font=\tiny]at(0,\y){\y};}
\draw[color=red ,domain=-1.2:1.2]plot(\x,{tanh(\x)});
\node[black,anchor=south] at (0,1.2) {\small $y = \frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}$};
\end{tikzpicture}
\end{minipage}
}\\ \vspace{-1em}
\subfigure[relu]{
\centering
\begin{minipage}{.2\textwidth}
\begin{tikzpicture}
\draw[->](-1.2,0)--(1.2,0)node[left,below,font=\tiny]{$x$};
\draw[->](0,-1.2)--(0,1.2)node[right,font=\tiny]{$y$};
\draw[dashed](-1.2,1)--(1.2,1);
\draw[dashed](-1.2,-1)--(1.2,-1);
\foreach \x in {-1.0,-0.5,0.0,0.5,1.0}{\draw(\x,0)--(\x,0.05)node[below,outer sep=2pt,font=\tiny]at(\x,0){\x};}
\foreach \y in {0.5,1.0}{\draw(0,\y)--(0.05,\y)node[left,outer sep=2pt,font=\tiny]at(0,\y){\y};}
\draw[color=red ,domain=-1.2:1.2]plot(\x,{max(\x,0)});
\node[black,anchor=south] at (0,1.2) {\small $y =\max (0, x)$};
\end{tikzpicture}
\end{minipage}%
}
\hfill
\subfigure[gaussian]{
\centering
\begin{minipage}{.2\textwidth}
\begin{tikzpicture}
\draw[->](-1.2,0)--(1.2,0)node[left,below,font=\tiny]{$x$};
\draw[->](0,-1.2)--(0,1.2)node[right,font=\tiny]{$y$};
\draw[dashed](-1.2,1)--(1.2,1);
\foreach \x in {-1.0,-0.5,0.0,0.5,1.0}{\draw(\x,0)--(\x,0.05)node[below,outer sep=2pt,font=\tiny]at(\x,0){\x};}
\foreach \y in {0.5,1.0}{\draw(0,\y)--(0.05,\y)node[left,outer sep=2pt,font=\tiny]at(0,\y){\y};}
\draw[color=red ,domain=-1.2:1.2]plot(\x,{exp(-1*((\x)^2))});
\node[black,anchor=south] at (0,1.2) {\small $y =e^{-x^2}$};
\end{tikzpicture}
\end{minipage}%
}
\hfill
\subfigure[identity]{
\centering
\begin{minipage}{.2\textwidth}
\begin{tikzpicture}
\draw[->](-1.2,0)--(1.2,0)node[left,below,font=\tiny]{$x$};
\draw[->](0,-1.2)--(0,1.2)node[right,font=\tiny]{$y$};
\foreach \x in {-1.0,-0.5,0.0,0.5,1.0}{\draw(\x,0)--(\x,0.05)node[below,outer sep=2pt,font=\tiny]at(\x,0){\x};}
\foreach \y in {0.5,1.0}{\draw(0,\y)--(0.05,\y)node[left,outer sep=2pt,font=\tiny]at(0,\y){\y};}
\draw[color=red ,domain=-1:1]plot(\x,\x);
\node[black,anchor=south] at (0,1.2) {\small $y =x$};
\end{tikzpicture}
\end{minipage}
}
\end{figure}
%%%------------------------------------------------------------------------------------------------------------
......@@ -25,10 +25,10 @@
\node [rectangle,inner sep=0.2em,fill=red!20] [fit = (neuron01) (neuron05)] (layer01) {};
\end{pgfonlayer}
\node [anchor=west] (layer00label) at ([xshift=1.25em]x5.east) {\footnotesize{\red{{输入层}}}};
\node [anchor=west] (layer00label) at ([xshift=1.3em]x5.east) {\footnotesize{第0层}};
\node [anchor=west] (layer00label2) at (layer00label.east) {\footnotesize{\red{(输入层)}}};
{
\node [anchor=west] (layer01label) at ([xshift=1em]layer01.east) {\footnotesize{}};
\node [anchor=west] (layer01label) at ([xshift=1em]layer01.east) {\footnotesize{1}};
}
{
\node [anchor=west] (layer01label2) at (layer01label.east) {\footnotesize{\red{({隐层})}}};
......@@ -55,7 +55,7 @@
}
\end{pgfonlayer}
\node [anchor=west] (layer02label) at ([xshift=4.4em]layer02.east) {\footnotesize{}};
\node [anchor=west] (layer02label) at ([xshift=4.4em]layer02.east) {\footnotesize{2}};
{
\node [anchor=west] (layer02label2) at (layer02label.east) {\footnotesize{\red{({隐层})}}};
}
......@@ -85,7 +85,7 @@
}
\end{pgfonlayer}
\node [anchor=west] (layer03label) at ([xshift=1em]layer03.east) {\footnotesize{}};
\node [anchor=west] (layer03label) at ([xshift=1em]layer03.east) {\footnotesize{3}};
{
\node [anchor=west] (layer03label2) at (layer03label.east) {\footnotesize{\red{({输出层})}}};
}
......
......@@ -10,9 +10,9 @@
\tikzstyle{parametershard} = [draw,thick,minimum width=4em,align=left,rounded corners=2pt]
{
\node[parametershard,anchor=west,fill=yellow!10] (param1) at (0,0) {$W_o$, $b_o$};
\node[parametershard,anchor=west,fill=yellow!10] (param1) at (0,0) {$W_o$};
\node (param2) at ([xshift=1em]param1.east) {};
\node[parametershard,anchor=west,fill=red!10] (param3) at ([xshift=1em]param2.east) {$W_h$, $b_h$};
\node[parametershard,anchor=west,fill=red!10] (param3) at ([xshift=1em]param2.east) {$W_h$};
\node[anchor=south,inner sep=1pt] (serverlabel) at ([yshift=0.2em]param2.north) {\footnotesize{\textbf{parameter server}: $\mathbf w_{new} = \mathbf w - \alpha\cdot \frac{\partial L}{\partial \mathbf w}$}};
}
......@@ -88,9 +88,9 @@
\tikzstyle{parametershard} = [draw,thick,minimum width=4em,align=left,rounded corners=2pt]
{
\node[parametershard,anchor=west,fill=yellow!10] (param1) at (0,0) {$W_o$, $b_o$};
\node[parametershard,anchor=west,fill=yellow!10] (param1) at (0,0) {$W_o$};
\node (param2) at ([xshift=1em]param1.east) {};
\node[parametershard,anchor=west,fill=red!10] (param3) at ([xshift=1em]param2.east) {$W_h$, $b_h$};
\node[parametershard,anchor=west,fill=red!10] (param3) at ([xshift=1em]param2.east) {$W_h$};
\node[anchor=south,inner sep=1pt] (serverlabel) at ([yshift=0.2em]param2.north) {\footnotesize{\textbf{parameter server}: $\mathbf w_{new} = \mathbf w - \alpha\cdot \frac{\partial L}{\partial \mathbf w}$}};
}
......
......@@ -2,7 +2,7 @@
\begin{tikzpicture}
%% a two-layer neural network
\begin{scope}
\begin{scope}[xshift=2in]
\tikzstyle{neuronnode} = [minimum size=1.7em,circle,draw,ublue,very thick,inner sep=1pt, fill=white,align=center,drop shadow={shadow xshift=0.1em,shadow yshift=-0.1em}]
%% output illustration
\begin{scope}[xshift=2.8in,yshift=0.1in]
......@@ -10,7 +10,7 @@
\draw [->,thick] (-2.2,0) -- (2.2,0);
\draw [->,thick] (0,0) -- (0,2);
\draw [-] (-0.05,1) -- (0.05,1);
\node [anchor=north,inner sep=1pt] (labela) at (0,-0.2) {\footnotesize{(a)}};
\node [anchor=north,inner sep=1pt] (labelb) at (0,-0.2) {\footnotesize{(b)}};
}
{
\draw [->,thick] (-2.2,0) -- (2.2,0);
......@@ -25,7 +25,7 @@
\end{scope}
%% a two-layer neural network
\begin{scope}[xshift=2in]
\begin{scope}[xshift=0in]
\tikzstyle{neuronnode} = [minimum size=1.7em,circle,draw,ublue,very thick,inner sep=1pt, fill=white,align=center,drop shadow={shadow xshift=0.1em,shadow yshift=-0.1em}]
%% output illustration
\begin{scope}[xshift=2.8in,yshift=0.1in]
......@@ -35,7 +35,7 @@
\draw [-] (-0.05,1) -- (0.05,1);
\node [anchor=east,inner sep=1pt] (label1) at (0,1) {\tiny{1}};
\node [anchor=south east,inner sep=1pt] (label2) at (0,0) {\tiny{0}};
\node [anchor=north,inner sep=1pt] (labelb) at (0,-0.2) {\footnotesize{(b)}};
\node [anchor=north,inner sep=1pt] (labela) at (0,-0.2) {\footnotesize{(a)}};
}
{
\draw [->,thick] (-2.2,0) -- (2.2,0);
......
%%%------------------------------------------------------------------------------------------------------------
\begin{tikzpicture}
%左
\node [anchor=west,draw=ublue,minimum width=1.5em,minimum height=1.5em] (part1-1) at (0,0) {\small{$x_1$}};
\node [anchor=north,draw=ublue,minimum width=1.5em,minimum height=1.5em] (part1-2) at ([yshift=-2.5em]part1-1.south) {\small {$x_2$}};
\node [anchor=north,draw=ublue,minimum width=1.5em,minimum height=1.5em] (part1-3) at ([yshift=-2.5em]part1-2.south) {\small {$x_3$}};
\node [anchor=north,minimum width=3.0em] (part1-4) at ([yshift=-1.0em]part1-3.south) {\small {输入层}};
\node[anchor=south,minimum height=13em,minimum width=4.0em,draw=ublue,dotted,thick] (part1out) at ([xshift=0.0em,yshift=-8.5em]part1-2.north) {};
%中
\node [circle,anchor=west,draw=ublue,minimum width=2.0em] (part2-1) at ([xshift=4.6em,yshift=2.0em]part1-2.east) {\small {$a_1$}};
\node [circle,anchor=west,draw=ublue,minimum width=2.0em] (part2-2) at ([xshift=4.6em,yshift=-2.0em]part1-2.east) {\small {$a_2$}};
\node [anchor=north,minimum width=3.0em] (part2-3) at ([xshift=0.0em,yshift=-2.79em]part2-2.south) {\small {隐藏层}};
\node[anchor=south,minimum height=13em,minimum width=4.0em,draw=ublue,dotted,thick] (part2out) at ([xshift=6.4em,yshift=-8.5em]part1-2.north) {};
%右
\node [circle,anchor=west,draw=ublue,minimum width=2.0em] (part3-1) at ([xshift=10.5em,yshift=0.0em]part1-2.east) {\small {$y$}};
\node [anchor=west,draw=ublue,minimum width=1.5em,minimum height=1.5em] (part3-2) at ([xshift=1.2em]part3-1.east) {\small {$y$}};
\node [anchor=north,minimum width=3.0em] (part3-3) at ([xshift=1.4em,yshift=-4.79em]part3-1.south) {\small {输出层}};
\node[anchor=south,minimum height=13em,minimum width=6.0em,draw=ublue,dotted,thick] (part3out) at ([xshift=13.8em,yshift=-8.5em]part1-2.north) {};
%连线
\draw [->,thick,ublue](part1-1.east)--(part2-1.west);
\draw [->,thick,ublue](part1-1.east)--(part2-2.west);
\draw [->,thick,ublue](part1-2.east)--(part2-1.west);
\draw [->,thick,ublue](part1-2.east)--(part2-2.west);
\draw [->,thick,ublue](part1-3.east)--(part2-1.west);
\draw [->,thick,ublue](part1-3.east)--(part2-2.west);
\draw [->,thick,ublue](part2-1.east)--(part3-1.west);
\draw [->,thick,ublue](part2-2.east)--(part3-1.west);
\draw [->,thick,ublue](part3-1.east)--(part3-2.west);
\end{tikzpicture}
%%------------------------------------------------------------------------------------------------------------
......@@ -18,8 +18,8 @@
\node [anchor=north,minimum width=4.0em,minimum height=1.5em] (part5) at ([yshift=-1.4em]part4.south) {\footnotesize {$\mathbf a$}};
\draw [-,thick](part4.south)--([yshift=-0.1em]part5.north);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\node [anchor=west,minimum width=2.0em,minimum height=1.5em,draw,fill=red!20] (part5-3) at ([xshift=0.0em,yshift=0.1em]part5.east) {\footnotesize {$\mathbf w^2$}};
\node [anchor=west,minimum width=2.0em,minimum height=1.5em,draw,fill=orange!40] (part5-4) at ([xshift=2.0em,yshift=0.0em]part5-3.east) {\footnotesize {$\mathbf b^2$}};
\node [anchor=west,minimum width=2.0em,minimum height=1.5em,draw,fill=red!20] (part5-3) at ([xshift=0.0em,yshift=0.1em]part5.east) {\footnotesize {$\mathbf w^{[2]}$}};
\node [anchor=west,minimum width=2.0em,minimum height=1.5em,draw,fill=orange!40] (part5-4) at ([xshift=2.0em,yshift=0.0em]part5-3.east) {\footnotesize {$ b^{[2]}$}};
\draw[-,thick](part4.south)--(part5-3.north);
\draw[-,thick](part3.south)--(part5-4.north);
\node [anchor=south,minimum width=1.5em,minimum height=1.5em] (part5-3-1) at ([xshift=1.1em,yshift=-0.45em]part5-3.north) {\scriptsize {$1\times 2$}};
......@@ -41,8 +41,8 @@
\node [anchor=north,minimum width=4.0em,minimum height=1.5em] (part9) at ([yshift=-1.4em]part8.south) {\footnotesize {$\mathbf x$}};
\draw [-,thick](part8.south)--([yshift=-0.1em]part9.north);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\node [anchor=west,minimum width=2.0em,minimum height=1.5em,draw,fill=red!20] (part9-3) at ([xshift=0.0em,yshift=0.1em]part9.east) {\footnotesize {$\mathbf w^1$}};
\node [anchor=west,minimum width=2.0em,minimum height=1.5em,draw,fill=orange!40] (part9-4) at ([xshift=2.0em,yshift=0.0em]part9-3.east) {\footnotesize {$\mathbf b^1$}};
\node [anchor=west,minimum width=2.0em,minimum height=1.5em,draw,fill=red!20] (part9-3) at ([xshift=0.0em,yshift=0.1em]part9.east) {\footnotesize {$\mathbf w^{[1]}$}};
\node [anchor=west,minimum width=2.0em,minimum height=1.5em,draw,fill=orange!40] (part9-4) at ([xshift=2.0em,yshift=0.0em]part9-3.east) {\footnotesize {$\mathbf b^{[1]}$}};
\draw[-,thick](part8.south)--(part9-3.north);
\draw[-,thick](part7.south)--(part9-4.north);
\node [anchor=south,minimum width=1.5em,minimum height=1.5em] (part9-3-1) at ([xshift=1.1em,yshift=-0.45em]part9-3.north) {\scriptsize {$3\times 2$}};
......
%%%------------------------------------------------------------------------------------------------------------
\begin{tikzpicture}
%左
\node [anchor=west,draw=ublue,minimum width=3.0em] (part1-1) at (0,0) {\small{天空状况}};
\node [anchor=north,draw=ublue,minimum width=3.0em] (part1-2) at ([yshift=-2.5em]part1-1.south) {\small {低空气温}};
\node [anchor=north,draw=ublue,minimum width=3.0em] (part1-3) at ([yshift=-2.5em]part1-2.south) {\small {水平气压}};
\node [anchor=north,minimum width=3.0em] (part1-4) at ([yshift=-1.0em]part1-3.south) {\small {输入层}};
\node[anchor=south,minimum height=13em,minimum width=6.0em,draw=ublue,dotted,thick] (part1out) at ([xshift=0.0em,yshift=-8.5em]part1-2.north) {};
%中
\node [circle,anchor=west,draw=ublue,minimum width=2.2em] (part2-1) at ([xshift=4.0em,yshift=2.0em]part1-2.east) {\footnotesize {温度}};
\node [circle,anchor=west,draw=ublue,minimum width=2.2em] (part2-2) at ([xshift=4.0em,yshift=-2.0em]part1-2.east) {\footnotesize {风速}};
\node [anchor=north,minimum width=3.0em] (part2-3) at ([xshift=0.0em,yshift=-2.42em]part2-2.south) {\small {隐藏层}};
\node[anchor=south,minimum height=13em,minimum width=4.0em,draw=ublue,dotted,thick] (part2out) at ([xshift=7.4em,yshift=-8.5em]part1-2.north) {};
%右
\node [anchor=west,draw=ublue,minimum width=3.0em] (part3-1) at ([xshift=10.0em,yshift=0.0em]part1-2.east) {\small {穿衣指数}};
\node [anchor=north,minimum width=3.0em] (part3-2) at ([yshift=-5.05em]part3-1.south) {\small {输出层}};
\node[anchor=south,minimum height=13em,minimum width=6.0em,draw=ublue,dotted,thick] (part3out) at ([xshift=14.4em,yshift=-8.5em]part1-2.north) {};
%连线
\draw [->,thick,ublue](part1-1.east)--(part2-1.west);
\draw [->,thick,ublue](part1-1.east)--(part2-2.west);
\draw [->,thick,ublue](part1-2.east)--(part2-1.west);
\draw [->,thick,ublue](part1-2.east)--(part2-2.west);
\draw [->,thick,ublue](part1-3.east)--(part2-1.west);
\draw [->,thick,ublue](part1-3.east)--(part2-2.west);
\draw [->,thick,ublue](part2-1.east)--(part3-1.west);
\draw [->,thick,ublue](part2-2.east)--(part3-1.west);
\end{tikzpicture}
%%%------------------------------------------------------------------------------------------------------------
......@@ -7,7 +7,7 @@
\node [anchor=north,draw=ublue,minimum width=3.55em,fill=yellow!20] (part1-2) at ([yshift=-2.0em]part1-1.south) {\scriptsize {低空气温}};
\node [anchor=north,draw=ublue,minimum width=3.55em,fill=yellow!20] (part1-3) at ([yshift=-2.0em]part1-2.south) {\scriptsize {水平气压}};
\node [rectangle,rounded corners,draw=black!50,densely dashed,inner sep=0.4em] [fit = (part1-1) (part1-2) (part1-3) (inputlabel)] (inputshadow) {};
\node [anchor=north,draw=ublue,minimum width=3.55em,fill=yellow!20] (part1-4) at ([yshift=-2.0em]part1-3.south) {\scriptsize {1}};
\node [anchor=north,draw=ublue,minimum width=3.55em,fill=yellow!20] (part1-4) at ([yshift=-2.0em]part1-3.south) {\scriptsize {1}};
\node [anchor=north,minimum width=2.5em] (part1-5) at ([yshift=-0.5em]part1-4.south) {\scriptsize {输入层}};
......@@ -16,7 +16,7 @@
\node [anchor=north] (hidlabel) at ([yshift=3.1em]part2-1.north) {\scriptsize{特征}};
\node [circle,anchor=west,draw=ublue,minimum width=2.5em,fill=blue!20] (part2-2) at ([xshift=2.0em,yshift=-1.7em]part1-2.east) {\scriptsize {风速}};
\node [rectangle,rounded corners,draw=black!50,densely dashed,inner sep=0.4em] [fit = (part2-1) (part2-2) (hidlabel) ] (inputshadow) {};
\node [circle,anchor=west,draw=ublue,minimum width=2.5em,fill=blue!20,inner sep=2pt] (part2-3) at ([xshift=2.0em,yshift=-1.7em]part1-3.east) {\scriptsize {2}};
\node [circle,anchor=west,draw=ublue,minimum width=2.5em,fill=blue!20,inner sep=2pt] (part2-3) at ([xshift=2.0em,yshift=-1.7em]part1-3.east) {\scriptsize {2}};
\node [anchor=north,minimum width=3.0em] (part2-4) at ([xshift=0.0em,yshift=-1.6em]part2-3.south) {\scriptsize{隐藏层}};
\node [anchor=north] (labela) at ([xshift=0.0em,yshift=-4em]part2-3.south) {\footnotesize {(a)}};
......@@ -54,7 +54,7 @@
y
\node [rectangle,rounded corners,draw=black!50,densely dashed,inner sep=0.4em] [fit = (part1-1) (part1-2) (part1-3) (inputlabel)] (inputshadow) {};
\node [anchor=north,draw=ublue,minimum width=3.55em,fill=yellow!20] (part1-4) at ([yshift=-2.0em]part1-3.south) {\footnotesize {$\mathbf b^1 $}};
\node [anchor=north,draw=ublue,minimum width=3.55em,fill=yellow!20] (part1-4) at ([yshift=-2.0em]part1-3.south) {\footnotesize {$\mathbf b^{[1]} $}};
\node [anchor=north,minimum width=2.5em] (part1-5) at ([yshift=-0.5em]part1-4.south) {\scriptsize {输入层}};
......@@ -65,7 +65,7 @@ y
\node [circle,anchor=west,draw=ublue,minimum width=2.5em,fill=blue!20] (part2-2) at ([xshift=2.0em,yshift=-1.7em]part1-2.east) {\large{$a_2$}};
\node [rectangle,rounded corners,draw=black!50,densely dashed,inner sep=0.4em] [fit = (part2-1) (part2-2) (hidlabel) ] (inputshadow) {};
\node [circle,anchor=west,draw=ublue,minimum width=2.5em,fill=blue!20,inner sep=2pt] (part2-3) at ([xshift=2.0em,yshift=-1.7em]part1-3.east) {\large {$b^2 $}};
\node [circle,anchor=west,draw=ublue,minimum width=2.5em,fill=blue!20,inner sep=2pt] (part2-3) at ([xshift=2.0em,yshift=-1.7em]part1-3.east) {\large {$b^{[2]} $}};
\node [anchor=north,minimum width=3.0em] (part2-4) at ([xshift=0.0em,yshift=-1.6em]part2-3.south) {\scriptsize{隐藏层}};
\node [anchor=north] (labelb) at ([xshift=0.0em,yshift=-4em]part2-3.south) {\footnotesize {(b)}};
......
......@@ -18,7 +18,7 @@
\chapter{人工神经网络和神经语言建模}
\parinterval {\small\sffamily\bfseries{人工神经网络}}\index{人工神经网络}(Artificial Neural Networks)\index{Artificial Neural Networks}{\small\sffamily\bfseries{神经网络}}\index{神经网络}(Neural Networks)\index{Neural Networks}是描述客观世界的一种数学模型。这种模型的行为和生物学上的神经系统有一些相似之处,但是人们更多的是把它作为一种计算工具,而非一个生物学模型。近些年,随着机器学习领域的快速发展,人工神经网络被更多的使用在对图像和自然语言处理问题的建模上。特别是,研究人员发现深层神经网络可以被成功训练后,学术界也逐渐形成了一种新的机器学习范式\ \dash \ 深度学习。可以说,深度学习是近几年最受瞩目的研究领域,其应用也十分广泛。比如,图像识别的很多重要进展都来自深度学习模型的使用。包括机器翻译在内的很多自然语言处理任务中,深度学习也已经成为了一种标准模型。基于深度学习的表示学习方法也为自然语言处理开辟了新的思路。
\parinterval {\small\sffamily\bfseries{人工神经网络}}\index{人工神经网络}(Artificial Neural Networks)\index{Artificial Neural Networks}{\small\sffamily\bfseries{神经网络}}\index{神经网络}(Neural Networks)\index{Neural Networks}是描述客观世界的一种数学模型。这种模型和生物学上的神经系统在行为上有一些相似之处,但是人们更多的是把它作为一种计算工具,而非一个生物学模型。近些年,随着机器学习领域的快速发展,人工神经网络被更多的使用在对图像和自然语言处理问题的建模上。特别是,研究人员发现深层神经网络可以被成功训练后,学术界也逐渐形成了一种新的机器学习范式\ \dash \ 深度学习。可以说,深度学习是近几年最受瞩目的研究领域之一,其应用也十分广泛。比如,图像识别的很多重要进展都来自深度学习模型的使用。包括机器翻译在内的很多自然语言处理任务中,深度学习也已经成为了一种标准模型。基于深度学习的表示学习方法也为自然语言处理开辟了新的思路。
\parinterval 本章将对深度学习的概念和技术进行介绍,目的是为第六章和第七章神经机器翻译的内容进行铺垫。此外,本章也会对深度学习在语言建模方面的应用进行介绍。这样,读者可以更容易地理解如何使用深度学习方法描述自然语言处理问题。同时,进一步了解一些相关的学术前沿,如预训练模型。
......@@ -30,7 +30,7 @@
\parinterval {\small\sffamily\bfseries{深度学习}}\index{深度学习}(Deep Learning)\index{Deep Learning}是机器学习研究中一个非常重要的分支,其概念来源于对人工神经网络的研究:通过人工神经元之间的连接建立一种数学模型,使计算机可以像人一样进行分析、学习和推理。
\parinterval 近几年来,随着深度学习技术的广泛传播与使用,``人工智能''这个名词在有些场合下甚至与``深度学习''划上了等号。这种理解非常片面,比较准确地说,``深度学习''是实现``人工智能''的一种技术手段。但从这种现象中也可以看出,深度学习的火爆情况可见一斑。深度学习的技术浪潮以惊人的速度席卷世界,也改变了很多领域的现状,在数据挖掘、自然语言处理、语音识别、图像识别等各个领域随处可见深度学习的身影。自然语言处理领域中,深度学习在很多任务中已经处于``统治''地位。特别是,基于深度学习的表示学习方法已经成为自然语言处理的新范式,在机器翻译任务中更是衍生出了``神经机器翻译''这样全新的模型。
\parinterval 近几年来,随着深度学习技术的广泛传播与使用,``人工智能''这个名词在有些场合下甚至与``深度学习''划上了等号。这种理解非常片面,比较准确地说,``深度学习''是实现``人工智能''的一种技术手段。但从这种现象中,深度学习的火爆情况可见一斑。深度学习的技术浪潮以惊人的速度席卷世界,也改变了很多领域的现状,在数据挖掘、自然语言处理、语音识别、图像识别等各个领域随处可见深度学习的身影。自然语言处理领域中,深度学习在很多任务中已经处于``统治''地位。特别是,基于深度学习的表示学习方法已经成为自然语言处理的新范式,在机器翻译任务中更是衍生出了``神经机器翻译''这样全新的模型。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -48,7 +48,7 @@
\subsubsection{早期的人工神经网络和第一次寒冬}
\parinterval 最初,神经网络设计的初衷是用计算模型来模拟生物大脑中神经元的运行机理,这种想法哪怕现在看来也是十分超前的。例如,目前很多机构关注的概念\ \dash \ ``类脑计算''就是希望研究人脑的运行机制及相关的计算机实现方法。然而模拟大脑这件事并没有想象中的那么简单,众所周知,生物学中对人脑机制的研究是十分困难的,我们对人脑的运行机制尚不明确又何谈模拟呢?因而,神经网络技术一直在摸索着前行,发展到现在,其计算过程与人脑的运行机制已经大相径庭。
\parinterval 最初,神经网络设计的初衷是用计算模型来模拟生物大脑中神经元的运行机理,这种想法哪怕现在看来也是十分超前的。例如,目前很多机构关注的概念\ \dash \ ``类脑计算''就是希望研究人脑的运行机制及相关的计算机实现方法。然而模拟大脑这件事并没有想象中的那么简单,众所周知,生物学中对人脑机制的研究是十分困难的,我们对人脑的运行机制尚不明确又何谈模拟呢?因而,神经网络技术一直在摸索着前行,发展到现在,其计算过程与人脑的运行机制已经大相径庭。
\parinterval 人工神经网络的第一个发展阶段是在二十世纪40年代到70年代,这个时期的人工神经网络还停留在利用线性模型模拟生物神经元的阶段,比如使用线性加权函数来描述输入$ \mathbf x $和输出$ y $ 之间的联系:$y=x_1 \cdot w_1 + \dots + x_n \cdot w_n $。举一个简单例子,输入$ \mathbf x $是某个地区的坐标和时间,输出$ y $是该地区的温度,尽管真实的问题可能要复杂的多,但是线性模型确实有能力去拟合简单的函数关系。
......@@ -60,7 +60,7 @@
\subsubsection{神经网络的第二次高潮和第二次寒冬}
\parinterval 虽然第一代神经网络受到了打击,但是20世纪80年代开始,第二代人工神经网络开始萌发新的生机。在这个发展阶段,生物属性已经不再是神经网络的唯一灵感来源,在{\small\bfnew{连接主义}}\index{连接主义}(Connectionism)\index{Connectionism}{\small\bfnew{分布式表示}}\index{分布式表示}(Distributed representation)\index{Distributed representation}两种思潮的影响下,神经网络方法再次走入了人们的视线。
\parinterval 虽然第一代神经网络受到了打击,但是20世纪80年代,第二代人工神经网络开始萌发新的生机。在这个发展阶段,生物属性已经不再是神经网络的唯一灵感来源,在{\small\bfnew{连接主义}}\index{连接主义}(Connectionism)\index{Connectionism}{\small\bfnew{分布式表示}}\index{分布式表示}(Distributed representation)\index{Distributed representation}两种思潮的影响下,神经网络方法再次走入了人们的视线。
\vspace{0.3em}
\parinterval (1)符号主义与连接主义
......@@ -72,7 +72,7 @@
\parinterval (2)分布式表示
\vspace{0.3em}
\parinterval 分布式表示的主要思想是``一个复杂系统的任何部分的输入都应该是多个特征共同表示的结果'',这种思想在自然语言处理领域的影响尤其深刻,它改变了刻画世界的角度,将世界万物从离散空间映射到多维连续空间。例如,在现实世界中,``张三''这个代号就代表着一个人。如果想要知道这个人亲属都有谁,因为有``A和B如果姓氏相同,在一个家谱中,那么A和B是本家''这个先验知识在,在知道代号``张三''的情况下,可以得知``张三''的亲属是谁。但是如果不依靠这个先验知识,就无法得知``张三''的亲属是谁。但在分布式表示中,可以用一个实数向量,如$ (0.1,0.3,0.4) $来表示``张三''这个人,这个人的所有特征信息都包含在这个实数向量中,通过在向量空间中的一些操作(如计算距离等),哪怕没有任何先验知识的存在,也完全可以找到这个人的所有亲属。在自然语言处理中,一个单词也用一个实数向量(词向量或词嵌入)表示,通过这种方式将语义空间重新刻画,将这个离散空间转化成了一个连续空间,这时单词就不再是一个简单的词条,而是由成百上千个特征共同描述出来,而每个特征都描述这个词的某个`` 方面''。
\parinterval 分布式表示的主要思想是``一个复杂系统的任何部分的输入都应该是多个特征共同表示的结果'',这种思想在自然语言处理领域的影响尤其深刻,它改变了刻画世界的角度,将世界万物从离散空间映射到多维连续空间。例如,在现实世界中,``张三''这个代号就代表着一个人。如果想要知道这个人亲属都有谁,因为有``A和B如果姓氏相同,在一个家谱中,那么A和B是本家''这个先验知识在,在知道代号``张三''的情况下,可以得知``张三''的亲属是谁。但是如果不依靠这个先验知识,就无法得知``张三''的亲属是谁。但在分布式表示中,可以用一个实数向量,如$ (0.1,0.3,0.4) $来表示``张三''这个人,这个人的所有特征信息都包含在这个实数向量中,通过在向量空间中的一些操作(如计算距离等),哪怕没有任何先验知识的存在,也完全可以找到这个人的所有亲属。在自然语言处理中,一个单词也用一个实数向量(词向量或词嵌入)表示,通过这种方式将语义空间重新刻画,将这个离散空间转化成了一个连续空间,这时单词就不再是一个简单的词条,而是由成百上千个特征共同描述出来的,其中每个特征分别代表这个词的某个`` 方面''。
\parinterval 随着第二代人工神经网络的``脱胎换骨'',学者们又对神经网络方法燃起了希望之火,这也导致有些时候过分夸大了神经网络的能力。20世纪90年代后期,由于在语音识别、自然语言处理等应用中,人们对神经网络方法期望过高,但是结果并没有达到预期,这也让很多人丧失了对神经网络方法的信任。相反,核方法、图模型等机器学习方法取得了很好的效果,这导致神经网络研究又一次进入低谷。
......@@ -82,13 +82,13 @@
\subsubsection{深度学习和神经网络方法的崛起}
\parinterval 21世纪初,随着深度学习浪潮席卷世界,人工神经网络又一次出现在人们的视野中。深度学习的流行源于2006年Hinton等人成功训练了一个深度信念网络(Deep Belief Network),在深度神经网络方法完全不受重视的情况下,大家突然发现深度神经网络完全是一个魔鬼般的存在,可以解决很多当时其他方法无法解决的问题。神经网络方法终于在一次又一次的否定后,迎来了它的春天。随之针对神经网络和深度学习的一系列研究前赴后继地展开了,延续至今。
\parinterval 21世纪初,随着深度学习浪潮席卷世界,人工神经网络又一次出现在人们的视野中。深度学习的流行源于2006年Hinton等人成功训练了一个深度信念网络(Deep Belief Network),在深度神经网络方法完全不受重视的情况下,大家突然发现深度神经网络完全是一个魔鬼般的存在,可以解决很多当时其他方法无法解决的问题。神经网络方法终于在一次又一次的否定后,迎来了它的春天。随之针对神经网络和深度学习的一系列研究前赴后继地展开了,延续至今。
\parinterval 回过头来看,现代深度学习的成功主要有三方面的原因:
\begin{itemize}
\vspace{0.5em}
\item 第一,模型和算法的不断完善和改进。这个方面的进步是现代深度学习能够获得成功的最主要原因;
\item 第一,模型和算法的不断完善和改进。这是现代深度学习能够获得成功的最主要原因;
\vspace{0.5em}
\item 第二,并行计算能力的提升使大规模的实践成为了可能。早期的计算机设备根本无法支撑深度神经网络训练所需要的计算量,导致实践变得十分困难。而设备的进步、计算能力的提升则彻底改变了这种窘境;
\vspace{0.5em}
......@@ -96,7 +96,7 @@
\vspace{0.5em}
\end{itemize}
\parinterval 另外,从应用的角度,数据量的快速提升和模型容量的增加也为深度学习的成功提供了条件,数据量的增加使得深度学习有了用武之地,例如,2000年以来,双文本数据量无论在学术研究还是在工业实践中的使用数量都在逐年上升(如图\ref{fig:5-1}所示)。现在的统计模型参数量往往很大,因此需要大规模数据才能保证模型学习的充分性,而大数据时代的到来为训练这样的模型提供了数据基础。
\parinterval 另外,从应用的角度,数据量的快速提升和模型容量的增加也为深度学习的成功提供了条件,数据量的增加使得深度学习有了用武之地,例如,2000年以来,双文本数据量无论在学术研究还是在工业实践中的使用数量都在逐年上升(如图\ref{fig:5-1}所示)。现在的深度学习模型参数量往往很大,因此需要大规模数据才能保证模型学习的充分性,而大数据时代的到来为训练这样的模型提供了数据基础。
%----------------------------------------------------------------------
\begin{figure}[htp]
......@@ -194,7 +194,7 @@
\sectionnewpage
\section{神经网络基础}
\parinterval 神经网络是一种由大量的节点(或称神经元)之间相互连接构成的计算模型。那么什么是神经元?神经元之间又是如何连接的?神经网络的数学描述又是什么样的?这一节将围绕这些问题对神经网络的基础知识进行系统的介绍。
\parinterval 神经网络是一种由大量的节点(或称神经元)之间相互连接构成的计算模型。那么什么是神经元?神经元之间又是如何连接的?神经网络的数学描述又是什么样的?这一节将围绕这些问题对神经网络的基础知识进行系统的介绍。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -330,7 +330,7 @@
\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}
{(\mathbf a\mathbf b)}_{ij} &=& \prod_{k=1}^p a_{ik}b_{kj}
{(\mathbf a\mathbf b)}_{ij} &=& \sum_{k=1}^p a_{ik}b_{kj}
\label{eq:5-6}
\end{eqnarray}
......@@ -398,7 +398,7 @@ f(c\mathbf v)&=&cf(\mathbf v)
\label{eq:5-10}
\end{eqnarray}
\parinterval 利用矩阵$ \mathbf a\in R^{m\times n} $,可以实现两个有限维欧氏空间的映射函数$f:R^n\rightarrow R^m$。例如$ n $维列向量$ \mathbf x $$ m\times n $的矩阵$ \mathbf a $,向量$ \mathbf x $左乘矩阵$ \mathbf a $,可将向量$ \mathbf x $映射为$ m $列向量,对于:
\parinterval 利用矩阵$ \mathbf a\in R^{m\times n} $,可以实现两个有限维欧氏空间的映射函数$f:R^n\rightarrow R^m$。例如$ n $维列向量$ \mathbf x ^{\rm T}$$ m\times n $的矩阵$ \mathbf a $,向量$ \mathbf x ^{\rm T}$左乘矩阵$ \mathbf a $,可将向量$ \mathbf x ^{\rm T}$映射为$ m $列向量,对于:
\begin{eqnarray}
\mathbf x^{\textrm{T}} & = & {\begin{pmatrix} x_1, & x_2, & \dots &, x_n \end{pmatrix}}^{\rm T}
\label{eq:5-11}
......@@ -477,7 +477,7 @@ l_p(\mathbf x) & = & {\Vert{\mathbf x}\Vert}_p \nonumber \\
\parinterval 在深度学习中,有时候希望衡量矩阵的大小,这时可以考虑使用 {\small\bfnew{Frobenius 范数}}\index{Frobenius 范数}(Frobenius Norm)\index{Frobenius Norm}。计算方式为:
\begin{eqnarray}
{\Vert{\mathbf A}\Vert}_F&=&\sqrt{\sum_{i,j} A_{i,j}^2}
{\Vert{\mathbf a}\Vert}_F&=&\sqrt{\sum_{i,j} a_{i,j}^2}
\label{eq:5-18}
\end{eqnarray}
......@@ -554,7 +554,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
\begin{figure}[htp]
\centering
\input{./Chapter5/Figures/fig-perceptron-to-predict-1}
\caption{预测是否去剧场的感知机:权重相同}
\caption{预测是否去剧场的感知机(权重相同)}
\label{fig:5-6}
\end{figure}
%-------------------------------------------
......@@ -565,7 +565,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
\subsubsection{神经元内部权重}
\parinterval 在上面的例子中,连接权重代表着每个输入因素对最终输出结果的重要程度,为了得到令人满意的决策,需要不断调整权重。如果你是守财奴,则会对票价看得更重一些,这样你会用不均匀的权重计算每个因素的影响,比如:$ w_0=0.5 $$ w_1=2 $$ w_2=0.5 $,此时感知机模型如图\ref{fig:5-7}所示。在这种情况下,女友很希望和你一起去看音乐会,但是剧场很远而且票价500元,会导致你不去看音乐会,因为
\parinterval 在上面的例子中,连接权重代表着每个输入因素对最终输出结果的重要程度,为了得到令人满意的决策,需要不断调整权重。如果你是守财奴,则会对票价看得更重一些,这样你会用不均匀的权重计算每个因素的影响,比如:$ w_0=0.5 $$ w_1=2 $$ w_2=0.5 $,此时感知机模型如图\ref{fig:5-7}所示。在这种情况下,女友很希望和你一起去看音乐会,但是剧场很远而且票价500元,会导致你不去看音乐会,因为
\begin{eqnarray}
\sum_{i}{x_i\cdot w_i} & = & 0\cdot 0.5+0\cdot 2+1\cdot 0.5 \nonumber \\
& = & 0.5 \nonumber \\
......@@ -577,12 +577,12 @@ 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
\begin{figure}[htp]
\centering
\input{./Chapter5/Figures/fig-perceptron-to-predict-2}
\caption{预测是否去剧场的感知机:改变权重}
\caption{预测是否去剧场的感知机(改变权重)}
\label{fig:5-7}
\end{figure}
%-------------------------------------------
\parinterval 当然,结果是女友对这个结果非常不满意,让你跪键盘上反思一下自己。
\parinterval 当然,结果是女友对这个决定非常不满意,让你跪键盘上反思一下自己。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
......@@ -631,7 +631,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
\begin{figure}[htp]
\centering
\input{./Chapter5/Figures/fig-perceptron-to-predict-3}
\caption{预测是否去剧场的决策模型:只考虑女友喜好}
\caption{预测是否去剧场的决策模型(只考虑女友喜好)}
\label{fig:5-9}
\end{figure}
%-------------------------------------------
......@@ -644,9 +644,9 @@ 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
\begin{itemize}
\vspace{0.5em}
\item 对问题建模,即定义输入$ \{x_i\} $的形式
\item 对问题建模,即定义输入$ \{x_i\} $的形式
\vspace{0.5em}
\item 设计有效的决策模型,即定义$ y $
\item 设计有效的决策模型,即定义$ y $
\vspace{0.5em}
\item 决定模型所涉及的参数(如权重$ \{w_i\} $)的最优值。
\vspace{0.5em}
......@@ -696,7 +696,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
\end{figure}
%-------------------------------------------
\parinterval 在神经网络中,对于输入向量$ \mathbf x\in R^m $,一层神经网络首先将其经过线性变换映射到$ R^n $,再经过激活函数变成$ \mathbf y\in R^n $。还是上面天气预测的例子,每个神经元获得相同的输入,权重矩阵$ \mathbf w $是一个$ 2\times 3 $矩阵,矩阵中每个元素$ w_{ij} $代表第$ j $个神经元中$ x_{i} $对应的权重值,假设编号为0的神经元负责预测温度,则$ w_{0j} $含义为预测温度时,输入$ x_{i} $对其影响程度。此外所有神经元的偏置$ b_{0} $$ b_{1} $$ b_{2} $组成了最终的偏置向量$ \mathbf b $。在该例中则有,权重矩阵$ \mathbf w=\begin{pmatrix} w_{00} & w_{01} & w_{02}\\ w_{10} & w_{11} & w_{12}\end{pmatrix} $,偏置向量$ \mathbf b=(b_0,b_1,b_2) $
\parinterval 在神经网络中,对于输入向量$ \mathbf x\in R^m $,一层神经网络首先将其经过线性变换映射到$ R^n $,再经过激活函数变成$ \mathbf y\in R^n $。还是上面天气预测的例子,每个神经元获得相同的输入,权重矩阵$ \mathbf w $是一个$ 2\times 3 $矩阵,矩阵中每个元素$ w_{ij} $代表第$ j $个神经元中$ x_{i} $对应的权重值,假设编号为0的神经元负责预测温度,则$ w_{i0} $含义为预测温度时,输入$ x_{i} $对其影响程度。此外所有神经元的偏置$ b_{0} $$ b_{1} $$ b_{2} $组成了最终的偏置向量$ \mathbf b $。在该例中则有,权重矩阵$ \mathbf w=\begin{pmatrix} w_{00} & w_{01} & w_{02}\\ w_{10} & w_{11} & w_{12}\end{pmatrix} $,偏置向量$ \mathbf b=(b_0,b_1,b_2) $
\parinterval 那么,线性变换的本质是什么?
......@@ -732,7 +732,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
\end{figure}
%-------------------------------------------
\parinterval 也就是说,线性变换提供了对输入数据进行空间中旋转、平移的能力。当然,线性变换也适用于更加复杂的情况,这也为神经网络提供了拟合不同函数的能力。比如,可以利用线性变换将三维图形投影到二维平面上,或者将二维平面上的图形映射到三维平面。如图\ref{fig:5-14},通过一个简单的线性变换,可以将三维图形投影到二维平面上。
\parinterval 也就是说,线性变换提供了对输入数据进行空间中旋转、平移的能力。当然,线性变换也适用于更加复杂的情况,这也为神经网络提供了拟合不同函数的能力。比如,可以利用线性变换将三维图形投影到二维平面上,或者将二维平面上的图形映射到三维空间。如图\ref{fig:5-14},通过一个简单的线性变换,可以将三维图形投影到二维平面上。
%----------------------------------------------
\begin{figure}[htp]
......@@ -815,7 +815,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
\begin{figure}[htp]
\centering
\input{./Chapter5/Figures/fig-four-layers-of-neural-network}
\caption{具有三层神经元的四层神经网络}
\caption{具有四层神经元的三层神经网络}
\label{fig:5-17}
\end{figure}
%-------------------------------------------
......@@ -858,7 +858,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
\begin{figure}[htp]
\centering
\input{./Chapter5/Figures/fig-bias}
\caption{通过改变偏$ b_1 $改变目标函数位置}
\caption{通过改变偏$ b_1 $改变目标函数位置}
\label{fig:5-20}
\end {figure}
%-------------------------------------------
......@@ -869,12 +869,12 @@ 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
\begin{figure}[htp]
\centering
\input{./Chapter5/Figures/fig-w1}
\caption{通过改变偏移量$ w'_1 $将目标函数``拉高''或``压扁''}
\caption{通过改变权重$ w'_1 $将目标函数``拉高''或``压扁''}
\label{fig:5-21}
\end {figure}
%-------------------------------------------
\parinterval 设置$ w'_1=0.7 $$ w_1=100 $$ b_1=-4 $,其他参数设置为0。可以得到如图\ref{fig:5-22}\\(a)所示的目标函数,此时目标函数是一个阶梯函数。若是将其他参数设置为$ w'_2=0.7 $$ w_2=100 $$ b_2=16 $,由图\ref{fig:5-22}(b)可以看出,原来目标函数的``阶梯''由一级变成了两级,由此可以推测,由于将第二组参数进行设置,使目标函数分段数增多;若将第二组参数中的$ w'_2 $由原来的$ 0.7 $设置为$ -0.7 $,可得到如图\ref{fig:5-22}(c)所示的目标函数,与图\ref{fig:5-22}(b)相比,原目标函数的``第二级阶梯''向下翻转,由此可见$ w' $的符号决定了目标函数的翻转方向。
\parinterval 设置$ w'_1=0.7 $$ w_1=100 $$ b_1=-4 $,其他参数设置为0。可以得到如图\ref{fig:5-22}\\(a)所示的目标函数,此时目标函数是一个阶梯函数。若是将其他参数设置为$ w'_2=0.7 $$ w_2=100 $$ b_2=16 $,由图\ref{fig:5-22}(b)可以看出,原来目标函数的``阶梯''由一级变成了两级,由此可以推测,将第二组参数进行设置,可以使目标函数分段数增多;若将第二组参数中的$ w'_2 $由原来的$ 0.7 $设置为$ -0.7 $,可得到如图\ref{fig:5-22}(c)所示的目标函数,与图\ref{fig:5-22}(b)相比,原目标函数的``第二级阶梯''向下翻转,由此可见$ w' $的符号决定了目标函数的翻转方向。
%----------------------------------------------
\begin{figure}[htp]
......@@ -945,7 +945,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
\subsubsection{张量}
\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},比如下式中的几种情况都可以看作是深度学习中定义数据的张量:
\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}
\mathbf x&=&\begin{pmatrix} -1 & 3\end{pmatrix}\qquad
\mathbf x\;\;=\;\;\begin{pmatrix} -1 & 3\\ 0.2 & 2\end{pmatrix}\qquad
......@@ -977,9 +977,9 @@ 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
\label{eq:5-66}
\end{eqnarray}
\noindent 其中,$ c $为任意实数。这个性质非常重要,根据这个性质可以推导出张量的其他定义。
\noindent 其中,$ u $$ v_i $的同型向量,$ c $为任意实数。这个性质非常重要,根据这个性质可以推导出张量的其他定义。
\parinterval 从我们的物理世界看,如果一个物理量在物体的某个位置上只是一个单值,那么它是一个标量,例如密度;如果一个物理量在同一个位置、从多个方向上看,有不同的值,那么这个物理量就是一个张量比如物理学中常用的应力的描述就是一个典型的张量。举一个简单的例子:$ \mathbf T(\mathbf v,\mathbf u) $是一个三维空间$(\textrm{x},\textrm{y},\textrm{z})$上的2阶张量,其中$ \mathbf v $$ \mathbf u $ 是两个向量,如图\ref{fig:5-26}所示,向量$ \mathbf v $在某个两两垂直的三维坐标系中可以表示为$ {(\begin{array}{ccc} a & b & c\end{array})}^{\rm T} $,同理向量$ \mathbf u $在某个两两垂直的三维坐标系中可以表示为$ {(\begin{array}{ccc} a' & b' & c' \end{array})}^{\rm T} $。但在三维空间$(\textrm{x},\textrm{y},\textrm{z})$中,向量$ \mathbf v $和向量$ \mathbf u $分别被表示为$ {(\begin{array}{ccc} v_x & v_y & v_z\end{array})}^{\rm T} $$ {(\begin{array}{ccc} u_x & u_y & u_z\end{array})}^{\rm T} $
\parinterval 从我们的物理世界看,如果一个物理量在物体的某个位置上只是一个单值,那么它是一个标量,例如密度;如果一个物理量在同一个位置、从多个方向上看,有不同的值,那么这个物理量就是一个张量比如物理学中常用的应力的描述就是一个典型的张量。举一个简单的例子:$ \mathbf T(\mathbf v,\mathbf u) $是一个三维空间$(\textrm{x},\textrm{y},\textrm{z})$上的2阶张量,其中$ \mathbf v $$ \mathbf u $ 是两个向量,如图\ref{fig:5-26}所示,向量$ \mathbf v $在某个两两垂直的三维坐标系中可以表示为$ {(\begin{array}{ccc} a & b & c\end{array})}^{\rm T} $,同理向量$ \mathbf u $在某个两两垂直的三维坐标系中可以表示为$ {(\begin{array}{ccc} a' & b' & c' \end{array})}^{\rm T} $。但在三维空间$(\textrm{x},\textrm{y},\textrm{z})$中,向量$ \mathbf v $和向量$ \mathbf u $分别被表示为$ {(\begin{array}{ccc} v_x & v_y & v_z\end{array})}^{\rm T} $$ {(\begin{array}{ccc} u_x & u_y & u_z\end{array})}^{\rm T} $
%----------------------------------------------
\begin{figure}[htp]
......@@ -1001,7 +1001,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
\parinterval 其中,$ \begin{pmatrix} v_x\\v_y\\v_z\end{pmatrix} $是向量$ \mathbf v $在基向量$(\textrm{x},\textrm{y},\textrm{z})$上的投影,$ \begin{pmatrix} u_x\\u_y\\u_z\end{pmatrix} $是向量$ \mathbf u $在基向量$(\textrm{x},\textrm{y},\textrm{z})$上的投影,$ \begin{pmatrix}T_{xx} & T_{xy} & T_{xz}\\T_{yx} & T_{yy} & T_{yz}\\T_{zx} & T_{zy} & T_{zz}\end{pmatrix} $是张量$ \mathbf T $$3 \times 3$个方向上的分量,恰巧用``矩阵''表示,记为$ [\mathbf T] $
\parinterval 以上的内容是明确张量的原始定义,以避免对这个概念的误解。但是,本书仍然遵循深度学习中常用的概念,把张量理解为多维数组。在保证数学表达的简洁性的同时,使程序实现接口更加统一。
\parinterval 以上的内容是帮助大家明确张量的原始定义,以避免对这个概念的误解。但是,本书仍然遵循深度学习中常用的概念,把张量理解为多维数组。在保证数学表达的简洁性的同时,使程序实现接口更加统一。
%----------------------------------------------------------------------------------------
......@@ -1025,7 +1025,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
\label{}
\end{eqnarray}
\parinterval 将矩阵乘法扩展到高阶张量中:一个张量$ \mathbf x $若要与矩阵$ \mathbf w $做矩阵乘法,则$ \mathbf x $一维度需要与$ \mathbf w $的行数大小相等,即:若张量$ \mathbf x $的形状为$ \cdot \times n $$ \mathbf w $须为$ n\times \cdot $的矩阵。如下是一个例子:
\parinterval 将矩阵乘法扩展到高阶张量中:一个张量$ \mathbf x $若要与矩阵$ \mathbf w $做矩阵乘法,则$ \mathbf x $最后一维度需要与$ \mathbf w $的行数大小相等,即:若张量$ \mathbf x $的形状为$ \cdot \times n $$ \mathbf w $须为$ n\times \cdot $的矩阵。如下是一个例子:
\begin{eqnarray}
\mathbf x(1:4,1:4,{\red{1:4}})\times {\mathbf w({\red{1:4}},1:2)}=\mathbf s(1:4,1:4,1:2)
\label{eq:5-25}
......@@ -1052,7 +1052,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
\begin{itemize}
\vspace{0.5em}
\item $ \mathbf s+\mathbf b $中的单元加就是对张量中的每个位置都进行加法。在例中$ \mathbf s $是形状为$ (1:4,1:4,1:2) $的3阶张量,而$ \mathbf b $是含有4个元素的向量,在形状不同的情况下是怎样进行单元加的呢?在这里需要引入{\small\sffamily\bfseries{广播机制}}\index{广播机制}:如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失或长度为1的维度上进行,它是深度学习框架中常用的计算方式。来看一个具体的例子,如图\ref{fig:5-28}所示,$ \mathbf s $是一个$ 2\times 4 $的矩阵而$ \mathbf b $是一个长度为4的向量,这两者进行单元加运算时,广播机制会将$ \mathbf b $沿第一个维度复制后,再与$ \mathbf s $做加法运算。
\item $ \mathbf s+\mathbf b $中的单元加就是对张量中的每个位置都进行加法。在例中$ \mathbf s $是形状为$ (1:4,1:4,1:2) $的3阶张量,而$ \mathbf b $是含有4个元素的向量,在形状不同的情况下是怎样进行单元加的呢?在这里需要引入{\small\sffamily\bfseries{广播机制}}\index{广播机制}:如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失或长度为1的维度上进行,它是深度学习框架中常用的计算方式。来看一个具体的例子,如图\ref{fig:5-28}所示,$ \mathbf s $是一个$ 2\times 4 $的矩阵而$ \mathbf b $是一个长度为4的向量,这两者进行单元加运算时,广播机制会将$ \mathbf b $沿第一个维度复制后,再与$ \mathbf s $做加法运算。
%----------------------------------------------
\begin{figure}[htp]
......@@ -1064,7 +1064,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}
\item 除了单位加之外,张量之间也可以使用减法操作、乘法操作,也可以对张量作激活操作。这里将其称作为函数的{\small\bfnew{向量化}}\index{向量化}(Vectorization)\index{Vectorization}。例如,对向量(1阶张量)作ReLU激活,其中ReLU激活函数的公式为:
\item 除了单位加之外,张量之间也可以使用减法操作、乘法操作。此外也可以对张量作激活操作,这里将其称作为函数的{\small\bfnew{向量化}}\index{向量化}(Vectorization)\index{Vectorization}。例如,对向量(1阶张量)作ReLU激活,ReLU激活函数的公式为:
\begin{eqnarray}
f(x)=\begin{cases} 0 & x\le 0 \\x & x>0\end{cases}
\label{eq:5-26}
......@@ -1086,9 +1086,9 @@ f(x)=\begin{cases} 0 & x\le 0 \\x & x>0\end{cases}
\vspace{0.5em}
\item 张量$ \mathbf T(1:3) $表示一个含有三个元素的向量(1阶张量),其物理存储如图\ref{fig:5-29}(a)所示。
\vspace{0.5em}
\item 张量$ \mathbf T(1:2,1:3) $表示一个$ 3\times 2 $的矩阵(2阶张量),其物理存储如图\ref{fig:5-29}(b)所示。
\item 张量$ \mathbf T(1:2,1:3) $表示一个$ 2\times 3 $的矩阵(2阶张量),其物理存储如图\ref{fig:5-29}(b)所示。
\vspace{0.5em}
\item 张量$ \mathbf T(1:2,1:2,1:3) $表示一个大小$ 3\times 2\times 2 $的3阶张量,其物理存储如图\ref{fig:5-29}(c)所示。
\item 张量$ \mathbf T(1:2,1:2,1:3) $表示一个大小$ 2\times 2\times 3 $的3阶张量,其物理存储如图\ref{fig:5-29}(c)所示。
\vspace{0.5em}
\end{itemize}
......@@ -1191,7 +1191,7 @@ f(x)=\begin{cases} 0 & x\le 0 \\x & x>0\end{cases}
\end{figure}
%-------------------------------------------
\parinterval 除了上述单元算子外,NiuTensor还支持张量之间的高阶运算,其中最常用的矩阵乘法,图\ref{fig:5-36}是张量之间进行矩阵乘法的程序示例。表\ref{tab:5-2}展示了一些NiuTensor支持的其他函数操作,除此还有很多其他操作无法在此一一列举,有兴趣可以参考网站上的详细说明。
\parinterval 除了上述单元算子外,NiuTensor还支持张量之间的高阶运算,其中最常用的矩阵乘法,图\ref{fig:5-36}是张量之间进行矩阵乘法的程序示例。表\ref{tab:5-2}展示了一些NiuTensor支持的其他函数操作,除此还有很多其他操作无法在此一一列举,有兴趣可以参考网站上的详细说明。
%----------------------------------------------
\begin{figure}[htp]
......@@ -1232,7 +1232,7 @@ f(x)=\begin{cases} 0 & x\le 0 \\x & x>0\end{cases}
\end{table}
%--------------------------------------------------------------------
\parinterval 随后的内容会使用NiuTensor作为一种张量``语言''来完成神经网络的描述,以便于读者理解一个抽象的神经网络是如何和具体的程序对应起来的。当然,神经网络也可以使用TensorFlow和PyTorch等框架进行定义,方法都是非常相似的。
\parinterval 随后的内容会使用NiuTensor作为一种张量``语言''来完成神经网络的描述,以便于读者理解一个抽象的神经网络是如何和具体的程序对应起来的。当然,神经网络也可以使用TensorFlow和PyTorch等框架进行定义,方法都是非常相似的。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -1253,9 +1253,9 @@ f(x)=\begin{cases} 0 & x\le 0 \\x & x>0\end{cases}
\end{figure}
%-------------------------------------------
\parinterval 它可以被描述为公式\ref{eq:5-27},其中隐藏层的激活函数是Tanh函数,输出层的激活函数是Sigmoid函数:
\parinterval 它可以被描述为公式\ref{eq:5-27},其中隐藏层的激活函数是Tanh函数,输出层的激活函数是Sigmoid函数$\mathbf w^{[1]}$$\mathbf b^{[1]}$分别表示第一层的权重矩阵和偏置,$\mathbf w^{[2]}$$b^{[2]}$分别表示第二层的权重矩阵和偏置且偏置$b^{[2]}$是标量
\begin{eqnarray}
y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^1+\mathbf b^1)\cdot \mathbf w^2+\mathbf b^2 )
y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^{[1]}+\mathbf b^{[1]})\cdot \mathbf w^{[2]}+ b^{[2]} )
\label{eq:5-27}
\end{eqnarray}
......@@ -1268,9 +1268,9 @@ y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^1+\mathbf b^1)\cdot \mat
\end{figure}
%-------------------------------------------
\parinterval 前向计算实现如图\ref{fig:5-38}所示,图中对各张量和其他参数的形状做了详细说明。输入$ \mathbf x=(x_1,x_2,x_3) $是一个$1\times 3$的张量,其三个维度分别对应天空状况、低空气温、水平气压三个方面的数据。输入数据经过隐藏层的线性变换$ \mathbf x\cdot \mathbf w^1+\mathbf b^1 $和Tanh函数的激活,得到新的张量$ \mathbf a=(a_1,a_2) $,其中$a_1$$a_2$分别对应着从输入数据中提取出的温度和风速两方面特征;神经网络在获取到天气情况的特征$ \mathbf a $后,继续对其进行线性变换$ \mathbf a\cdot \mathbf w^2+ b^2 $(其中$b^2$是标量)和Sigmoid函数的激活操作,得到神经网络的最终输出$ y $,即神经网络此时预测的穿衣指数。
\parinterval 前向计算实现如图\ref{fig:5-38}所示,图中对各张量和其他参数的形状做了详细说明。输入$ \mathbf x=(x_1,x_2,x_3) $是一个$1\times 3$的张量,其三个维度分别对应天空状况、低空气温、水平气压三个方面的数据。输入数据经过隐藏层的线性变换$ \mathbf x\cdot \mathbf w^{[1]}+\mathbf b^{[1]}$和Tanh函数的激活,得到新的张量$ \mathbf a=(a_1,a_2) $,其中$a_1$$a_2$分别对应着从输入数据中提取出的温度和风速两方面特征;神经网络在获取到天气情况的特征$ \mathbf a $后,继续对其进行线性变换$ \mathbf a\cdot \mathbf w^{[2]}+ b^{[2]} $和Sigmoid函数的激活操作,得到神经网络的最终输出$ y $,即神经网络此时预测的穿衣指数。
\parinterval\ref{fig:5-38}实际上是神经网络的一种{\small\bfnew{计算图}}\index{计算图}(Computation Graph)\index{Computation Graph}表示。现在很多深度学习框架都是把神经网络转化为计算图,这样可以把复杂的运算分解为简单的运算。通过对计算图中节点的遍历,可以方便地完成神经网络的计算。比如,可以对图中节点进行拓扑排序(由输入到输出),之后依次访问每个节点同时完成相应的计算。这也就实现了一个前向计算的过程。构建计算图的方式有很多,比如,动态图、静态图等。在\ref{sec5:para-training}节会进一步对计算图在模型参数训练中的应用进行介绍。
\parinterval\ref{fig:5-38}实际上是神经网络的一种{\small\bfnew{计算图}}\index{计算图}(Computation Graph)\index{Computation Graph}表示。现在很多深度学习框架都是把神经网络转化为计算图,这样可以把复杂的运算分解为简单的运算。通过对计算图中节点的遍历,可以方便地完成神经网络的计算。比如,可以对图中节点进行拓扑排序(由输入到输出),之后依次访问每个节点,同时完成相应的计算,这也就实现了一个前向计算的过程。构建计算图的方式有很多,比如,动态图、静态图等。在\ref{sec5:para-training}节会进一步对计算图在模型参数训练中的应用进行介绍。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -1318,7 +1318,7 @@ y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^1+\mathbf b^1)\cdot \mat
\sectionnewpage
\section{神经网络的参数训练}
\parinterval 简单来说,神经网络可以被看作是由变量和函数组成的表达式,例如:$ \mathbf y=\mathbf x+\mathbf b $$ \mathbf y={\rm{ReLU}}(\mathbf x\cdot \mathbf w+\mathbf b) $$ \mathbf y={\rm{Sigmoid}}({\rm{ReLU}}(\mathbf x\cdot \mathbf w^1+\mathbf b^1)\cdot \mathbf w^2+\mathbf b^2) $等等,其中的$ \mathbf x $$ \mathbf y $作为输入和输出变量, $ \mathbf w $$ \mathbf b $等其他变量作为{\small\sffamily\bfseries{模型参数}}\index{模型参数}(Model Parameters)\index{Model Parameters}。确定了函数表达式和模型参数,也就确定了神经网络模型。通常,表达式的形式需要系统开发者设计,而模型参数的数量有时会非常巨大,因此需要自动学习,这个过程也被称为模型学习或{\small\bfnew{训练}}\index{训练}(Training)\index{Training}。为了实现这个目标,通常会准备一定量的带有标准答案的数据,称之为{\small\sffamily\bfseries{有标注数据}}\index{有标注数据}(Annotated Data/Labeled Data)\index{Annotated Data/Labeled Data}。这些数据会用于对模型参数的学习,这也对应了统计模型中的参数估计过程。在机器学习中,一般把这种使用有标注数据进行统计模型参数训练的过程称为{\small\sffamily\bfseries{有指导的训练}}\index{有指导的训练}{\small\sffamily\bfseries{有监督的训练}}\index{有监督的训练}(Supervised Training)\index{Supervised Training}。在本章中,如果没有特殊说明,模型训练都是指有监督的训练。那么神经网络内部是怎样利用有标注数据对参数进行训练的呢?
\parinterval 简单来说,神经网络可以被看作是由变量和函数组成的表达式,例如:$ \mathbf y=\mathbf x+\mathbf b $$ \mathbf y={\rm{ReLU}}(\mathbf x\cdot \mathbf w+\mathbf b) $$ \mathbf y={\rm{Sigmoid}}({\rm{ReLU}}(\mathbf x\cdot \mathbf w^{[1]}+\mathbf b^{[1]})\cdot \mathbf w^{[2]}+\mathbf b^{[2]}) $等等,其中的$ \mathbf x $$ \mathbf y $作为输入和输出变量, $ \mathbf w $$ \mathbf b $等其他变量作为{\small\sffamily\bfseries{模型参数}}\index{模型参数}(Model Parameters)\index{Model Parameters}。确定了函数表达式和模型参数,也就确定了神经网络模型。通常,表达式的形式需要系统开发者设计,而模型参数的数量有时会非常巨大,因此需要自动学习,这个过程也被称为模型学习或{\small\bfnew{训练}}\index{训练}(Training)\index{Training}。为了实现这个目标,通常会准备一定量的带有标准答案的数据,称之为{\small\sffamily\bfseries{有标注数据}}\index{有标注数据}(Annotated Data/Labeled Data)\index{Annotated Data/Labeled Data}。这些数据会用于对模型参数的学习,这也对应了统计模型中的参数估计过程。在机器学习中,一般把这种使用有标注数据进行统计模型参数训练的过程称为{\small\sffamily\bfseries{有指导的训练}}\index{有指导的训练}{\small\sffamily\bfseries{有监督的训练}}\index{有监督的训练}(Supervised Training)\index{Supervised Training}。在本章中,如果没有特殊说明,模型训练都是指有监督的训练。那么神经网络内部是怎样利用有标注数据对参数进行训练的呢?
\parinterval 为了回答这个问题,可以把模型参数的学习过程看作是一个优化问题,即找到一组参数,使得模型达到某种最优的状态。这个问题又可以被转化为两个新的问题:
......@@ -1381,7 +1381,7 @@ y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^1+\mathbf b^1)\cdot \mat
\subsection{基于梯度的参数优化}\label{sec5:para-training}
\parinterval 对于第$ i $个样本$ (\mathbf x_i,\mathbf {\widetilde y}_i) $,把损失函数$ Loss(\mathbf {\widetilde y}_i,\mathbf y_i) $看作是参数$ \mathbf w $的函数\footnote{为了简化描述,可以用$ \mathbf w $表示神经网络中的所有参数}。因为输出$ \mathbf y_i $是由输入$ \mathbf x_i $和模型参数$ \mathbf w $决定,因此也把损失函数写为$ L(\mathbf x_i,\mathbf {\widetilde y}_i;\mathbf w) $。参数学习过程可以被描述为
\parinterval 对于第$ i $个样本$ (\mathbf x_i,\mathbf {\widetilde y}_i) $,把损失函数$ Loss(\mathbf {\widetilde y}_i,\mathbf y_i) $看作是参数$ \mathbf w $的函数\footnote{为了简化描述,可以用$ \mathbf w $表示神经网络中的所有参数}。因为输出$ \mathbf y_i $是由输入$ \mathbf x_i $和模型参数$ \mathbf w $决定,因此也把损失函数写为$ L(\mathbf x_i,\mathbf {\widetilde y}_i;\mathbf w) $。参数学习过程可以被描述为
\begin{eqnarray}
\widehat{\mathbf w}&=&\mathop{\arg\min}_{\mathbf w}\frac{1}{n}\sum_{i=1}^{n}{L(\mathbf x_i,\mathbf {\widetilde y}_i;\mathbf w)}
\label{eq:5-28}
......@@ -1397,7 +1397,7 @@ y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^1+\mathbf b^1)\cdot \mat
\subsubsection{梯度下降}
\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}所示。
\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}所示。
%----------------------------------------------
\begin{figure}[htp]
......@@ -1414,7 +1414,7 @@ y&=&{\rm{Sigmoid}}({\rm{Tanh}}(\mathbf x\cdot \mathbf w^1+\mathbf b^1)\cdot \mat
\label{eq:5-29}
\end{eqnarray}
\noindent 其中$t $表示更新的步数,$ \alpha $是一个参数,被称作{\small\sffamily\bfseries{学习率}}\index{学习率}(Learning Rate)\index{Learning Rate},表示更新步幅的大小。$ \alpha $的设置需要根据任务进行调整。
\noindent 其中$t $表示更新的步数,$ \alpha $是一个参数,被称作{\small\sffamily\bfseries{学习率}}\index{学习率}(Learning Rate)\index{Learning Rate},表示更新步幅的大小。$ \alpha $的设置需要根据任务进行调整。
\parinterval 从优化的角度看,梯度下降是一种典型的 {\small\bfnew{基于梯度的方法}}\index{基于梯度的方法}(Gradient-based Method)\index{Gradient-based Method},属于基于一阶导数的方法。其他类似的方法还有牛顿法、共轭方向法、拟牛顿法等。在具体实现时,公式\ref{eq:5-29}可以有以下不同的形式。
......@@ -1450,7 +1450,7 @@ J(\mathbf w)&=&L(\mathbf x_i,\mathbf {\widetilde y}_i;\mathbf w)
\label{eq:5-31}
\end{eqnarray}
\noindent 由于每次只随机选取一个样本$(\mathbf x_i,\mathbf {\widetilde y}_i)$进行优化,这样更新的计算代价低,参数更新的速度大大加快,而且也适用于利用少量样本进行在线学习的情况\footnote{比如,训练数据不是一次给定的,而是随着模型的使用不断追加的。这时,需要不断地用新的训练样本更新模型,这种模式也被称作{\scriptsize\bfnew{在线学习}}(Online Learning)}
\noindent 由于每次只随机选取一个样本$(\mathbf x_i,\mathbf {\widetilde y}_i)$进行优化,这样更新的计算代价低,参数更新的速度大大加快,而且也适用于利用少量样本进行在线学习的情况\footnote{比如,训练数据不是一次给定的,而是随着模型的使用不断追加的。这时,需要不断地用新的训练样本更新模型,这种模式也被称作{\scriptsize\bfnew{在线学习}}(Online Learning)}
\parinterval 因为随机梯度下降算法每次优化的只是某一个样本上的损失,所以它的问题也非常明显:单个样本上的损失无法代表在全部样本上的损失,因此参数更新的效率低,方法收敛速度极慢。即使在目标函数为强凸函数的情况下,SGD仍旧无法做到线性收敛。
......@@ -1561,7 +1561,7 @@ $+2x^2+x+1)$ & \ \ $(x^4+2x^3+2x^2+x+1)$ & $+6x+1$ \\
\end{figure}
%-------------------------------------------
\parinterval 前向计算实际上就是网络构建的过程,所有的计算都会被转化为计算图上的节点,前向计算和反向计算都依赖计算图来完成。通常,构建计算图有以下两种实现方式
\parinterval 前向计算实际上就是网络构建的过程,所有的计算都会被转化为计算图上的节点,前向计算和反向计算都依赖计算图来完成。通常,构建计算图有以下两种实现方式
\begin{itemize}
\vspace{0.5em}
......@@ -1596,7 +1596,7 @@ $+2x^2+x+1)$ & \ \ $(x^4+2x^3+2x^2+x+1)$ & $+6x+1$ \\
\label{}
\end{eqnarray}
\noindent 其中$ \alpha $是一个参数,表示更新步幅的大小,称作{\small\bfnew{学习率}}\index{学习率}(Learning Rate)\index{Learning Rate}。当然,这是一种最基本的梯度下降方法。如果函数的形状非均向,比如呈延伸状,搜索最优点的路径就会非常低效,因为这时梯度的方向并没有指向最小值的方向,并且随着参数的更新,梯度方向往往呈锯齿状,这将是一条相当低效的路径;此外这种梯度下降算法并不是总能到达最优点,而是在其附近徘徊;还有一个最令人苦恼的问题\ \dash \ 设置学习率,如果学习率设置的比较小,会导致训练收敛速度慢,如果学习率设置的比较大,会导致训练过程中因为优化幅度过大而频频跳过最优点。我们希望网络在优化的时候损失函数有一个很好的收敛速度同时又不至于摆动幅度太大。
\noindent 其中$ \alpha $是一个参数,表示更新步幅的大小,称作{\small\bfnew{学习率}}\index{学习率}(Learning Rate)\index{Learning Rate}。当然,这是一种最基本的梯度下降方法。如果函数的形状非均向,比如呈延伸状,搜索最优点的路径就会非常低效,因为这时梯度的方向并没有指向最小值的方向,并且随着参数的更新,梯度方向往往呈锯齿状,这将是一条相当低效的路径;此外这种梯度下降算法并不是总能到达最优点,而是在其附近徘徊;还有一个最令人苦恼的问题\ \dash \ 设置学习率,如果学习率设置的比较小,会导致训练收敛速度慢,如果学习率设置的比较大,会导致训练过程中因为优化幅度过大而频频跳过最优点。我们希望网络在优化的时候损失函数有一个很好的收敛速度同时又不至于摆动幅度太大。
\parinterval 针对以上问题,很多学者尝试对梯度下降方法做出改进,如Momentum, Adagrad, Adadelta, RMSprop, Adam, AdaMax, Nadam, AMSGrad等等,在这里将介绍Momentum、AdaGrad、RMSprop、Adam这4 种方法。
......@@ -1645,7 +1645,7 @@ w_{t+1}&=&w_t-\eta \frac{1}{\sqrt{z_t}}\cdot \frac{\partial L}{\partial w_t}
\label{eq:5-37}
\end{eqnarray}
\parinterval 这里新出现了变量$ z $,它保存了以前的所有梯度值的平方和,在更新参数时,通过乘以$ \frac{1}{\sqrt{z_t}} $ ,就可以调整学习的尺度。这意味着,变动较大(被大幅更新)的参数的学习率将变小。也就是说,可以按参数的元素进行学习率衰减,使变动大的参数的学习率逐渐减小。
\parinterval 这里新出现了变量$ z $,它保存了以前的所有梯度值的平方和,在更新参数时,通过乘以$ \frac{1}{\sqrt{z_t}} $ ,就可以调整学习的尺度。这意味着,变动较大(被大幅更新)的参数的学习率将变小。也就是说,可以按参数的元素进行学习率衰减,使变动大的参数的学习率逐渐减小。
%----------------------------------------------------------------------------------------
%
......@@ -1686,7 +1686,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\noindent 可以看到Adam 算法相当于在RMSProp算法中引入了Momentum算法中的动量项,这样做使得Adam算法兼具了Momentum算法和RMSProp算法的优点:既能使梯度更为``平滑''地更新,同时可以为神经网络中的每个参数设置不同的学习率。
\parinterval 需要注意的是包括Adam在内的很多参数更新算法中的学习率都需要人为设置。而且模型学习的效果与学习率的设置关系极大,甚至在研发实际系统时工程师需要进行大量的实验,得到最佳的模型。第六章还会具体介绍在机器翻译中参数更新学习率设置的策略。
\parinterval 需要注意的是包括Adam在内的很多参数更新算法中的学习率都需要人为设置。而且模型学习的效果与学习率的设置关系极大,甚至在研发实际系统时工程师需要进行大量的实验,才能得到最佳的模型。第六章还会具体介绍在机器翻译中参数更新学习率设置的策略。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -1713,7 +1713,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\end {figure}
%-------------------------------------------
\parinterval\ref{fig:5-47}对比了同步更新和异步更新的区别,在这个例子中,使用4台设备对一个两层神经网络中的参数进行更新,其中使用了一个{\small\bfnew{参数服务器}}\index{参数服务器}(Parameter Server\index{Parameter Server},图中的G4)来保存最新的参数,不同设备(Worker,图中的G1、G2、G3)可以通过同步或者异步的方式访问参数服务器。图中的$ \mathbf w_o $$ \mathbf w_h $分别代表输出层和隐藏层的全部参数,操作push(P) 表示设备向参数服务器传送梯度,操作fetch(F)表示参数服务器向设备传送更新后的参数。
\parinterval\ref{fig:5-47}对比了同步更新和异步更新的区别,在这个例子中,使用4台设备对一个两层神经网络中的参数进行更新,其中使用了一个{\small\bfnew{参数服务器}}\index{参数服务器}(Parameter Server\index{Parameter Server})来保存最新的参数,不同设备(Worker,图中的G1、G2、G3)可以通过同步或者异步的方式访问参数服务器。图中的$ \mathbf w_o $$ \mathbf w_h $分别代表输出层和隐藏层的全部参数,操作push(P) 表示设备向参数服务器传送梯度,操作fetch(F)表示参数服务器向设备传送更新后的参数。
\parinterval 此外,在使用多个设备进行并行训练的时候,由于设备间带宽的限制,大量的数据传输会有较高的延时。对于复杂神经网络来说,设备间参数和梯度传递的时间消耗也会成为一个不得不考虑的因素。有时候,设备间数据传输的时间甚至比模型计算的时间都长,大大降低了并行度\cite{xiao2017fast}。对于这种问题,可以考虑对数据进行压缩或者减少传输的次数来缓解问题。
......@@ -1802,7 +1802,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\parinterval (3){\small\bfnew{残差网络}}\index{残差网络}(Residual Networks)\index{Residual Networks}
\parinterval 最初,残差网络是为了解决神经网络持续加深时的模型退化问题\cite{DBLP:journals/corr/HeZRS15},但是残差结构对解决梯度消失和梯度爆炸问题也有所帮助。有了残差结构,可以很轻松的构建几十甚至上百层的神经网络,而不用担心层数过深造成的梯度消失问题。残差网络的结构如图\ref{fig:5-51}所示:
\parinterval 最初,残差网络是为了解决神经网络持续加深时的模型退化问题\cite{DBLP:journals/corr/HeZRS15},但是残差结构对解决梯度消失和梯度爆炸问题也有所帮助。有了残差结构,可以很轻松的构建几十甚至上百层的神经网络,而不用担心层数过深造成的梯度消失问题。残差网络的结构如图\ref{fig:5-51}所示:
%----------------------------------------------
\begin{figure}[htp]
......@@ -1888,7 +1888,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
& = & \sum{h_j^{k-1}w_{j,i}^k}
\end{eqnarray}
\vspace{0.5em}
\item $ f^k $:第$ k $层的激活函数,$ \mathbf h_k=f^k(\mathbf s^k)$
\item $ f^k $:第$ k $层的激活函数,$ \mathbf h^k=f^k(\mathbf s^k)$
\vspace{0.5em}
\end{itemize}
......@@ -1960,7 +1960,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\begin{spacing}{1.6}
\begin{itemize}
\vspace{0.5em}
\item $ \frac{\partial L}{\partial \mathbf h^K} $表示损失函数$ L $相对网络输出$ \mathbf h^K $的梯度。比如,对于平方损失$ L=\frac{1}{2}{\Vert \widetilde {\mathbf y}-\mathbf h^K\Vert}^2 $,有$ \frac{\partial L}{\partial \mathbf h^K}= \widetilde{ \mathbf y} -\mathbf h^K $。计算结束后,将$ \frac{\partial L}{\partial \mathbf h^K} $向前传递。
\item $ \frac{\partial L}{\partial \mathbf h^K} $表示损失函数$ L $相对网络输出$ \mathbf h^K $的梯度。比如,对于平方损失$ L=\frac{1}{2}{\Vert \widetilde {\mathbf y}-\mathbf h^K\Vert}^2 $,有$ \frac{\partial L}{\partial \mathbf h^K}= \widetilde{ \mathbf y} -\mathbf h^K $。计算结束后,将$ \frac{\partial L}{\partial \mathbf h^K} $向前传递。
\vspace{0.5em}
\item $ \frac{\partial f^T(\mathbf s^K)}{\partial \mathbf s^K} $表示激活函数相对于其输入$ \mathbf s^K $的梯度。比如,对于Sigmoid函数$ f(\mathbf s)=\frac{1}{1+e^{- \mathbf s}}$,有$ \frac{\partial f(\mathbf s)}{\partial \mathbf s}=f(\mathbf s) (1-f(\mathbf s))$
\vspace{0.5em}
......@@ -2073,7 +2073,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\subsubsection{程序实现}
\parinterval 在了解了反向传播的原理之后,实现反向传播就变得非常容易了。实际上,现在主流的深度学习框架都支持自动微分。这里,为了进一步说明反向传播的过程,这里使用NiuTensor工具构建两个简单的实例,并分别尝试手动编写反向传播代码和使用NiuTensor自带的自动微分模块。
\parinterval 在了解了反向传播的原理之后,实现反向传播就变得非常容易了。实际上,现在主流的深度学习框架都支持自动微分。为了进一步说明反向传播的过程,这里使用NiuTensor工具构建两个简单的实例,并分别尝试手动编写反向传播代码和使用NiuTensor自带的自动微分模块。
\parinterval\ref{fig:5-58}展示了一个简单的神经网络的反向传播程序示例。这种反向传播的实现方式正是上一节内容的代码实现:按层实现自动微分并将梯度向前一层传播。
......@@ -2114,7 +2114,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\subsection{基于神经网络的语言建模}
\parinterval 回顾一下第二章的内容,语言建模的问题被定义为:对于一个词序列$ w_1w_2\dots w_m$,如何计算的可能性?词序列出现的概率可以通过链式法则得到:
\parinterval 回顾一下第二章的内容,语言建模的问题被定义为:对于一个词序列$ w_1w_2\dots w_m$,如何计算该词序列的可能性?词序列出现的概率可以通过链式法则得到:
\begin{eqnarray}
{\rm P}(w_1w_2\dots w_m)&=&{\rm P}(w_1){\rm P}(w_2|w_1){\rm P}(w_3|w_1w_2)\dots {\rm P}(w_m|w_1\dots w_{m-1})
\label{eq:5-57}
......@@ -2176,7 +2176,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\end{figure}
%-------------------------------------------
\parinterval 在FNNLM中,所有的参数、输入、输出都是连续变量,因此FNNLM也是典型的一个连续空间模型。通过使用交叉熵等损失函数,FNNLM很容易进行优化。比如,可以使梯度下降方法对FNNLM的模型参数进行训练。
\parinterval 在FNNLM中,所有的参数、输入、输出都是连续变量,因此FNNLM也是典型的一个连续空间模型。通过使用交叉熵等损失函数,FNNLM很容易进行优化。比如,可以使梯度下降方法对FNNLM的模型参数进行训练。
\parinterval FNNLM的实现也非常简单,图\ref{fig:5-61}展示了基于NiuTensor的FNNLM的部分代码。需要注意的是,在程序实现时, Tanh函数一般会用HardTanh函数代替。因为 Tanh函数中的指数运算容易导致溢出:
\begin{eqnarray}
......@@ -2201,7 +2201,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\parinterval 虽然FNNLM模型形式简单,却为处理自然语言提供了一个全新的视角。首先,该模型重新定义了``词是什么''\ \dash \ 它并非词典的一项,而是可以用一个连续实数向量进行表示的可计算的``量''。此外,由于$n$-gram不再是离散的符号序列,模型不需要记录$n$-gram,所以很好的缓解了上面所提到的数据稀疏问题,模型体积也大大减小。
\parinterval 当然,FNNLM模型也引发后人的许多思考,比如:神经网络每一层都学到了什么?是词法、句法还是一些其他知识?如何理解词的分布式表示?等等。在随后的内容中也会看到,随着近几年深度学习和自然语言处理的发展,部分问题已经得到了很好的解答,但是仍有许多问题需要进一步探索。
\parinterval 当然,FNNLM模型也引发后人的许多思考,比如:神经网络每一层都学到了什么?是词法、句法还是一些其他知识?如何理解词的分布式表示?等等。在随后的内容中也会看到,随着近几年深度学习和自然语言处理的发展,部分问题已经得到了很好的解答,但是仍有许多问题需要进一步探索。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
......@@ -2248,9 +2248,9 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\parinterval 通过引入记忆历史的能力,RNNLM缓解了$n$-gram模型中有限上下文的局限性,但依旧存在一些问题。随着序列变长,不同单词之间信息传递路径变长,信息传递的效率变低。对于长序列,很难通过很多次的循环单元操作保留很长的历史信息。过长的序列还容易引起梯度消失和梯度爆炸问题(详见\ref{sec:5.4.4}节),增加模型训练的难度。
\parinterval 对于这个问题,研究者又提出了一种新的结构$\ \dash \ ${\small\bfnew{自注意力机制}}\index{自注意力机制}(Self-Attention Mechanism)\index{Self-Attention Mechanism}。自注意力是一种特殊的神经网络结构,它可以对序列上任意两个词的相互作用直接进行建模,这样也就避免了循环神经网络中随着距离变长信息传递步骤增多的缺陷。在自然语言处理领域,自注意力机制被成功地应用在机器翻译,形成了著名的Transformer模型\cite{NIPS2017_7181}。第六章会系统地介绍自注意力机制和Transformer模型。
\parinterval 对于这个问题,研究者又提出了一种新的结构$\ \dash \ ${\small\bfnew{自注意力机制}}\index{自注意力机制}(Self-Attention Mechanism)\index{Self-Attention Mechanism}。自注意力是一种特殊的神经网络结构,它可以对序列上任意两个词的相互作用直接进行建模,这样也就避免了循环神经网络中随着距离变长信息传递步骤增多的缺陷。在自然语言处理领域,自注意力机制被成功地应用在机器翻译任务上,形成了著名的Transformer模型\cite{NIPS2017_7181}。第六章会系统地介绍自注意力机制和Transformer模型。
\parinterval 这里,先简单了解一下基于Transformer的语言模型结构(图\ref{fig:5-63})。与FNNLM\\和RNNLM一样,Transformer首先对输入单词进行分布式表示,同时加上每个位置的编码构成了整个模型的输入(蓝色方框)。之后,利用自注意力机制对输入的向量进行处理(绿色方框)。自注意力的结果会被送入一个前馈神经网络,之后再送给Softmax输出层(橙色方框)。
\parinterval 这里,先简单了解一下基于Transformer的语言模型结构(图\ref{fig:5-63})。与FNNLM\\和RNNLM一样,Transformer首先对输入单词进行分布式表示,同时加上每个单词的位置编码构成了整个模型的输入(蓝色方框)。之后,利用自注意力机制对输入的向量进行处理(绿色方框)。自注意力的结果会被送入一个前馈神经网络,之后再送给Softmax输出层(橙色方框)。
%----------------------------------------------
\begin{figure}[htp]
......@@ -2275,7 +2275,7 @@ w_{t+1}&=&w_t-\frac{\eta}{\sqrt{z_t+\epsilon}} v_t
\label{eq:5-65}
\end{eqnarray}
\parinterval 本质上,PPL反映了语言模型对序列可能性预测能力的一种评估。因为$ w_1\dots w_m $\\是真实的自然语言,``完美''的模型会得到$ {\rm P} (w_1\dots w_m)=1 $,它对应了最低的困惑度$ {\rm{PPL}}=1$这说明模型可以完美地对词序列出现的可能性进行预测。当然,真实的语言模型是无法达到$ {\rm{PPL}}=1$的,比如,在著名的Penn Treebank(PTB)数据上最好的语言模型的PPL值也只能到达35左右。可见自然语言处理任务的困难程度。
\parinterval 本质上,PPL反映了语言模型对序列可能性预测能力的一种评估。如果$ w_1\dots w_m $\\是真实的自然语言,``完美''的模型会得到$ {\rm P} (w_1\dots w_m)=1 $,它对应了最低的困惑度$ {\rm{PPL}}=1$这说明模型可以完美地对词序列出现的可能性进行预测。当然,真实的语言模型是无法达到$ {\rm{PPL}}=1$的,比如,在著名的Penn Treebank(PTB)数据上最好的语言模型的PPL值也只能到达35左右。可见自然语言处理任务的困难程度。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -2372,7 +2372,7 @@ Jobs was the CEO of {\red{\underline{apple}}}.
\qquad \qquad \; He finally ate the {\red{\underline{apple}}}.
\end{example}
\parinterval 这两句中``apple''的语义显然是不同的,第一句中的上下文``Jobs''和``CEO''可以帮助我们判断``apple''是一个公司名字,而不是水果。但是词嵌入只有一个结果,因此无法区分这两种情况。这个例子给我们一个启发:在一个句子中,不能孤立的看待单词,应同时考虑其上下文的信息。也就是需要一个能包含句子中上下文信息的表示模型。
\parinterval 这两句中``apple''的语义显然是不同的,第一句中的上下文``Jobs''和``CEO''可以帮助我们判断``apple''是一个公司名字,而不是水果。但是词嵌入只有一个结果,因此无法区分这两种情况。这个例子给我们一个启发:在一个句子中,不能孤立的看待单词,应同时考虑其上下文的信息。也就是需要一个能包含句子中上下文信息的表示模型。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
......@@ -2456,7 +2456,7 @@ Jobs was the CEO of {\red{\underline{apple}}}.
\begin{itemize}
\vspace{0.5em}
\item 第一个任务被称为Masked LM。在输入的词序列中随机挡住一定量的的词(比如15\%的单词被挡住),然后让模型去预测挡住的这些词。这个过程有些类似于英语考试中的完形填空。这么做的好处是,模型能够从多个方向去预测这些被遮罩住的词(图\ref{fig:5-72}),而不是像传统语言模型一样从单个方向预测(自左向右或者自右向左)。Masked LM的思想也影响了很多预训练模型的设计。
\item 第一个任务被称为Masked LM。在输入的词序列中随机挡住一定量的的词(比如15\%的单词被挡住),然后让模型去预测挡住的这些词。这个过程有些类似于英语考试中的完形填空。这么做的好处是,模型能够从多个方向去预测这些被遮罩住的词(图\ref{fig:5-72}),而不是像传统语言模型一样从单个方向预测(自左向右或者自右向左)。Masked LM的思想也影响了很多预训练模型的设计。
\vspace{0.5em}
\item 第二个任务是预测下一个句子。当选择句子a与b作为预训练样本时,b有一半几率可能是a的下一句,也有一半几率来自语料库的随机句子,从而可以更好地学习句子之间的相关性。
\vspace{0.5em}
......@@ -2515,6 +2515,6 @@ Jobs was the CEO of {\red{\underline{apple}}}.
\vspace{0.5em}
\item 词嵌入是自然语言处理近些年的重要进展。所谓“嵌入”是一类方法,理论上,把一个事物进行分布式表示的过程都可以被看作是广义上的“嵌入”。基于这种思想的表示学习也成为了自然语言处理中的前沿方法。比如,如何对树结构,甚至图结构进行分布式表示\cite{plank2013embedding}\cite{perozzi2014deepwalk}成为了分析自然语言的重要方法。此外,除了语言建模,还有很多方式可以进行词嵌入的学习,比如,SENNA\cite{collobert2011natural}、word2vec\cite{mikolov2013efficient}\cite{mikolov2013distributed}、Glove\cite{pennington2014glove}、CoVe\cite{mccann2017learned}等。
\vspace{0.5em}
\item 预训练是表示学习的重要产物。预训练已经在图像处理等领域得到应用。在自然语言处理中,以BERT为代表的预训练模型席卷了很多自然语言处理任务,在阅读理解等比赛(如Stanford Question Answering)中已经成为了所有参赛系统的标配。除了ELMO、GPT、BERT,还有很多优秀的预训练模型,包括GPT-2\cite{radford2019language}、XLM\cite{lample2019cross}、MASS\cite{song2019mass}、XLNet\cite{yang2019xlnet},等等。但是,预训练往往依赖大规模的数据和并行运算设备,这使得很多普通研究者对训练这样的模型望而却步。不过,也有一些研究关注轻量的预训练方法,也受到了很多关注,例如ALBERT\cite{lan2019albert}
\item 预训练是表示学习的重要产物。预训练已经在图像处理等领域得到应用。在自然语言处理中,以BERT为代表的预训练模型席卷了很多自然语言处理任务,在阅读理解等比赛(如Stanford Question Answering)中已经成为了所有参赛系统的标配。除了ELMO、GPT、BERT,还有很多优秀的预训练模型,包括GPT-2\cite{radford2019language}、XLM\cite{lample2019cross}、MASS\cite{song2019mass}、XLNet\cite{yang2019xlnet},等等。但是,预训练往往依赖大规模的数据和并行运算设备,这使得很多普通研究者对训练这样的模型望而却步。不过,也有一些研究轻量的预训练方法,也受到了很多关注,例如ALBERT\cite{lan2019albert}
\vspace{0.5em}
\end{itemize}
......@@ -22,12 +22,12 @@
%----------------------------------------------------------------------------------------
% NEW SECTION
%----------------------------------------------------------------------------------------
\vspace{-0.7em}
\section{神经机器翻译的发展简史}
\parinterval 纵观机器翻译的发展历程,神经机器翻译诞生很晚。无论是早期的基于规则的方法,还是逐渐发展起来的基于实例的方法,再到上世纪末的统计方法,每次机器翻译框架级的创新都需要很长时间的酝酿,而技术走向成熟甚至需要更长的时间。但是,神经机器翻译的出现和后来的发展速度多少有些令人``出人意料''。神经机器翻译的概念出现在2013-2014年间,当时机器翻译领域的主流方法仍然是统计机器翻译。虽然那个时期深度学习已经在图像、语音等领域取得令人瞩目的效果,但是对于自然语言处理来说深度学习仍然不是主流。这也导致当时的研究者对神经机器翻译这种方法还有一些排斥。
\parinterval 不过,有人也意识到了神经机器翻译在表示学习等方面的优势。特别是,以Yoshua Bengio团队为代表的研究力量对包括机器翻译在内的序列到序列问题进行了广泛而深入的研究,注意力机制等新的模型不断被推出。这使得神经机器翻译系统在翻译品质上逐渐体现出优势,甚至超越了当时的统计机器翻译系统。正当大家在讨论神经机器翻译是否能取代统计机器翻译成为下一代机器翻译的范式的时候,谷歌、百度等企业推出以神经机器翻译技术为内核的在线机器翻译服务在很多场景下的翻译品质显著超越了当时最好的统计机器翻译系统。这也引发了学术界和产业界对神经机器翻译的讨论。随着关注度的不断升高,神经机器翻译的研究吸引了更多的科研机构和企业的投入,神经机器翻译系统的翻译品质得到进一步提升。
\parinterval 不过,有人也意识到了神经机器翻译在表示学习等方面的优势。特别是,以Yoshua Bengio团队为代表的研究力量对包括机器翻译在内的序列到序列问题进行了广泛而深入的研究,注意力机制等新的模型不断被推出。这使得神经机器翻译系统在翻译品质上逐渐体现出优势,甚至超越了当时的统计机器翻译系统。正当大家在讨论神经机器翻译是否能取代统计机器翻译成为下一代机器翻译的范式的时候,谷歌、百度等企业推出以神经机器翻译技术为内核的在线机器翻译服务在很多场景下的翻译品质显著超越了当时最好的统计机器翻译系统。这也引发了学术界和产业界对神经机器翻译的讨论。随着关注度的不断升高,神经机器翻译的研究吸引了更多的科研机构和企业的投入,神经机器翻译系统的翻译品质得到进一步提升。
\parinterval 在短短5-6年间,神经机器翻译从一个新生的概念已经成长为机器翻译领域的最前沿技术之一,在各种机器翻译评测和应用中呈全面替代统计机器翻译之势。比如,从近几年WMT、CCMT等评测的结果来看,神经机器翻译已经处于绝对的统治地位,在不同语种和领域的翻译任务中,成为各参赛系统的标配。此外,从ACL等自然语言处理顶级会议的发表论文看,神经机器翻译是毫无疑问的焦点,在论文数量上呈明显的增长趋势,这也体现了学术界对该方法的热情。至今,无论是国外的著名企业,如谷歌、微软、脸书,还是国内的团队,如百度、腾讯、阿里巴巴、有道、搜狗、小牛翻译,都推出了自己研发的神经机器翻译系统,整个研究和产业生态欣欣向荣。图\ref{fig:6-1}展示了包含神经机器翻译在内的机器翻译发展简史。
......@@ -40,11 +40,11 @@
\end{figure}
%----------------------------------------------
\parinterval 神经机器翻译的迅速崛起确实让所有人都有些措手不及,甚至有一种一觉醒来天翻地覆的感觉。也有人评价,神经机器翻译的出现给整个机器翻译领域带来了前所未有的发展机遇。不过,客观看,机器翻译达到今天这样的状态也是一种历史必然,其中有几方面原因:
\parinterval 神经机器翻译的迅速崛起确实让所有人都有些措手不及,甚至有一种一觉醒来天翻地覆的感觉。也有人评价,神经机器翻译的出现给整个机器翻译领域带来了前所未有的发展机遇。不过,客观看,机器翻译达到今天这样的状态也是一种历史必然,其中有几方面原因:
\begin{itemize}
\vspace{0.5em}
\item 自上世纪末所发展起来的基于数据驱动的方法为神经机器翻译提供了很好的基础。本质上,神经机器翻译仍然是一种基于统计建模的数据驱动的方法,因此无论是对问题的基本建模方式,还是训练统计模型所使用到的带标注数据,都可以复用机器翻译领域以前的研究成果。特别是机器翻译长期的发展已经积累了大量的双语、单语数据,这些数据在统计机器翻译时代就发挥了很大作用。随着时间的推移,数据规模和质量又得到进一步提升,包括一些评测基准、任务设置都已经非常完备,研究者可以直接在数据条件全部具备的情况下开展神经机器翻译的研究工作,这些都省去了大量的时间成本。从这个角度说,神经机器翻译是站在巨人的肩膀上才发展起来的。
\item 自上世纪末所发展起来的基于数据驱动的方法为神经机器翻译提供了很好的基础。本质上,神经机器翻译仍然是一种基于统计建模的数据驱动的方法,因此无论是对问题的基本建模方式,还是训练统计模型所使用到的带标注数据,都可以复用机器翻译领域以前的研究成果。特别是机器翻译长期的发展已经积累了大量的双语、单语数据,这些数据在统计机器翻译时代就发挥了很大作用。随着时间的推移,数据规模和质量又得到进一步提升,包括一些评测基准、任务设置都已经非常完备,研究者可以直接在数据条件全部具备的情况下开展神经机器翻译的研究工作,这些都省去了大量的时间成本。从这个角度说,神经机器翻译是站在巨人的肩膀上才发展起来的。
\vspace{0.5em}
\item 深度学习经过长时间的酝酿终于爆发,为机器翻译等自然语言处理任务提供了新的思路和技术手段。神经机器翻译的不断壮大伴随着深度学习技术的发展。在深度学习的视角下,语言文字可以被表示成抽象的实数向量。这种文字的表示方法可以被自动学习,为机器翻译建模提供了更大的灵活性。相对于神经机器翻译,深度学习的发展更加曲折。虽然深度学习经过了漫长的起伏过程,但是神经机器翻译恰好出现在深度学习逐渐走向成熟的阶段。反过来说,受到深度学习及相关技术空前发展的影响,自然语言处理的范式也发生了变化,神经机器翻译的出现只是这种趋势下的一种必然。
\vspace{0.5em}
......@@ -54,17 +54,17 @@
\vspace{0.5em}
\end{itemize}
\parinterval 至今,神经机器翻译已经成为带有时代特征的标志性方法。当然,机器翻译的发展也远没有达到终点。下面将介绍神经机器翻译的起源和优势,以便读者在正式了解神经机器翻译的技术方法前对现状有一个充分的认识。
\parinterval 至今,神经机器翻译已经成为带有时代特征的标志性方法。当然,机器翻译的发展也远没有达到终点。下面将介绍神经机器翻译的起源和优势,以便读者在正式了解神经机器翻译的技术方法前对现状有一个充分的认识。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
%----------------------------------------------------------------------------------------
\vspace{-0.2em}
\subsection{神经机器翻译的起源}
\parinterval 从广义上讲,神经机器翻译是一种基于人工神经网络的方法,它把翻译过程描述为可以用人工神经网络表示的函数。所有的训练和推断都在这些函数上进行。由于神经机器翻译中的神经网络可以用连续可微函数表示,因此这类方法也可以用基于梯度的方法进行优化,相关技术非常成熟。更为重要的是,在神经网络的设计中,研究者引入了{\small\bfnew{分布式表示}} \index{分布式表示}(Distributed Representation)\index{Distributed Representation}的概念,这也是近些年自然语言处理领域的重要成果之一。传统统计机器翻译仍然把词序列看作离散空间里的由多个特征函数描述的点,类似于$n$-gram语言模型,这类模型对数据稀疏问题非常敏感。此外,人工设计特征也在一定程度上限制了模型对问题的表示能力。神经机器翻译把文字序列表示为实数向量,一方面避免了特征工程繁重的工作,另一方面使得系统可以对文字序列的``表示''进行学习。可以说,神经机器翻译的成功很大程度上源自`` 表示学习''这种自然语言处理的新范式的出现。在表示学习的基础上,注意力机制、深度神经网络等技术都被应用于神经机器翻译,使其得以进一步发展。
\parinterval 虽然神经机器翻译中大量的使用了人工神经网络方法,但是它并不是最早在机器翻译中使用人工神经网络的框架。实际上,人工神经网络在机器翻译中应用的历史要远早于现在的神经机器翻译。 在统计机器翻译时代,也有很多研究者利用人工神经网络进行机器翻译系统模块的构建\cite{devlin-etal-2014-fast,Schwenk_continuousspace},比如,Jacob Devlin等人就成功地在统计机器翻译系统中使用了基于神经网络的联合表示模型,取得了令人振奋的结果,这项工作也获得了ACL2014的最佳论文奖(best paper award)。
\parinterval 虽然神经机器翻译中大量的使用了人工神经网络方法,但是它并不是最早在机器翻译中使用人工神经网络的框架。实际上,人工神经网络在机器翻译中应用的历史要远早于现在的神经机器翻译。 在统计机器翻译时代,也有很多研究者利用人工神经网络进行机器翻译系统模块的构建\cite{devlin-etal-2014-fast,Schwenk_continuousspace},比如,Jacob Devlin等人就成功地在统计机器翻译系统中使用了基于神经网络的联合表示模型,取得了令人振奋的结果,这项工作也获得了ACL2014的最佳论文奖(Best Paper Award)。
\parinterval 不过,以上这些工作大多都是在系统的局部模块中使用人工神经网络和深度学习方法。与之不同的是,神经机器翻译是用人工神经网络完成整个翻译过程的建模,这样做的一个好处是,整个系统可以进行端到端学习,无需引入对任何翻译的隐含结构假设。这种利用端到端学习对机器翻译进行神经网络建模的方式也就成为了现在大家所熟知的神经机器翻译。这里简单列出部分代表性的工作:
......@@ -72,11 +72,11 @@
\vspace{0.5em}
\item 早在2013年,牛津大学的Nal Kalchbrenner和Phil Blunsom提出了一个基于编码器-解码器结构的新模型\cite{kalchbrenner-blunsom-2013-recurrent}。该模型用卷积神经网络(CNN)将源语言编码成实数向量,之后用循环神经网络(RNN)将连续向量转换成目标语言。这使得模型不需要进行词对齐、特征提取等工作,就能够自动学习源语言的信息。这也是一种端到端学习的方法。不过,这项工作的实现较复杂,而且方法存在梯度消失/爆炸等问题\cite{HochreiterThe,BENGIO1994Learning},因此并没有成为后来神经机器翻译的基础框架。
\vspace{0.5em}
\item 2014年,谷歌的Ilya Sutskever等人提出了序列到序列(seq2seq)学习的方法,同时将长短记忆结构(LSTM)引入到神经机器翻译中,这个方法解决了梯度爆炸/消失的问题,并且通过遗忘门的设计让网络选择性记忆信息,缓解了序列中长距离依赖的问题\cite{NIPS2014_5346}。但是该模型在进行编码的过程中,将不同长度的源语言句子压缩成了一个固定长度的向量,句子越长,损失的信息越多,同时该模型无法对输入和输出序列之间的对齐进行建模,因此并不能有效的保证翻译质量。
\item 2014年,谷歌的Ilya Sutskever等人提出了序列到序列(seq2seq)学习的方法,同时将长短记忆结构(LSTM)引入到神经机器翻译中,这个方法解决了梯度爆炸/消失的问题,并且通过遗忘门的设计让网络选择性记忆信息,缓解了序列中长距离依赖的问题\cite{NIPS2014_5346}。但是该模型在进行编码的过程中,将不同长度的源语言句子压缩成了一个固定长度的向量,句子越长,损失的信息越多,同时该模型无法对输入和输出序列之间的对齐进行建模,因此并不能有效的保证翻译质量。
\vspace{0.5em}
\item 同年Dzmitry Bahdanau等人首次将注意力机制(Attention Mechanism)应用到机器翻译领域,在机器翻译任务上对翻译和局部翻译单元之间的对应关系同时建模\cite{bahdanau2014neural}。Bahdanau等人工作的意义在于,使用了更加有效的模型来表示源语言的信息,同时使用注意力机制对两种语言不同部分之间的相互联系进行建模。这种方法可以有效处理长句子的翻译,而且注意力的中间结果具有一定的可解释性\footnote{比如,目标语言和源语言句子不同单词之间的注意力强度能够在一定程度上反应单词之间的互译程度。} 。然而相比于前人的神经机器翻译模型,注意力模型也引入了额外的成本,计算量较大。
\item 同年Dzmitry Bahdanau等人首次将注意力机制(Attention Mechanism)应用到机器翻译领域,在机器翻译任务上对翻译和局部翻译单元之间的对应关系同时建模\cite{bahdanau2014neural}。Bahdanau等人工作的意义在于,使用了更加有效的模型来表示源语言的信息,同时使用注意力机制对两种语言不同部分之间的相互联系进行建模。这种方法可以有效处理长句子的翻译,而且注意力的中间结果具有一定的可解释性\footnote{比如,目标语言和源语言句子不同单词之间的注意力强度能够在一定程度上反应单词之间的互译程度。} 。然而相比于前人的神经机器翻译模型,注意力模型也引入了额外的成本,计算量较大。
\vspace{0.5em}
\item 2016年谷歌发布了基于多层循环神经网络方法的GNMT系统。该系统集成了当时的神经机器翻译技术,并进行了诸多的改进。它的性能显著优于基于短语的机器翻译系统\cite{Wu2016GooglesNM},引起了研究者的广泛关注。在之后不到一年的时间里,Facebook采用卷积神经网络(CNN)研发了新的神经机器翻译系统\cite{DBLP:journals/corr/GehringAGYD17},实现了比基于循环神经网络(RNN)系统更好的翻译水平,并获得了明显的加速
\item 2016年谷歌发布了基于多层循环神经网络方法的GNMT系统。该系统集成了当时的神经机器翻译技术,并进行了诸多的改进。它的性能显著优于基于短语的机器翻译系统\cite{Wu2016GooglesNM},引起了研究者的广泛关注。在之后不到一年的时间里,Facebook采用卷积神经网络(CNN)研发了新的神经机器翻译系统\cite{DBLP:journals/corr/GehringAGYD17},实现了比基于循环神经网络(RNN)系统更高的翻译水平,并大幅提升翻译速度
\vspace{0.5em}
\item 2017年,谷歌的Ashish Vaswani等人提出了新的翻译模型Transformer。其完全抛弃了CNN、RNN等结构,仅仅通过自注意力机制(self-attentiion)和前向神经网络,不需要使用序列对齐的循环框架就展示出强大的性能,并且巧妙的解决了翻译中长距离依赖问题\cite{NIPS2017_7181}。Transformer是第一个完全基于注意力机制搭建的模型,不仅训练速度更快,在翻译任务上也获得了更好的结果,一跃成为目前最主流的神经机器翻译框架。
\vspace{0.5em}
......@@ -95,12 +95,32 @@
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter6/Figures/figure-example-of-mt}
\input{./Chapter6/Figures/figure-example-of-mt-1}
\setlength{\abovecaptionskip}{-0.2cm}
%\caption{机器翻译实例对比}
%\label{fig:6-2}
\end{figure}
%----------------------------------------------
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter6/Figures/figure-example-of-mt-2}
\setlength{\abovecaptionskip}{-0.2em}
\caption{机器翻译实例对比}
\label{fig:6-2}
\end{figure}
%----------------------------------------------
%----------------------------------------------
%\begin{figure}[htp]
%\centering
%\input{./Chapter6/Figures/figure-example-of-mt}
%\caption{机器翻译实例对比}
%\label{fig:6-2}
%\end{figure}
%----------------------------------------------
\vspace{-0.3em}
\parinterval 可以明显地看到译文2更加通顺,意思的表达更加准确,翻译质量明显高于译文1。这个例子基本反应出统计机器翻译和神经机器翻译的差异性。当然,这里并不是要讨论统计机器翻译和神经机器翻译孰优孰劣。但是,很多场景中都不难发现神经机器翻译可以生成非常流畅的译文,易于人工阅读和修改。
\parinterval 在很多量化的评价中也可以看到神经机器翻译的优势。回忆一下第一章提到的机器翻译质量的自动评估指标中,使用最广泛的一种指标是BLEU。在统计机器翻译时代,在由美国国家标准和科技机构(NIST)举办的汉英机器翻译评测中(比如汉英MT08数据集),基于统计方法的翻译系统能够得到30\%以上的BLEU值已经是当时最顶尖的结果了。而现在的神经机器翻译系统,则可以轻松的将BLEU提高至45\%以上。
......@@ -114,19 +134,20 @@
\end{figure}
%----------------------------------------------
\parinterval 同样,在机器翻译领域中最具影响力的评测比赛WMT(Workshop of Machine Translation)中,使用统计机器翻译方法的参赛系统也在逐年减少。而现在获得比赛冠军的系统中几乎没有只使用纯统计机器翻译模型的系统\footnote{但是,仍然有大量的统计机器翻译和神经机器翻译融合的方法。比如,在无指导机器翻译中,统计机器翻译仍然被作为初始模型。} 。图\ref{fig:6-3}展示了近年来WMT比赛冠军系统中神经机器翻译系统的占比逐年提高。
\parinterval 同样,在机器翻译领域中最具影响力的评测比赛WMT(Workshop of Machine Translation)中,使用统计机器翻译方法的参赛系统也在逐年减少。而现在获得比赛冠军的系统中几乎没有只使用纯统计机器翻译模型的系统\footnote{但是,仍然有大量的统计机器翻译和神经机器翻译融合的方法。比如,在无指导机器翻译中,统计机器翻译仍然被作为初始模型。} 。图\ref{fig:6-3}展示了近年来WMT比赛冠军系统中神经机器翻译系统的占比,可见神经机器翻译系统的占比在逐年提高。
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter6/Figures/figure-score-of-mTER}
\caption{不同系统在不同长度句子上的mTER分值}
\caption{不同系统在不同长度句子上的mTER分值(得分越低越好)}
\label{fig:6-4}
\end{figure}
%----------------------------------------------
\parinterval 除了上面例子中展示的流畅度和准确度外,神经机器翻译在其他评价指标上的表现也全面超越统计机器翻译\cite{Bentivogli2016NeuralVP}。比如,在IWSLT 2015英语-德语任务中,与三个最先进的统计机器翻译系统(PBSY、HPB、SPB)相比,神经机器翻译系统的mTER得分在不同长度句子上都有明显的下降,如图\ref{fig:6-4}\footnote{mTER是一种错误率度量,值越低表明译文越好。}。其次,神经机器翻译的单词形态错误率和单词词义错误率都远低于统计机器翻译系统(表\ref{tab:6-1} )。
\vspace{0.5em}%全局布局使用
%----------------------------------------------
\begin{table}[htp]
\centering
......@@ -144,6 +165,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\parinterval 更振奋人心的是,神经机器翻译在某些任务上的结果已经相当惊艳,比如在汉英新闻翻译任务中,神经机器翻译就取得了至少和专业翻译人员相媲美的效果\cite{Hassan2018AchievingHP}。在该任务中,神经机器系统(Combo-4、Combo-5 和 Combo-6)的人工评价得分与Reference-HT(专业翻译人员翻译)的得分无显著差别,且远超Reference-WMT(WMT的参考译文,也是由人类翻译)得分(表\ref{tab:6-2})。
\vspace{0.5em}%全局布局使用
%----------------------------------------------
\begin{table}[htp]
\centering
......@@ -162,6 +184,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\parinterval 在最近两年,神经机器翻译的发展更加迅速,新的模型、方法层出不穷。表\ref{tab:6-3}给出了2019年一些主流的神经机器翻译模型的对比\cite{WangLearning}。可以看到,相比2017年,2018-2019年中机器翻译仍然有明显的进步。
\vspace{0.5em}%全局布局使用
%----------------------------------------------
\begin{table}[htp]
\centering
......@@ -186,6 +209,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\subsection{神经机器翻译的优势 }
\vspace{1em}%全局布局使用
%----------------------------------------------
\begin{table}[htp]
\centering
......@@ -203,22 +227,27 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\parinterval 既然神经机器翻译如此强大,它的优势在哪里呢?为了回答这个问题,表\ref{tab:6-4}给出了神经机器翻译与统计机器翻译的简单对比。具体来说,神经机器翻译有如下特点:
\vspace{0.5em}
\parinterval (一)分布式连续空间表示模型,能捕获更多隐藏信息
\parinterval 神经机器翻译与统计机器翻译最大的区别在于对语言文字串的表示方法上。在统计机器翻译中,所有词串本质上都是由更小的词串(短语、规则)组合而成,也就是机器翻译模型利用了词串之间的组合性来表示更大的词串。统计机器翻译使用多个特征描述翻译结果,但是其仍然对应着离散的字符串的组合,因此可以把模型对问题的表示空间看做是由一个离散结构组成的集合。在神经机器翻译中,词串的表示已经被神经网络转化为多维实数向量,而且也不依赖任何的可组合性等假设来刻画离散的语言结构,从这个角度说,所有的词串对应了一个连续空间上的点(比如,对应$n$维实数空间中一个点)。这样,模型可以更好的进行优化,而且对未见样本有更好的泛化能力。此外,基于连续可微函数的机器学习算法已经相对完备,可以很容易的对问题进行建模和优化。
\parinterval 神经机器翻译与统计机器翻译最大的区别在于对语言文字串的表示方法上。在统计机器翻译中,所有词串本质上都是由更小的词串(短语、规则)组合而成,也就是统计机器翻译模型利用了词串之间的组合性来表示更大的词串。统计机器翻译使用多个特征描述翻译结果,但是其仍然对应着离散的字符串的组合,因此可以把模型对问题的表示空间看做是由一个离散结构组成的集合。在神经机器翻译中,词串的表示已经被神经网络转化为多维实数向量,而且也不依赖任何的可组合性假设等其他假设来刻画离散的语言结构,从这个角度说,所有的词串分别对应了一个连续空间上的点(比如,对应$n$维实数空间中一个点)。这样,模型可以更好地进行优化,而且对未见样本有更好的泛化能力。此外,基于连续可微函数的机器学习算法已经相对完备,可以很容易的对问题进行建模和优化。
\vspace{0.5em}
\parinterval (二)不需要特征工程,特征学习更加全面
\parinterval 经典的统计机器翻译可以通过判别式模型引入任意特征,不过这些特征需要人工设计,因此这个过程也被称为{\small\bfnew{特征工程}} \index{特征工程}(Feature Engineering)\index{Feature Engineering}。特征工程依赖大量的人工,特别是对不同语种、不同场景的翻译任务,所采用的特征可能不尽相同,这也使得设计有效的特征成为了统计机器翻译时代最主要的工作之一。但是,由于人类自身的思维和认知水平的限制,人工设计的特征可能不全面,甚至会遗漏一些重要的翻译现象。神经机器翻译并不依赖任何人工特征的设计,或者说它的特征都隐含在分布式表示中。这些``特征''都是自动学习得到的,因此神经机器翻译并不会受到人工思维的限制,学习到的特征对问题描述更加全面。
\parinterval 经典的统计机器翻译可以通过判别式模型引入任意特征,不过这些特征需要人工设计,因此这个过程也被称为{\small\bfnew{特征工程}} \index{特征工程}(Feature Engineering)\index{Feature Engineering}。特征工程依赖大量的人工,特别是对不同语种、不同场景的翻译任务,所采用的特征可能不尽相同,这也使得设计有效的特征成为了统计机器翻译时代最主要的工作之一。但是,由于人类自身的思维和认知水平的限制,人工设计的特征可能不全面,甚至会遗漏一些重要的翻译现象。神经机器翻译并不依赖任何人工特征的设计,或者说它的特征都隐含在分布式表示中。这些``特征''都是自动学习得到的,因此神经机器翻译并不会受到人工思维的限制,学习到的特征对问题描述更加全面。
\vspace{0.5em}
\parinterval (三)不含隐含结构假设,端到端学习对问题建模更加直接
\parinterval 传统的自然语言处理任务会对问题进行隐含结构假设。比如,进行翻译时,统计机器翻译会假设翻译过程由短语的拼装完成。这些假设可以大大化简问题的复杂度,但是另一方面也带来了各种各样的约束条件。错误的隐含假设往往会导致建模错误。神经机器翻译是一种端到端模型,它并不依赖任何隐含结构假设。这样,模型并不会受到错误的隐含结构的引导。从某种意义上说,端到端学习可以让模型更加`` 自由''进行学习,因此往往可以学到很多传统认知上不容易理解或者不容易观测到的现象。
\parinterval 传统的自然语言处理任务会对问题进行隐含结构假设。比如,进行翻译时,统计机器翻译会假设翻译过程由短语的拼装完成。这些假设可以大大化简问题的复杂度,但是另一方面也带来了各种各样的约束条件。错误的隐含假设往往会导致建模错误。神经机器翻译是一种端到端模型,它并不依赖任何隐含结构假设。这样,模型并不会受到错误的隐含结构的引导。从某种意义上说,端到端学习可以让模型更加`` 自由''进行学习,因此往往可以学到很多传统认知上不容易理解或者不容易观测到的现象。
\vspace{0.5em}
\parinterval (四)模型结构统一,存储消耗更小
\parinterval 统计机器翻译系统依赖于很多模块,比如词对齐、短语(规则)表、目标语言模型等等,因为所有的信息(如$n$-gram)都是离散化表示的,因此模型需要消耗大量的存储资源。同时,由于系统模块较多,开发的难度也较大。神经机器翻译的模型都是用神经网络进行表示,模型参数大多是实数矩阵,因此存储资源的消耗很小。而且神经网络可以作为一个整体进行开发和调试,系统搭建的代价相对较低。实际上,由于模型体积小,神经机器翻译也非常合适于离线小设备上的翻译任务。
\vspace{0.5em}
\parinterval 当然,神经机器翻译也并不完美,很多问题有待解决。首先,神经机器翻译需要大规模浮点运算的支持,模型的推断速度较低。为了获得优质的翻译结果,往往需要大量GPU设备的支持,计算资源成本很高;其次,由于缺乏人类的先验知识对翻译过程的指导,神经机器翻译的运行过程缺乏可解释性,系统的可干预性也较差;此外,虽然脱离了繁重的特征工程,神经机器翻译仍然需要人工设计网络结构,包括在模型的各种超参的设置、训练策略的选择等方面,仍然需要大量人工参与。这也导致很多实验结果不容易重现。显然,完全不依赖人工进行机器翻译还很遥远。不过,随着研究者的不断攻关,很多问题也得到了解决。
%----------------------------------------------------------------------------------------
......@@ -237,8 +266,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
%----------------------------------------------------------------------------------------
\subsection{框架结构}
\parinterval 编码器-解码器框架是一种典型的基于``表示''的模型。编码器的作用是将输入的文字序列通过某种转换变为一种新的``表示''形式,这种``表示''包含了输入序列的所有信息。之后,解码器把这种``表示''重新转换为输出的文字序列。这其中的一个核心问题是表示学习,即:如何定义对输入文字序列的表示形式,并自动学习这种表示,同时应用它生成输出序列。一般来说,不同的表示学习方法可以对应不同的机器翻译模型,比如,在最初的神经机器翻译模型中,源语言句子都被表示为一个独立的向量,这时表示结果是静态的;而在注意力机制中,源语言句子的表示是动态的,也就是翻译目标语每个单词时都会使用不同的表示结果。
\parinterval 编码器-解码器框架是一种典型的基于``表示''的模型。编码器的作用是将输入的文字序列通过某种转换变为一种新的``表示''形式,这种``表示''包含了输入序列的所有信息。之后,解码器把这种``表示''重新转换为输出的文字序列。这其中的一个核心问题是表示学习,即:如何定义对输入文字序列的表示形式,并自动学习这种表示,同时应用它生成输出序列。一般来说,不同的表示学习方法可以对应不同的机器翻译模型,比如,在最初的神经机器翻译模型中,源语言句子都被表示为一个独立的向量,这时表示结果是静态的;而在注意力机制中,源语言句子的表示是动态的,也就是翻译目标语的每个单词时都会使用不同的表示结果。
\parinterval\ref{fig:6-5}是一个应用编码器-解码器结构来解决机器翻译问题的简单实例。给定一个中文句子``我\ \ \ 感到\ 满意'',编码器会将这句话编码成一个实数向量(0.2,-1,6,5,0.7,-2),这个向量就是源语言句子的``表示''结果。虽然有些不可思议,但是神经机器翻译模型把这个向量等同于输入序列。向量中的数字并没有实际的意义,然而解码器却能从中提取到源语句子中所包含的信息。也有研究者把向量的每一个维度看作是一个``特征'',这样源语言句子就被表示成多个``特征''的联合,而且这些特征可以被自动学习。有了这样的源语言句子的``表示'',解码器可以把这个实数向量作为输入,然后逐词生成目标语句子``I am satisfied with you''。
......@@ -263,7 +291,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\parinterval 编码器-解码器框架的创新之处在于,将传统基于符号的离散型知识转化为分布式的连续型知识。比如,对于一个句子,它可以由离散的符号所构成的文法规则来生成,也可以直接被表示为一个实数向量记录句子的各个``属性''。这种分布式的实数向量可以不依赖任何离散化的符号系统,简单来说,它就是一个函数,把输入的词串转化为实数向量。更为重要的是,这种分布式表示可以被自动学习。或者从某种意义上说,编码器-解码器框架的作用之一就是学习输入序列的表示。表示结果学习的好与坏很大程度上会影响神经机器翻译系统的性能。
\parinterval\ref{fig:6-6}形象对比了统计机器翻译和神经机器翻译的表示模型的区别。传统的统计机器翻译(a)通过短语或者规则组合来获得更大的翻译片段,直至覆盖整个句子。这本质上是在一个离散的结构空间中不断组合的过程。神经机器翻译(b)与之不同,它并没有所谓的``组合''的过程,整个句子的处理是直接在连续空间上进行计算得到的。这二者的区别也体现了符号系统与神经网络系统的区别。前者更适合处理离散化的结构表示,后者更适合处理连续化的表示。
\parinterval\ref{fig:6-6}形象对比了统计机器翻译和神经机器翻译的表示模型的区别。传统的统计机器翻译(a)通过短语或者规则组合来获得更大的翻译片段,直至覆盖整个句子。这本质上是在一个离散的结构空间中不断组合的过程。神经机器翻译(b)与之不同,它并没有所谓的``组合''的过程,整个句子的处理是直接在连续空间上进行计算得到的。这二者的区别也体现了符号系统与神经网络系统的区别。前者更适合处理离散化的结构表示,后者更适合处理连续化的表示。
%----------------------------------------------
\begin{figure}[htp]
......@@ -274,9 +302,9 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\end{figure}
%----------------------------------------------
\parinterval 实际上,编码器-解码器模型也并不是表示学习实现的唯一途径。比如,在第五章提到的神经语言模型实际上也是一种有效的学习句子表示的方法,它所衍生出的预训练模型可以从大规模单语数据上学习句子的表示形式。这种学习会比使用少量的双语数据进行编码端和解码端的学习更加充分。相比机器翻译任务,语言模型相当于一个编码器的学习 \footnote{相比神经机器翻译的编码器,神经语言模型会多出一个输出层,这时可以直接把神经语言模型的中间层的输出作为编码器的输出。},可以无缝嵌入到神经机器翻译模型中。不过,值得注意的是,机器翻译的目的是解决双语字符串之间的映射问题,因此它所使用的句子表示是为了更好的进行翻译。从这个角度说,机器翻译中的表示学习又和语言模型的表示学习有不同。不过,这里不会深入讨论神经语言模型和预训练与神经机器翻译之间的异同,感兴趣的读者可以参看第五章的相关内容。
\parinterval 实际上,编码器-解码器模型也并不是表示学习实现的唯一途径。比如,在第五章提到的神经语言模型实际上也是一种有效的学习句子表示的方法,它所衍生出的预训练模型可以从大规模单语数据上学习句子的表示形式。这种学习会比使用少量的双语数据进行编码端和解码端的学习更加充分。相比机器翻译任务,语言模型相当于一个编码器的学习 \footnote{相比神经机器翻译的编码器,神经语言模型会多出一个输出层,这时可以直接把神经语言模型的中间层的输出作为编码器的输出。},可以无缝嵌入到神经机器翻译模型中。不过,值得注意的是,机器翻译的目的是解决双语字符串之间的映射问题,因此它所使用的句子表示是为了更好地进行翻译。从这个角度说,机器翻译中的表示学习又和语言模型中的表示学习有不同。不过,这里不会深入讨论神经语言模型和预训练与神经机器翻译之间的异同,感兴趣的读者可以参看第五章的相关内容。
\parinterval 还有一点,在神经机器翻译中,句子的表示形式可以有很多选择。使用单个向量表示一个句子是一种最简单的方法。当然,也可以用矩阵、高阶张量完成表示。甚至,在解码时动态生成源语言的表示结果。这部分技术也会在随后的内容中进行介绍。
\parinterval 还有一点,在神经机器翻译中,句子的表示形式可以有很多选择。使用单个向量表示一个句子是一种最简单的方法。当然,也可以用矩阵、高阶张量完成表示。甚至,在解码时动态生成源语言的表示结果。这部分技术也会在随后的内容中进行介绍。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -318,8 +346,6 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\parinterval 对于不同类型的机器翻译方法,人类所扮演的作用是不同的。在统计机器翻译时代,往往需要人工来定义翻译时所需要的特征和翻译单元,翻译中的每一个步骤对于人来说都是透明的,翻译过程具有一定的可解释性。而在神经机器翻译时代,神经机器翻译将所有的工作都交给神经网络,翻译的过程完全由神经网络计算得到。在整个神经网络的运行过程中并不需要人工先验知识,其中所生成的中间表示也只有神经网络自身才可以理解。有时候也会把神经机器翻译系统看作``黑盒''。所谓``黑盒''并不是指神经网络计算的过程不可见,而是这种复杂的计算过程无法控制也很难解释。那么是神经机器翻译会魔法吗,不需要任何人为的干预就可以进行翻译吗?其实不然,相对于统计机器翻译,真正变化的是人类使用知识的形式。
\parinterval 在机器翻译的不同时期,人类参与到机器翻译中的形式并不相同。如表\ref{tab:6-5}所述,在早期基于规则的方法中,规则的编写、维护均需要人来完成,也就是人类直接提供了计算机可读的知识形式;在统计机器翻译方法中,则需要人为的设计翻译特征,并且定义基本翻译单元的形式,然后剩下的事情(比如翻译过程)交由统计机器翻译算法完成,也就是人类间接的提供了翻译所需要的知识;在神经机器翻译方法中,特征的设计完全不需要人的参与,但是完成特征提取的网络结构仍然需要人为的设计,训练网络所需要的参数也需要工程师的不断调整,才能发挥神经机器翻译的强大性能。
%----------------------------------------------
\begin{table}[htp]
\centering
......@@ -334,6 +360,8 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\end{table}
%----------------------------------------------
\parinterval 在机器翻译的不同时期,人类参与到机器翻译中的形式并不相同。如表\ref{tab:6-5}所述,在早期基于规则的方法中,规则的编写、维护均需要人来完成,也就是人类直接提供了计算机可读的知识形式;在统计机器翻译方法中,则需要人为的设计翻译特征,并且定义基本翻译单元的形式,然后剩下的事情(比如翻译过程)交由统计机器翻译算法完成,也就是人类间接的提供了翻译所需要的知识;在神经机器翻译方法中,特征的设计完全不需要人的参与,但是完成特征提取的网络结构仍然需要人为地设计,训练网络所需要的参数也需要工程师的不断调整,才能发挥神经机器翻译的强大性能。
\parinterval 可见,不管是基于规则的机器翻译方法,还是统计机器翻译方法,甚至今天的神经机器翻译方法,人类的作用是不可替代的。虽然神经机器翻译很强大,但是它的成功仍然依赖人工设计网络结构、调参。纵然,也有一些研究工作通过结构搜索的方法自动获得神经网络结构,但是搜索的算法和模型仍然需要人工设计。当然,这里不是要讨论一个新的悖论,因为结论还是很简单的:机器翻译是人类设计的,脱离了人的工作,机器翻译是不可能成功的。
%----------------------------------------------------------------------------------------
......@@ -344,7 +372,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\section{基于循环神经网络的翻译模型及注意力机制}
\label{sec:6.3}
\parinterval 早期神经机器翻译的进展主要来自两个方面:1)使用循环神经网络对单词序列进行建模;2)注意力机制的使用。表\ref{tab:6-6}列出了2013-2015年间有代表性的部分研究工作。从这些工作的内容上看,当时的研究重点还是如何有效使用循环神经网络进行翻译建模以及使用注意力机制捕捉双语单词序列间的对应关系。
\parinterval 早期神经机器翻译的进展主要来自两个方面:1)使用循环神经网络对单词序列进行建模;2)注意力机制的使用。表\ref{tab:6-6}列出了2013-2015年间有代表性的部分研究工作。从这些工作的内容上看,当时的研究重点还是如何有效使用循环神经网络进行翻译建模以及使用注意力机制捕捉双语单词序列间的对应关系。
%----------------------------------------------
\begin{table}[htp]
......@@ -365,6 +393,8 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\parinterval 可以说循环神经网络和注意力机制构成了当时神经机器翻译的标准框架。比较有代表性的工作是谷歌公司于2016年上线的谷歌神经机器翻译系统(GNMT),它是由多层循环神经网络(长短时记忆模型)以及注意力机制搭建,且在当时来看性能很强劲的翻译模型\cite{Wu2016GooglesNM}。这项工作也引起了广泛的关注(图\ref{fig:6-8}),甚至可以被看作是神经机器翻译进入飞速发展时期的一个重要的标志。在GNMT推出后,很多企业也推出了基于循环神经网络的神经机器翻译系统,出现了百花齐放的局面。
\parinterval 本章将会从基于循环神经网络的翻译模型和注意力机制入手,介绍神经机器翻译的基本方法。同时也会以GNMT系统为例,对神经机器翻译的其他相关技术进行讨论。
%----------------------------------------------
\begin{figure}[htp]
\centering
......@@ -374,14 +404,13 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\end{figure}
%----------------------------------------------
\parinterval 本章将会从基于循环神经网络的翻译模型和注意力机制入手,介绍神经机器翻译的基本方法。同时也会以GNMT系统为例,对神经机器翻译的其他相关技术进行讨论。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
%----------------------------------------------------------------------------------------
%\vspace{-0.5em}
\subsection{建模}
\label{sec:6.3.1}
\vspace{0.5em}
\parinterval 同大多数自然语言处理任务一样,神经机器翻译要解决的一个基本问题是如何描述文字序列,称为序列表示问题。例如,处理语音数据、文本数据都可以被看作是典型的序列表示问题。如果把一个序列看作一个时序上的一系列变量,不同时刻的变量之间往往是存在相关性的。也就是说,一个时序中某个时刻变量的状态会依赖其他时刻变量的状态,即上下文的语境信息。下面是一个简单的例子,假设有一个句子,但是最后两个单词被擦掉了,如何猜测被擦掉的单词是什么?
......@@ -393,7 +422,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\parinterval 第五章已经对循环神经网络的基本知识进行过介绍。这里再回顾一下。简单来说,循环神经网络由循环单元组成。对于序列中的任意时刻,都有一个循环单元与之对应,它会融合当前时刻的输入和上一时刻循环单元的输出,生成当前时刻的输出。这样每个时刻的信息都会被传递到下一时刻,这也间接达到了记录历史信息的目的。比如,对于序列$\mathbf{x}=\{x_1, x_2,..., x_m\}$,循环神经网络会按顺序输出一个序列$\mathbf{h}=\{ \mathbf{h}_1, \mathbf{h}_2,..., \mathbf{h}_m \}$,其中$\mathbf{h}_i$表示$i$时刻循环神经网络的输出(通常为一个向量)。
\parinterval\ref{fig:6-9}展示了一个循环神经网络处理序列问题的实例。当前时刻循环单元的输入由上一个时刻的输入和当前时刻的输入组成,因此也可以理解为,网络当前时刻计算得到的输出是由之前的序列共同决定的,即网络在不断传递信息的过程中记忆了历史信息。以最后一个时刻的循环单元为例,它在对``开始''这个单词的信息进行处理时,参考了之前所有词(``<eos>\ \ 我们'')的信息。
\parinterval\ref{fig:6-9}展示了一个循环神经网络处理序列问题的实例。当前时刻循环单元的输入由上一个时刻的输入和当前时刻的输入组成,因此也可以理解为,网络当前时刻计算得到的输出是由之前的序列共同决定的,即网络在不断传递信息的过程中记忆了历史信息。以最后一个时刻的循环单元为例,它在对``开始''这个单词的信息进行处理时,参考了之前所有词(``<eos>\ \ 我们'')的信息。
%----------------------------------------------
\begin{figure}[htp]
......@@ -404,7 +433,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\end{figure}
%----------------------------------------------
\parinterval 在神经机器翻译里使用循环神经网络也很简单。我们只需要把源语言句子和目标语言句子分别看作两个序列,之后使用两个循环神经网络分别对其进行建模。这个过程如图\ref{fig:6-10}所示。图中,下半部分是编码器,上半部分是解码器。编码器利用循环神经网络对源语言序列逐词进行编码处理,同时利用循环单元的记忆能力,不断累积序列信息,遇到终止符<eos>后便得到了包含源语言句子全部信息的表示结果。解码器利用编码器的输出和起始符<sos>开始逐词的进行解码,即逐词翻译,每得到一个译文单词,便将其作为当前时刻解码端循环单元的输入,这也是一个典型的神经语言模型的序列生成过程。解码器通过循环神经网络不断累积已经得到的译文的信息,并继续生成下一个单词,直到遇到结束符<eos>,便得到了最终完整的译文。
\parinterval 在神经机器翻译里使用循环神经网络也很简单。我们只需要把源语言句子和目标语言句子分别看作两个序列,之后使用两个循环神经网络分别对其进行建模。这个过程如图\ref{fig:6-10}所示。图中,下半部分是编码器,上半部分是解码器。编码器利用循环神经网络对源语言序列逐词进行编码处理,同时利用循环单元的记忆能力,不断累积序列信息,遇到终止符<eos>后便得到了包含源语言句子全部信息的表示结果。解码器利用编码器的输出和起始符<sos>开始逐词的进行解码,即逐词翻译,每得到一个译文单词,便将其作为当前时刻解码端循环单元的输入,这也是一个典型的神经语言模型的序列生成过程。解码器通过循环神经网络不断累积已经得到的译文的信息,并继续生成下一个单词,直到遇到结束符<eos>,便得到了最终完整的译文。
%----------------------------------------------
\begin{figure}[htp]
......@@ -427,6 +456,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\label{eq:6-2}
\end{eqnarray}
\vspace{-0.5em}
\noindent 其中,$ \mathbf{y}_{<j }$表示目标语第$j$个位置之前已经生成的译文单词序列。$\textrm{P} ( y_j | \mathbf{y}_{<j }, \mathbf{x})$可以被解释为:根据源语句子$\mathbf{x} $和已生成的目标语言译文片段$\mathbf{y}_{<j }=\{ y_1, y_2,..., y_{j-1} \}$,生成第$j$个目标语言单词$y_j$的概率。举个简单的例子,已知源文为$\mathbf{x} =$\{\textrm{``我'', ``很好''}\},则译文$\mathbf{y}=$\{``I’m'', ``fine''\}的概率为:
\begin{eqnarray}
\textrm{P} ( \{{\textrm{``I'm'',``fine''}}\}|\{\textrm{``我'', ``很好''}\}) & = & \textrm{P} (\textrm{``I'm''}| \{\textrm{``我'', ``很好''}\} ) \cdot \nonumber \\
......@@ -436,6 +466,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\parinterval 求解$\textrm{P}(y_j | \mathbf{y}_{<j},\mathbf{x})$有三个关键问题(图\ref{fig:6-11}):
\vspace{-0.5em}
\begin{itemize}
\vspace{0.5em}
\item 如何对$\mathbf{x}$$\mathbf{y}_{<j }$进行分布式表示,即{\small\sffamily\bfseries{词嵌入}}\index{词嵌入}(Word Embedding)\index{Word Embedding}。首先,将由one-hot向量表示的源语言单词,即由0和1构成的离散化向量表示,转化为实数向量。可以把这个过程记为$\textrm{e}_x (\cdot)$。类似的,可以把目标语序列$\mathbf{y}_{<j }$中的每个单词用同样的方式进行表示,记为$\textrm{e}_y (\cdot)$
......@@ -634,7 +665,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\mathbf{c}_t = \mathbf{f}_t \cdot \mathbf{c}_{t-1} + \mathbf{i}_t \cdot \hat{\mathbf{c}_t}
\label{eq:6-15}
\end{eqnarray}
\vspace{0.5em}
\vspace{-1.0em}
\item {\small\sffamily\bfseries{输出}}\index{输出}。该部分使用输出门计算最终的输出信息$\mathbf{h}_t$,其结构如图\ref{fig:6-15}(d)红色线部分所示。在输出门中,首先将$\mathbf{x}_t$$\mathbf{h}_{t-1}$通过$\sigma$函数变换得到$\mathbf{o}_t$。其次,将上一步得到的新记忆信息$\mathbf{c}_t$通过Tanh函数进行变换,得到值在[-1,1]范围的向量。最后将这两部分进行点乘,具体公式如下:
\begin{eqnarray}
\mathbf{o}_t & = & \sigma (\mathbf{W}_o [\mathbf{h}_{t-1},\mathbf{x}_{t}] + \mathbf{b}_o ) \label{eq:6-16} \\
......@@ -643,6 +674,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\vspace{0.5em}
\end{itemize}
\vspace{-2em}
%----------------------------------------------
\begin{figure}[htp]
\centering
......@@ -662,6 +694,17 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\parinterval LSTM 通过门控单元控制传递状态,忘记不重要的信息,记住必要的历史信息,在长序列上取得了很好的效果,但是其进行了许多门信号的计算,较为繁琐。{\small\bfnew{门循环单元}}\index{门循环单元}(Gated Recurrent Unit,GRU)\index{Gated Recurrent Unit,GRU}作为一个LSTM的变种,它继承了LSTM中利用门控单元控制信息传递的思想,并对LSTM进行了简化\cite{Cho2014Learning}。它把循环单元状态$\mathbf{h}_t$和记忆$\mathbf{c}_t$合并成一个状态$\mathbf{h}_t$,同时使用了更少的门控单元,大大提升了计算效率。
%----------------------------------------------
\begin{figure}[htp]
\centering
\subfigure[重置门]{\input{./Chapter6/Figures/figure-GRU01}}
\subfigure[更新门]{\input{./Chapter6/Figures/figure-GRU02}}
\subfigure[隐藏状态更新]{\input{./Chapter6/Figures/figure-GRU03}}
\caption{GRU中的门控结构}
\label{fig:6-17}
\end{figure}
%----------------------------------------------
\parinterval GRU的输入和RNN是一样的,由输入$\mathbf{x}_t$$t-1$时刻的状态$\mathbf{h}_{t-1}$组成。GRU只有两个门信号,分别是重置门和更新门。重置门$\mathbf{r}_t$用来控制前一时刻隐藏状态的记忆程度,其结构如图\ref{fig:6-17}(a)。更新门用来更新记忆,使用一个门同时完成遗忘和记忆两种操作,其结构如图\ref{fig:6-17}(b)。重置门和更新门的计算公式如下:
\begin{eqnarray}
\mathbf{r}_t & = &\sigma (\mathbf{W}_r [\mathbf{h}_{t-1},\mathbf{x}_{t}] ) \label{eq:6-18} \\
......@@ -682,17 +725,6 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\noindent 这里,$\mathbf{u}_t$是更新门中得到的权重,将$\mathbf{u}_t$作用于$\hat{\mathbf{h}}_t$表示对当前时刻的状态进行``遗忘'',舍弃一些不重要的信息,将$(1-\mathbf{u}_t)$作用于$\mathbf{h}_{t-1}$,用于对上一时刻隐藏状态进行选择性记忆。
%----------------------------------------------
\begin{figure}[htp]
\centering
\subfigure[重置门]{\input{./Chapter6/Figures/figure-GRU01}}
\subfigure[更新门]{\input{./Chapter6/Figures/figure-GRU02}}
\subfigure[隐藏状态更新]{\input{./Chapter6/Figures/figure-GRU03}}
\caption{GRU中的门控结构}
\label{fig:6-17}
\end{figure}
%----------------------------------------------
\parinterval GRU的输入输出和RNN类似,其采用与LSTM类似的门控思想,达到捕获长距离依赖信息的目的。此外,GRU比LSTM少了一个门结构,而且参数只有$\mathbf{W}_r$$\mathbf{W}_u$$\mathbf{W}_h$。因此,GRU具有比LSTM高的运算效率,在系统研发中也经常被使用。
%----------------------------------------------------------------------------------------
......@@ -748,7 +780,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\noindent 之所以能想到在横线处填``吃饭''、``吃东西''很有可能是因为看到了``没\ 吃饭''、 ``很\ 饿''等关键信息。也就是这些关键的片段对预测缺失的单词起着关键性作用。而预测``吃饭''与前文中的`` 中午''、``又''之间的联系似乎不那么紧密。也就是说,在形成 ``吃饭''的逻辑时,在潜意识里会更注意``没吃饭''、``很饿''等关键信息。也就是我们的关注度并不是均匀地分布在整个句子上的。
\parinterval 这个现象可以用注意力机制进行解释。注意力机制的概念来源于生物学的一些现象:当待接收的信息过多时,人类会选择性地关注部分信息而忽略其他信息。它在人类的视觉、听觉、嗅觉等方面均有体现,当我们在感受事物时,大脑会自动过滤或衰减部分信息,仅关注其中少数几个部分。例如,当我们看到图\ref{fig:6-20}时,往往不是``均匀地''看图像中的所有区域,可能最先注意到的是大狗头上的帽子,然后才会关注图片中其他的部分。
\parinterval 这个现象可以用注意力机制进行解释。注意力机制的概念来源于生物学的一些现象:当待接收的信息过多时,人类会选择性地关注部分信息而忽略其他信息。它在人类的视觉、听觉、嗅觉等方面均有体现,当我们在感受事物时,大脑会自动过滤或衰减部分信息,仅关注其中少数几个部分。例如,当我们看到图\ref{fig:6-20}时,往往不是``均匀地''看图像中的所有区域,可能最先注意到的是大狗头上的帽子,然后才会关注图片中其他的部分。
\parinterval 那么注意力机制和神经机器翻译又有什么关系呢?它如何解决神经机器翻译的问题呢?下面就一起来看一看。
......@@ -788,9 +820,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\end{figure}
%----------------------------------------------
\parinterval 显然,以上问题的根本原因在于所使用的表示模型还比较``弱''。因此需要一个更强大的表示模型,在生成目标语单词时能够有选择的获取源语言句子中更有用的部分。更准确的说,对于要生成的目标语单词,相关性更高的源语言片段应该在源语言句子的表示中体现出来,而不是将所有的源语言单词一视同仁。在神经机器翻译中引入注意力机制正是为了达到这个目的\cite{bahdanau2014neural,DBLP:journals/corr/LuongPM15}。实际上,除了机器翻译,注意力机制也被成功地应用于图像处理、语音识别、自然语言处理的其他任务。而正是注意力机制的引入,使得包括机器翻译在内很多自然语言处理系统得到了新的飞跃。
\parinterval 神经机器翻译中的注意力机制并不复杂。对于每个目标语单词$y_j$,系统生成一个源语言表示向量$\mathbf{C}_j$与之对应,$\mathbf{C}_j$会包含生成$y_j$所需的源语言的信息,或者说$\mathbf{C}_j$是一种包含目标语言单词与源语言单词对应关系的源语言表示。相比用一个静态的表示$\mathbf{C}$,注意机制使用的是动态的表示$\mathbf{C}_j$$\mathbf{C}_j$也被称作对于目标语位置$j$的上下文向量。图\ref{fig:6-22}对比了未引入注意力机制和引入了注意力机制的编码器-解码器结构。可以看出,在注意力模型中,对于每一个目标单词的生成,都会额外引入一个单独的上下文向量参与运算。
\parinterval 显然,以上问题的根本原因在于所使用的表示模型还比较``弱''。因此需要一个更强大的表示模型,在生成目标语单词时能够有选择地获取源语言句子中更有用的部分。更准确的说,对于要生成的目标语单词,相关性更高的源语言片段应该在源语言句子的表示中体现出来,而不是将所有的源语言单词一视同仁。在神经机器翻译中引入注意力机制正是为了达到这个目的\cite{bahdanau2014neural,DBLP:journals/corr/LuongPM15}。实际上,除了机器翻译,注意力机制也被成功地应用于图像处理、语音识别、自然语言处理等其他任务。而正是注意力机制的引入,使得包括机器翻译在内很多自然语言处理系统得到了飞跃发展。
%----------------------------------------------
\begin{figure}[htp]
......@@ -801,6 +831,8 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\end{figure}
%----------------------------------------------
\parinterval 神经机器翻译中的注意力机制并不复杂。对于每个目标语单词$y_j$,系统生成一个源语言表示向量$\mathbf{C}_j$与之对应,$\mathbf{C}_j$会包含生成$y_j$所需的源语言的信息,或者说$\mathbf{C}_j$是一种包含目标语言单词与源语言单词对应关系的源语言表示。相比用一个静态的表示$\mathbf{C}$,注意机制使用的是动态的表示$\mathbf{C}_j$$\mathbf{C}_j$也被称作对于目标语位置$j$的上下文向量。图\ref{fig:6-22}对比了未引入注意力机制和引入了注意力机制的编码器-解码器结构。可以看出,在注意力模型中,对于每一个目标单词的生成,都会额外引入一个单独的上下文向量参与运算。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
......@@ -826,7 +858,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\end{figure}
%----------------------------------------------
\parinterval 如图5所示,注意力权重$\alpha_{i,j}$的计算分为两步:
\parinterval 如图\ref{fig:6-23}所示,注意力权重$\alpha_{i,j}$的计算分为两步:
\begin{itemize}
\vspace{0.5em}
......@@ -887,7 +919,7 @@ a (\mathbf{s},\mathbf{h}) = \left\{ \begin{array}{ll}
\label{eq:6-26}
\end{eqnarray}
\parinterval 这样,可以在生成每个$y_j$时动态的使用不同的源语言表示$\mathbf{C}_j$,并更准确捕捉源语言和目标语言不同位置之间的相关性。表\ref{tab:6-7}展示了引入注意力机制前后译文单词生成公式的对比。
\parinterval 这样,可以在生成每个$y_j$时动态的使用不同的源语言表示$\mathbf{C}_j$,并更准确捕捉源语言和目标语言不同位置之间的相关性。表\ref{tab:6-7}展示了引入注意力机制前后译文单词生成公式的对比。
%----------------------------------------------
\begin{table}[htp]
......@@ -1013,13 +1045,13 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\vspace{0.5em}
\end{eqnarray}
其中$U(a,b)$表示以$[a,b]$为范围的均匀分布。
其中$U(a,b)$表示以$[a,b]$为范围的均匀分布$6$是固定值
\end{itemize}
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\vspace{-0.5em}
\subsubsection{优化策略}
\parinterval 公式\ref{eq:6-30}展示了最基本的优化策略,也被称为标准的SGD优化器。实际上,训练神经机器翻译模型时,还有非常多的优化器可以选择,在第五章也有详细介绍,这里考虑Adam优化器。 Adam 通过对梯度的{\small\bfnew{一阶矩估计}}\index{一阶矩估计}(First Moment Estimation)\index{First Moment Estimation}{\small\bfnew{二阶矩估计}}\index{二阶矩估计}(Second Moment Estimation)\index{Second Moment Estimation}进行综合考虑,计算出更新步长。
......@@ -1043,6 +1075,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\vspace{-1.5em}
\subsubsection{梯度裁剪}
\parinterval 需要注意的是,训练循环神经网络时,反向传播使得网络层之间的梯度重复相乘,在网络层数过深时,如果连乘因子小于1可能造成梯度指数级的减少,甚至趋近于0,导致网络无法优化,也就是梯度消失问题。当连乘因子大于1时,可能会导致梯度的乘积变得异常大,造成梯度爆炸的问题。在这种情况下需要使用``梯度裁剪''来防止梯度超过阈值。梯度裁剪在第五章已经介绍过,这里简单回顾一下。梯度裁剪的具体公式如下:
......@@ -1093,11 +1126,12 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
\vspace{0.5em}
\subsubsection{并行训练}
\parinterval 机器翻译是自然语言处理中很``重''的任务。因为数据量巨大而且模型较为复杂,模型训练的时间往往很长。比如,使用一千万句的训练数据,性能优异的系统往往需要几天甚至一周的时间。更大规模的数据会导致训练时间更长。特别是使用多层网络同时增加模型容量时(比如增加隐层宽度时),神经机器翻译的训练会更加缓慢。对于这个问题,一个思路是从模型训练算法上进行改进。比如前面提到的Adam就是一种高效的训练策略。另一种思路是利用多设备进行加速,也称作分布式训练。
\vspace{0.5em}
%----------------------------------------------
\begin{table}[htp]
\centering
......@@ -1137,17 +1171,27 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\begin{tabular}{l l}
\subfigure[]{\input{./Chapter6/Figures/figure-process01}} &\subfigure[]{\input{./Chapter6/Figures/figure-process02}} \\
\subfigure[]{\input{./Chapter6/Figures/figure-process03}} &\subfigure[]{\input{./Chapter6/Figures/figure-process04}} \\
\subfigure[]{\input{./Chapter6/Figures/figure-process05}} &\subfigure[]{\input{./Chapter6/Figures/figure-process06}}\\
%\subfigure[]{\input{./Chapter6/Figures/figure-process05}} &\subfigure[]{\input{./Chapter6/Figures/figure-process06}}\\
\end{tabular}
%\caption{一个三层循环神经网络的模型并行过程}
%\label{fig:6-31}
\end{figure}
%----------------------------------------------
%-------------------------------------------
\begin{figure}[htp]
\centering
\begin{tabular}{l l}
%\subfigure[]{\input{./Chapter6/Figures/figure-process01}} &\subfigure[]{\input{./Chapter6/Figures/figure-process02}} \\
%\subfigure[]{\input{./Chapter6/Figures/figure-process03}} &\subfigure[]{\input{./Chapter6/Figures/figure-process04}} \\
\subfigure[]{\input{./Chapter6/Figures/figure-process05}} &\subfigure[]{\input{./Chapter6/Figures/figure-process06}}
\end{tabular}
\caption{一个三层循环神经网络的模型并行过程}
\label{fig:6-31}
\end{figure}
%----------------------------------------------
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
%----------------------------------------------------------------------------------------
\subsection{推断}
\parinterval 神经机器翻译的推断是指:利用已经训练好的模型对新的源语言句子进行翻译的过程。具体来说,首先利用编码器生成源语言句子的表示,之后利用解码器预测目标语译文。也就是,对于源语言句子$\mathbf{x}$,生成一个使翻译概率$\textrm{P}(\mathbf{y} | \mathbf{x})$最大的目标语译文$\hat{\mathbf{y}}$,如下(详细过程见\ref{sec:6.3.1}节):
......@@ -1180,7 +1224,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\subsubsection{贪婪搜索}
\parinterval\ref{fig:6-32}展示了一个基于贪婪方法的神经机器翻译解码过程。每一个时间步的单词预测都依赖于其前一步单词的生成。在解码第一个单词时,由于没有之前的单词信息,会用<eos>进行填充,作为起始的单词,且会用一个零向量(可以理解为没有之前时间步的信息)表示第0步的中间层状态。
\parinterval\ref{fig:6-32}展示了一个基于贪婪方法的神经机器翻译解码过程。每一个时间步的单词预测都依赖于其前一步单词的生成。在解码第一个单词时,由于没有之前的单词信息,会用<sos>进行填充,作为起始的单词,且会用一个零向量(可以理解为没有之前时间步的信息)表示第0步的中间层状态。
%----------------------------------------------
\begin{figure}[htp]
......@@ -1193,6 +1237,8 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\parinterval 解码端的每一步Softmax层会输出所有单词的概率,由于是基于贪心的方法,这里会选择概率最大(top-1)的单词作为输出。这个过程可以参考图\ref{fig:6-33}的内容。我们选择分布中概率最大的单词``Have''作为得到的第一个单词,并再次送入解码器,作为第二步的输入同时预测下一个单词。以此类推,直到生成句子的终止符为止,就得到了完整的译文。
\parinterval 贪婪搜索的优点在于速度快。在对翻译速度有较高要求的场景中,贪婪搜索是一种十分有效的对系统加速的方法。而且贪婪搜索的原理非常简单,易于快速原型。不过,由于每一步只保留一个最好的局部结果,贪婪搜索往往会带来翻译品质上的损失。
%----------------------------------------------
\begin{figure}[htp]
\centering
......@@ -1202,8 +1248,6 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{figure}
%----------------------------------------------
\parinterval 贪婪搜索的优点在于速度快。在对翻译速度有较高要求的场景中,贪婪搜索是一种十分有效的对系统加速的方法。而且贪婪搜索的原理非常简单,易于快速原型。不过,由于每一步只保留一个最好的局部结果,贪婪搜索往往会带来翻译品质上的损失。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
%----------------------------------------------------------------------------------------
......@@ -1412,6 +1456,14 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
%----------------------------------------------------------------------------------------
\subsection{Transformer架构}
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter6/Figures/figure-transformer}
\caption{ Transformer结构}
\label{fig:6-39}
\end{figure}
%----------------------------------------------
\parinterval\ref{fig:6-39}展示了经典的Transformer结构。解码器由若干层组成(绿色虚线框就代表一层)。每一层(layer)的输入都是一个向量序列,输出是同样大小的向量序列,而Transformer层的作用是对输入进行进一步的抽象,得到新的表示结果。不过这里的层并不是指单一的神经网络结构,它里面由若干不同的模块组成,包括:
......@@ -1427,15 +1479,6 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\vspace{0.5em}
\end{itemize}
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter6/Figures/figure-transformer}
\caption{ Transformer结构}
\label{fig:6-39}
\end{figure}
%----------------------------------------------
\parinterval 以上操作就构成了Transformer的一层,各个模块执行的顺序可以简单描述为:Self-Attention $\to$ Residual Connection $\to$ Layer Normalization $\to$ Feed Forward Network $\to$ Residual Connection $\to$ Layer Normalization。编码器可以包含多个这样的层,比如,可以构建一个六层编码器,每层都执行上面的操作。最上层的结果作为整个编码的结果,会被传入解码器。
\parinterval 解码器的结构与编码器十分类似。它也是由若干层组成,每一层包含编码器中的所有结构,即:自注意力子层、前馈神经网络子层、残差连接和层正则化模块。此外,为了捕捉源语言的信息,解码器又引入了一个额外的{\small\sffamily\bfseries{编码-解码注意力子层}}\index{编码-解码注意力子层}(Encoder-decoder Attention Sub-layer)\index{Encoder-decoder Attention Sub-layer}。这个新的子层,可以帮助模型使用源语言句子的表示信息生成目标语不同位置的表示。编码-解码注意力子层仍然基于自注意力机制,因此它和自注意力子层的结构是相同的,只是$\mathrm{query}$$\mathrm{key}$$\mathrm{value}$的定义不同。比如,在解码端,自注意力子层的$\mathrm{query}$$\mathrm{key}$$\mathrm{value}$是相同的,它们都等于解码端每个位置的表示。而在编码-解码注意力子层中,$\mathrm{query}$是解码端每个位置的表示,此时$\mathrm{key}$$\mathrm{value}$是相同的,等于编码端每个位置的表示。图\ref{fig:6-40}给出了这两种不同注意力子层输入的区别。
......@@ -1449,7 +1492,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{figure}
%----------------------------------------------
\parinterval 此外,编码端和解码端都有输入的词序列。编码端的词序列输入是为了对其进行表示,进而解码端能从编码端访问到源语言句子的全部信息。解码端的词序列输入是为了进行目标语的生成,本质上它和语言模型是一样的,在得到前$n-1$个单词的情况下输出第$n$个单词。除了输入的词序列的词嵌入,Transformer中也引入了位置嵌入,以表示每个位置信息。原因是,自注意力机制没有显性地对位置进行表示,因此也无法考虑词序。在输入中引入位置信息可以让自注意力机制间接感受到每个词的位置,进而保证对序列表示的合理性。最终,整个模型的输出由一个Softmax层完成,它和循环神经网络中的输出层是完全一样的(\ref{sec:6.3.2}节)。
\parinterval 此外,编码端和解码端都有输入的词序列。编码端的词序列输入是为了对其进行表示,进而解码端能从编码端访问到源语言句子的全部信息。解码端的词序列输入是为了进行目标语的生成,本质上它和语言模型是一样的,在得到前$n-1$个单词的情况下输出第$n$个单词。除了输入的词序列的词嵌入,Transformer中也引入了位置嵌入,以表示每个位置信息。原因是,自注意力机制没有显性地对位置进行表示,因此也无法考虑词序。在输入中引入位置信息可以让自注意力机制间接感受到每个词的位置,进而保证对序列表示的合理性。最终,整个模型的输出由一个Softmax层完成,它和循环神经网络中的输出层是完全一样的(\ref{sec:6.3.2}节)。
\parinterval 在进行更详细的介绍前,先利用图\ref{fig:6-39}简单了解一下Transformer模型是如何进行翻译的。首先,Transformer将源语``我\ \ 好''的{\small\bfnew{词嵌入}}\index{词嵌入}(Word Embedding)\index{Word Embedding}融合{\small\bfnew{位置编码}}\index{位置编码}(Position Embedding)\index{Position Embedding}后作为输入。然后,编码器对输入的源语言句子进行逐层抽象,得到包含丰富的上下文信息的源语表示并传递给解码器。解码器的每一层,使用自注意力子层对输入解码端的表示进行加工,之后再使用编码-解码注意力子层融合源语言句子的表示信息。就这样逐词生成目标语译文单词序列。解码器的每个位置的输入是当前单词(比如,``I''),而这个位置输出是下一个单词(比如,``am''),这个设计和标准的神经语言模型是完全一样的。
......@@ -1520,7 +1563,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\label{eq:6-46}
\end{eqnarray}
\noindent 即对于任意固定的偏移量$k$$\textrm{PE}(pos+k)$能被表示成$\textrm{PE}(pos)$的线性函数,换句话说,位置编码可以表示词之间的距离。在实践中发现,位置编码对Transformer系统的性能有很大影响。对其进行改进也会带来性能的进一步提升\cite{Shaw2018SelfAttentionWR}
\noindent 即对于任意固定的偏移量$k$$\textrm{PE}(pos+k)$能被表示成$\textrm{PE}(pos)$的线性函数,换句话说,位置编码可以表示词之间的距离。在实践中发现,位置编码对Transformer系统的性能有很大影响。对其进行改进也会带来进一步的性能提升\cite{Shaw2018SelfAttentionWR}
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
......@@ -1858,7 +1901,6 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^{6}$
%----------------------------------------------------------------------------------------
\subsection{自动文摘}
\parinterval 自动文本摘要,即在不改变文本原意的情况下,自动生成文本的主要内容。自动文本摘要技术被广泛应用于新闻报道、信息检索等领域。文本自动摘要是根据输入的文档得到摘要,因此可以把原始文档看作输入序列,把得到的摘要看作输出序列。常见的解决思路有:抽取式文摘和生成式文摘。前者试图从输入的文本中抽取能表达原文主要内容的句子,进行重新组合、提炼;后者则试图让计算机``理解''并``表达''出原文的主要内容。生成式文摘也可以用端到端框架实现。比如,可以利用编码器将整个输入序列编码成一个具有输入序列信息的固定维度向量,然后利用解码器对这个向量解码,获取所需要文本摘要\cite{DBLP:journals/corr/RushCW15}。图\ref{fig:6-57}展示了一个文本自动摘要的例子\cite{DBLP:journals/corr/PaulusXS17}
%----------------------------------------------
......@@ -1870,6 +1912,7 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^{6}$
\end{figure}
%----------------------------------------------
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
%----------------------------------------------------------------------------------------
......
......@@ -100,10 +100,10 @@
\draw[-latex,emph] (aux71) -| (aux53) -- (aux23) -| (aux46) -- (z76);
\draw[emph] (aux12) |- (aux23) -| (aux46);
\node[opnode,rectangle,rounded corners=2pt,inner sep=2pt,draw=red,thick] (tanh) at (aux46) {$\mathrm{tanh}$};
\node[opnode,circle,draw=red,thick] () at (aux53) {X};
\node[opnode,circle,draw=red,thick] () at (aux56) {X};
\node[opnode,circle,draw=red,thick] () at (aux75) {X};
\node[opnode,circle,draw=red,thick] () at (aux76) {\textbf{+}};
\node[opnode,circle,draw=red,thick] (a1) at (aux53) {};
\node[opnode,circle,draw=red,thick] (a2) at (aux56) {};
\node[opnode,circle,draw=red,thick] (a3) at (aux75) {};
\node[opnode,circle,draw=red,thick] (a4) at (aux76) {};
}
\end{scope}
......@@ -120,6 +120,16 @@
\begin{pgfonlayer}{background}
\node[draw,very thick,rectangle,fill=blue!10!white,rounded corners=5pt,inner sep=6pt,fit=(aux22) (aux76) (z76) (tanh)] (GRU) {};
\end{pgfonlayer}
%%new
\draw[-] (a1.north west) -- (a1.south east);
\draw[-] (a1.north east) -- (a1.south west);
\draw[-] (a2.north west) -- (a2.south east);
\draw[-] (a2.north east) -- (a2.south west);
\draw[-] (a3.north west) -- (a3.south east);
\draw[-] (a3.north east) -- (a3.south west);
\draw [-,line width=0.8pt] (a4.north) -- (a4.south);
\draw [-,line width=0.8pt] (a4.west) -- (a4.east);
\end{tikzpicture}
\ No newline at end of file
......@@ -94,7 +94,7 @@
\draw[emph] (aux12) -- (aux22) -- (aux23);
\node[opnode,circle,draw=red,thick] () at (aux34) {$\sigma$};
\node[opnode,rectangle,rounded corners=2pt,inner sep=2pt,draw=red,thick] () at (aux35) {$\mathrm{tanh}$};
\node[opnode,circle,draw=red,thick] (i45) at (aux45) {X};
\node[opnode,circle,draw=red,thick] (i45) at (aux45) {};
}
\end{scope}
......@@ -111,5 +111,8 @@
\node[draw,very thick,rectangle,fill=blue!10!white,rounded corners=5pt,inner sep=4pt,fit=(aux22) (aux58) (u55) (o27)] (LSTM) {};
\end{pgfonlayer}
%%new
\draw[-] (i45.north west) -- (i45.south east);
\draw[-] (i45.north east) -- (i45.south west);
\end{tikzpicture}
\ No newline at end of file
......@@ -101,13 +101,13 @@
\draw[-latex,standard] (aux21) -- (aux25) -- (u55);
\node[opnode,circle] () at (aux34) {$\sigma$};
\node[opnode,rectangle,rounded corners=2pt,inner sep=2pt] () at (aux35) {$\mathrm{tanh}$};
\node[opnode,circle] (i45) at (aux45) {X};
\node[opnode,circle] (i45) at (aux45) {};
}
% cell update
{
\draw[-latex,emph] (aux51) -- (aux59);
\node[opnode,circle,draw=red,thick] (f53) at (aux53) {X};
\node[opnode,circle,draw=red,thick] (u55) at (aux55) {\textbf{+}};
\node[opnode,circle,draw=red,thick] (f53) at (aux53) {};
\node[opnode,circle,draw=red,thick] (u55) at (aux55) {};
}
\end{scope}
......@@ -127,6 +127,13 @@
\begin{pgfonlayer}{background}
\node[draw,very thick,rectangle,fill=blue!10!white,rounded corners=5pt,inner sep=4pt,fit=(aux22) (aux58) (u55) (o27)] (LSTM) {};
\end{pgfonlayer}
%%new
\draw[-] (i45.north west) -- (i45.south east);
\draw[-] (i45.north east) -- (i45.south west);
\draw[-] (f53.north west) -- (f53.south east);
\draw[-] (f53.north east) -- (f53.south west);
\draw [-,line width=0.8pt] (u55.north) -- (u55.south);
\draw [-,line width=0.8pt] (u55.west) -- (u55.east);
\end{tikzpicture}
\ No newline at end of file
......@@ -102,7 +102,7 @@
\draw[-latex,standard] (aux21) -- (aux25) -- (u55);
\node[opnode,circle] () at (aux34) {$\sigma$};
\node[opnode,rectangle,rounded corners=2pt,inner sep=2pt] () at (aux35) {$\mathrm{tanh}$};
\node[opnode,circle] (i45) at (aux45) {X};
\node[opnode,circle] (i45) at (aux45) {};
}
% cell update
{
......@@ -112,12 +112,12 @@
}
{
\draw[-latex,standard] (aux51) -- (aux59);
\node[opnode,circle] (f53) at (aux53) {X};
\node[opnode,circle] (u55) at (aux55) {\textbf{+}};
\node[opnode,circle] (f53) at (aux53) {};
\node[opnode,circle] (u55) at (aux55) {};
}
% output gate
{
\node[opnode,circle,draw=red,thick] (o27) at (aux27) {X};
\node[opnode,circle,draw=red,thick] (o27) at (aux27) {};
\draw[-latex,emph] (u55) -| (o27);
\draw[-latex,emph] (aux21) -- (o27);
\draw[emph] (aux12) -- (aux22) -- (aux23);
......@@ -146,6 +146,15 @@
\begin{pgfonlayer}{background}
\node[draw,very thick,rectangle,fill=blue!10!white,rounded corners=5pt,inner sep=4pt,fit=(aux22) (aux58) (u55) (o27)] (LSTM) {};
\end{pgfonlayer}
%%new
\draw[-] (i45.north west) -- (i45.south east);
\draw[-] (i45.north east) -- (i45.south west);
\draw[-] (f53.north west) -- (f53.south east);
\draw[-] (f53.north east) -- (f53.south west);
\draw [-,line width=0.8pt] (u55.north) -- (u55.south);
\draw [-,line width=0.8pt] (u55.west) -- (u55.east);
\draw[-] (o27.north west) -- (o27.south east);
\draw[-] (o27.north east) -- (o27.south west);
\end{tikzpicture}
\ No newline at end of file
......@@ -40,7 +40,7 @@
\node [anchor=west,inner sep=2pt] (o4) at ([xshift=0.3em]o3.east) {\scriptsize{...}};
}
\node [wnode,anchor=north] (wt1) at ([yshift=-0.8em]t1.south) {\scriptsize{$\langle$eos$\rangle$}};
\node [wnode,anchor=north] (wt1) at ([yshift=-0.8em]t1.south) {\scriptsize{$\langle$sos$\rangle$}};
{
\node [wnode,anchor=north] (wt2) at ([yshift=-0.8em]t2.south) {\scriptsize{Have}};
......
......@@ -16,7 +16,7 @@
\node [rnnnode,anchor=south] (s1) at ([yshift=1em]t1.north) {\scriptsize{$\textbf{s}_1$}};
}
\node [wnode,anchor=north] (wt1) at ([yshift=-0.8em]t1.south) {\scriptsize{$\langle$eos$\rangle$}};
\node [wnode,anchor=north] (wt1) at ([yshift=-0.8em]t1.south) {\scriptsize{$\langle$sos$\rangle$}};
{
\node [rnnnode,anchor=south,fill=blue!20] (o1) at ([yshift=1em]s1.north) {\scriptsize{Softmax}};
......
......@@ -56,7 +56,7 @@
\node [anchor=west,inner sep=2pt] (o5) at ([xshift=0.3em]o4.east) {\tiny{...}};
}
{
\node [anchor=north,inner sep=2pt] (wt1) at ([yshift=-0.6em]t1.south) {\tiny{$\langle$eos$\rangle$}};
\node [anchor=north,inner sep=2pt] (wt1) at ([yshift=-0.6em]t1.south) {\tiny{$\langle$sos$\rangle$}};
}
{
\node [anchor=north,inner sep=2pt] (wt2) at ([yshift=-0.6em]t2.south) {\tiny{Have}};
......
\begin{tikzpicture}
%第一段----------------------------------------------
%原文-------------
\node [pos=0.4,left,xshift=-36em,yshift=7.3em,font=\small] (original0) {原文:};
\node [pos=0.4,left,xshift=-2em,yshift=3.3em,font=\small] (original1) {
\begin{tabular}[t]{l}
\parbox{36em}{During Soviet times, if a city’s population topped one million, it would become eligible for its own metro. Planners wanted to brighten the lives of everyday Soviet citizens, and saw the metros, with their tens of thousands of daily passengers, as a singular opportunity to do so. In 1977, Tashkent, the capital of Uzbekistan, became the seventh Soviet city to have a metro built. Grand themes celebrating the history of Uzbekistan and the Soviet Union were brought to life, as art was commissioned and designers set to work. The stations reflected different themes, some with domed ceilings and painted tiles reminiscent of Uzbekistan’s Silk Road mosques, while others ...}
\end{tabular}
};
%译文1--------------mt1
\node[font=\small] (mt1) at ([xshift=0em,yshift=-9.1em]original0.south) {译文1:};
\node[font=\small] (ts1) at ([xshift=0em,yshift=-4em]original1.south) {
\begin{tabular}[t]{l}
\parbox{36em}{在苏联时代,如果一个城市的人口突破一百万,这将成为合资格为自己的地铁。规划者想去照亮每天的苏联公民的生命,看到地铁,与他们的数十每天数千乘客,作为一个独特的机会来这样做。1977年,塔什干,乌兹别克斯坦的首都,成了苏联第七城市建有地铁。宏大主题,庆祝乌兹别克斯坦和苏联的历史被带到生活,因为艺术是委托和设计师开始工作。车站反映了不同的主题,有的圆顶天花板和绘瓷砖让人想起乌兹别克斯坦是丝绸之路的清真寺,而另一些则装饰着...}
\end{tabular}
};
%{
%\draw[dotted,thick,ublue] ([xshift=10.3em,yshift=0.3em]mt8.south west)--%([xshift=-5.2em,yshift=-0.3em]ht8.north);
%}
\begin{pgfonlayer}{background}
{
\node[rectangle,draw=ublue, inner sep=0mm] [fit =(original0)(mt1)(mt1)(ts1)(original1)] {};
}
\end{pgfonlayer}
\end{tikzpicture}
\ No newline at end of file
\begin{tikzpicture}
%-------译文2
\node [pos=0.4,left,xshift=-36em,yshift=7.3em,font=\small] (original0) {译文2:};
\node [pos=0.4,left,xshift=-2em,yshift=4.5em,font=\small] (original1) {
\begin{tabular}[t]{l}
\parbox{36em}{在苏联时期,如果一个城市的人口超过一百万,它就有资格拥有自己的地铁。 规划者想要照亮日常苏联公民的生活,并把拥有数万名每日乘客的地铁看作是这样做的一个绝佳机会。 1977年,乌兹别克斯坦首都塔什干成为苏联第七个修建地铁的城市。 随着艺术的委托和设计师们的工作,乌兹别克斯坦和苏联历史的宏伟主题被赋予了生命力。 这些电台反映了不同的主题,有的有穹顶和彩砖,让人想起乌兹别克斯坦的丝绸之路清真寺,有的则用...}
\end{tabular}
};
\begin{pgfonlayer}{background}
{
\node[rectangle,draw=ublue, inner sep=0mm] [fit =(original0)(original1)] {};
}
\end{pgfonlayer}
\end{tikzpicture}
\ No newline at end of file
......@@ -6,6 +6,7 @@
\setlength{\base}{0.9em}
\tikzstyle{rnnnode} = [rounded corners=1pt,minimum size=1\base,draw,inner sep=0pt,outer sep=0pt,fill=blue!30!white]
\tikzstyle{wordnode} = [font=\footnotesize,align=center]
\tikzstyle{test} = [rounded corners=1pt,minimum size=1\base,inner sep=0pt,outer sep=0pt]
\begin{scope}
% rnn[layer][step]
......@@ -27,7 +28,16 @@
\node[draw=red,thick,inner sep=5pt,rounded corners=0.3em,rotate fit=-45,label={[font=\scriptsize,align=center]90:正在运算的\\{\color{red} 循环单元}},fit=(rnn11)] () {};
}
% 占位
{
\node[test] (z2) at ([xshift=2\base]rnn10) {};
\node[test] (z3) at ([xshift=2\base]z2) {};
\node[test] (z4) at ([xshift=2\base]z3) {};
\node[test] (z5) at ([xshift=2\base]z4) {};
\node[test] (z6) at ([xshift=2\base]z5) {};
\node[test] (z7) at ([xshift=2\base]z6) {};
%\node[test] (z8) at ([xshift=2\base]z7) {};
}
% labels
%\alt<1-4>
......
......@@ -5,6 +5,7 @@
\setlength{\base}{0.9em}
\tikzstyle{rnnnode} = [rounded corners=1pt,minimum size=1\base,draw,inner sep=0pt,outer sep=0pt,fill=blue!30!white]
\tikzstyle{wordnode} = [font=\footnotesize,align=center]
\tikzstyle{test} = [rounded corners=1pt,minimum size=1\base,inner sep=0pt,outer sep=0pt]
\begin{scope}
% rnn[layer][step]
......@@ -38,6 +39,15 @@
\node[draw=red,thick,inner sep=5pt,rounded corners=0.3em,rotate fit=-45,label={[font=\scriptsize,align=center]90:正在运算的\\{\color{red} 循环单元}},fit=(rnn12) (rnn21)] () {};
}
% 占位
{
\node[test] (z2) at ([xshift=2\base]rnn11) {};
\node[test] (z3) at ([xshift=2\base]z2) {};
\node[test] (z4) at ([xshift=2\base]z3) {};
\node[test] (z5) at ([xshift=2\base]z4) {};
\node[test] (z6) at ([xshift=2\base]z5) {};
\node[test] (z7) at ([xshift=2\base]z6) {};
}
% labels
{
......
......@@ -95,7 +95,7 @@
\draw[emph] (aux12) -- (aux22) -- (aux23);
\node[opnode,circle,draw=red,thick] () at (aux34) {$\sigma$};
\node[opnode,rectangle,rounded corners=2pt,inner sep=2pt,draw=red,thick] () at (aux35) {$\mathrm{tanh}$};
\node[opnode,circle,draw=red,thick] (i45) at (aux45) {X};
\node[opnode,circle,draw=red,thick] (i45) at (aux45) {};
}
{
\node[opnode,circle] (i45) at (aux45) {};
......@@ -103,22 +103,22 @@
\draw[-latex,standard] (aux21) -- (aux25) -- (u55);
\node[opnode,circle] () at (aux34) {$\sigma$};
\node[opnode,rectangle,rounded corners=2pt,inner sep=2pt] () at (aux35) {$\mathrm{tanh}$};
\node[opnode,circle] (i45) at (aux45) {X};
\node[opnode,circle] (i45) at (aux45) {};
}
% cell update
{
\draw[-latex,emph] (aux51) -- (aux59);
\node[opnode,circle,draw=red,thick] (f53) at (aux53) {X};
\node[opnode,circle,draw=red,thick] (u55) at (aux55) {\textbf{+}};
\node[opnode,circle,draw=red,thick] (f53) at (aux53) {};
\node[opnode,circle,draw=red,thick] (u55) at (aux55) {};
}
{
\draw[-latex,standard] (aux51) -- (aux59);
\node[opnode,circle] (f53) at (aux53) {X};
\node[opnode,circle] (u55) at (aux55) {\textbf{+}};
\node[opnode,circle] (f53) at (aux53) {};
\node[opnode,circle] (u55) at (aux55) {};
}
% output gate
{
\node[opnode,circle,draw=red,thick] (o27) at (aux27) {X};
\node[opnode,circle,draw=red,thick] (o27) at (aux27) {};
\draw[-latex,emph] (u55) -| (o27);
\draw[-latex,emph] (aux21) -- (o27);
\draw[emph] (aux12) -- (aux22) -- (aux23);
......@@ -129,7 +129,7 @@
\draw[-latex,emph] (o27) -| (aux68);
}
{
\node[opnode,circle] (o27) at (aux27) {X};
\node[opnode,circle] (o27) at (aux27) {};
\draw[-latex,standard] (u55) -| (o27);
\draw[-latex,standard] (aux21) -- (o27);
\node[opnode,circle] () at (aux26) {$\sigma$};
......@@ -157,6 +157,16 @@
\node[draw,very thick,rectangle,fill=blue!10!white,rounded corners=5pt,inner sep=4pt,fit=(aux22) (aux58) (u55) (o27)] (LSTM) {};
\end{pgfonlayer}
%%new
\draw[-] (i45.north west) -- (i45.south east);
\draw[-] (i45.north east) -- (i45.south west);
\draw[-] (f53.north west) -- (f53.south east);
\draw[-] (f53.north east) -- (f53.south west);
\draw [-,line width=0.8pt] (u55.north) -- (u55.south);
\draw [-,line width=0.8pt] (u55.west) -- (u55.east);
\draw[-] (o27.north west) -- (o27.south east);
\draw[-] (o27.north east) -- (o27.south west);
\begin{scope}
{
% forget gate formula
......
......@@ -19,7 +19,7 @@
\parinterval 作为机器翻译的前沿方向,神经机器翻译方法是近些年来最受关注的热点之一。凭借其高品质的译文,神经机器翻译的身影在各种机器翻译比赛和产品中随处可见。第六章已经介绍了神经机器翻译的基础模型,包括:基于循环神经网络的翻译模型、基于Transformer的翻译模型、注意力机制等等。但是,简单使用这些模型和方法显然无法取得最好的结果。实际上,先进的系统往往依赖多种技术的综合运用,是一项庞大的系统工程。
\parinterval 本章将沿着神经机器翻译框架继续探讨:如何研发性能更为突出的机器翻译系统。这里将介绍若干常用的提升神经机器翻译系统品质和速度的方法。同时,也会讨论一些开放性的前沿课题,旨在使机器翻译达到更加先进的水平。本章的绝大部分内容都经过笔者所在团队的实验,具有实践方面的参考价值。正如本章的副标题一样,希望这里所讨论的内容可以帮助读者了解如何开发出一套足以参加高水平机器翻译比赛的系统,为相关研究建立更加科学、合理的基线,同时为机器翻译的应用提供一些具体可落地的思路。
\parinterval 本章将沿着神经机器翻译框架继续探讨:如何研发性能更为突出的机器翻译系统。这里将介绍若干常用的提升神经机器翻译系统品质和速度的方法。同时,也会讨论一些开放性的前沿课题,旨在使机器翻译达到更加先进的水平。本章的绝大部分内容都经过笔者所在团队的实验,具有实践方面的参考价值。正如本章的副标题一样,希望这里所讨论的内容可以帮助读者了解如何开发出一套足以参加高水平机器翻译比赛的系统,为相关研究建立更加科学、合理的基线,同时为机器翻译的应用提供一些具体可落地的思路。
%----------------------------------------------------------------------------------------
......@@ -32,7 +32,7 @@
\begin{itemize}
\vspace{0.5em}
\item {\small\bfnew{神经网络模型很脆弱}}。神经机器翻译对超参数、训练策略的选择、网络结构的细微差别都非常敏感。比如,学习率、Dropout比率上下浮动一点点都会给翻译结果带来明显区别。这也导致系统研发人员需要花费大量的时间来寻找合理的系统配置。虽然也有一些研究工作探讨自动化调参和结构设计(如:AutoML),但是为了确保翻译品质,现在普遍的做法仍然是``人肉''搜索最佳的网络架构和系统配置。
\item {\small\bfnew{神经网络模型很脆弱}}。神经机器翻译对超参数和训练策略的选择以及网络结构的细微差别都非常敏感。比如,学习率、Dropout比率上下浮动一点点都会给翻译结果带来明显区别。这也导致系统研发人员需要花费大量的时间来寻找合理的系统配置。虽然也有一些研究工作探讨自动化调参和结构设计(如:AutoML),但是为了确保翻译品质,现在普遍的做法仍然是``人肉''搜索最佳的网络架构和系统配置。
\vspace{0.5em}
\item {\small\bfnew{神经机器翻译需要对不同翻译任务进行适应}}。理想中一套``包打天下''的模型和设置是不存在的。针对不同语种、不同领域,机器翻译系统都需要进行调整。比如,一个在新闻数据上训练的系统在专利数据上的表现往往不会很好。这里并不否认在很多研究工作中为了缩短研究周期,可以用同一套系统及设置在所有任务上进行实验。但是,具体到每个翻译任务上,高质量翻译都离不开对系统细致地调整,比如,与语言相关的数据加工等。
\vspace{0.5em}
......@@ -447,7 +447,7 @@ y = f(x)
\label{eq:7-2}
\end{eqnarray}
\noindent 其中,$L(\mathbf{w})$是损失函数,$R(\mathbf{w})$是正则项$\lambda$是正则项的系数,用于控制正则化对训练影响的程度。$R(\mathbf{w})$通常也可以被看作是一种先验,因为在数据不充分且存在噪声的情况下,可以根据一些先验知识让模型偏向正确的方向一些,而不是一味地根据受噪声影响的不准确的$L(\mathbf{w})$进行优化。相应的,引入正则化后的模型可以获得更好的{\small\bfnew{泛化}}\index{泛化}(Generalization)\index{Generalization}能力,即模型在新的未见数据上表现会更好。
\noindent 其中,$L(\mathbf{w})$是损失函数,$R(\mathbf{w})$是正则项$\lambda$是正则项的系数,用于控制正则化对训练影响的程度。$R(\mathbf{w})$通常也可以被看作是一种先验,因为在数据不充分且存在噪声的情况下,可以根据一些先验知识让模型偏向正确的方向一些,而不是一味地根据受噪声影响的不准确的$L(\mathbf{w})$进行优化。相应的,引入正则化后的模型可以获得更好的{\small\bfnew{泛化}}\index{泛化}(Generalization)\index{Generalization}能力,即模型在新的未见数据上表现会更好。
\parinterval 实践中已经证明,正则化方法有助于像神经机器翻译这样复杂的模型获得稳定的模型参数。甚至有些情况下,如果不引入正则化,训练得到的翻译模型根本无法使用。
......@@ -572,7 +572,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\parinterval 那么是否还有类似的方法可以改善系统性能呢?答案显然是肯定的。这里,把这类方法统称为基于大容量模型的方法。在传统机器学习的观点中,神经网络的性能不仅依赖于架构设计,同样与容量密切相关。那么什么是模型的{\small\bfnew{容量}}\index{容量}(Capacity)\index{Capacity}?简单理解,容量是指神经网络的参数量,即神经元之间连接权重的个数。另一种定义是把容量看作神经网络所能表示的假设空间大小\cite{DBLP:journals/nature/LeCunBH15},也就是神经网络能表示的不同函数所构成的空间。
\parinterval 而学习一个神经网络就是要找到一个``最优''的函数,它可以准确地拟合数据。当假设空间变大时,训练系统有机会找到更好的函数,但是同时也需要依赖更多的训练样本才能完成最优函数的搜索。相反,当假设空间变小时,训练系统会更容易完成函数搜索,但是很多优质的函数可能都没有包含在假设空间里。这也体现了一种简单的辩证思想:如果训练(搜索)的代价高,会有更大的机会找到更好的解;另一方面,如果想少花力气进行训练(搜索),那就设计一个小一些的假设空间,在小一些规模的样本集上进行训练,当然搜索到的解可能不是最好的。
\parinterval 而学习一个神经网络就是要找到一个``最优''的函数,它可以准确地拟合数据。当假设空间变大时,训练系统有机会找到更好的函数,但是同时也需要依赖更多的训练样本才能完成最优函数的搜索。相反,当假设空间变小时,训练系统会更容易完成函数搜索,但是很多优质的函数可能都没有包含在假设空间里。这也体现了一种简单的辩证思想:如果训练(搜索)的代价高,会有更大的机会找到更好的解;另一方面,如果想少花力气进行训练(搜索),那就设计一个小一些的假设空间,在小一些规模的样本集上进行训练,当然搜索到的解可能不是最好的。
\parinterval 在很多机器翻译任务中,训练数据是相对充分的。这时增加模型容量是提升性能的一种很好的选择。常见的方法有三种:
......@@ -701,7 +701,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\end{figure}
%----------------------------------------------
\parinterval 此外,前人工作表明,使用大批量训练复杂网络结构时要配合略大一些的学习率,加快模型在梯度方向上的更新速度,进而达到更优的翻译性能\cite{DBLP:conf/wmt/OttEGA18}。例如,深层网络也需要对学习率进行适当的调整才能发挥较好的性能。表\ref{tab:7-3}展示了30层网络在不同批次大小和学习率峰值的条件下的BLEU值(WMT14 En-De)\footnote{学习率峰值是指Transformer模型训练的预热阶段,学习率所到达的最高值。}。可以发现,在固定学习率峰值的条件下增大批次大小并不能带来性能上的增益,必须同时调整学习率的峰值。也有研究团队验证了Transformer-Big模型在128张GPU上进行分布式训练时,适当的增大学习率会带来明显的BLEU提升\cite{DBLP:conf/wmt/OttEGA18}
\parinterval 此外,前人工作表明,使用大批量训练复杂网络结构时要配合略大一些的学习率,加快模型在梯度方向上的更新速度,进而达到更优的翻译性能\cite{DBLP:conf/wmt/OttEGA18}。例如,深层网络也需要对学习率进行适当的调整才能发挥较好的性能。表\ref{tab:7-3}展示了30层网络在不同批次大小和学习率峰值的条件下的BLEU值(WMT14 En-De)\footnote{学习率峰值是指Transformer模型训练的预热阶段,学习率所到达的最高值。}。可以发现,在固定学习率峰值的条件下增大批次大小并不能带来性能上的增益,必须同时调整学习率的峰值。也有研究团队验证了Transformer-Big模型在128张GPU上进行分布式训练时,适当的增大学习率会带来明显的BLEU提升\cite{DBLP:conf/wmt/OttEGA18}
%----------------------------------------------
\begin{table}[htp]
......@@ -914,7 +914,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\parinterval 另一种思路是化简Transformer的解码端神经网络。比如,可以使用平均注意力机制代替原始的Transformer自注意力机制\cite{DBLP:journals/corr/abs-1805-00631},也可以使用运算更轻的卷积操作代替注意力模块\cite{Wu2019PayLA}。前面提到的基于共享注意力机制的模型也是一种典型的轻量模型\cite{Xiao2019SharingAW}
\parinterval 此外,使用异构神经网络也是一种平衡精度和速度的有效方法。在很多研究中发现,基于Transformer的编码器对翻译品质的影响更大,但是解码端的作用会小一些。因此,一种想法是用更快速的解码端结构,比如,用基于循环神经网络的解码端替换基于Transformer的解码端\cite{Chen2018TheBO}。这样,既能发挥Transformer在编码上的优势,同时也能利用循环神经网络在解码端速度上的优势。使用类似的思想,也可以用卷积网络等结构进行解码端网络的设计。
\parinterval 此外,使用异构神经网络也是一种平衡精度和速度的有效方法。在很多研究中发现,基于Transformer的编码器对翻译品质的影响更大,解码端的作用会小一些。因此,一种想法是用更快速的解码端结构,比如,用基于循环神经网络的解码端替换基于Transformer的解码端\cite{Chen2018TheBO}。这样,既能发挥Transformer在编码上的优势,同时也能利用循环神经网络在解码端速度上的优势。使用类似的思想,也可以用卷积网络等结构进行解码端网络的设计。
\vspace{0.5em}
\noindent {\small\bfnew{d) 批量推断}}
......@@ -1476,7 +1476,16 @@ x_{l+1}=\mathcal{F}(\textrm{LN}(x_l))+x_l
x_{l+1}=M \cdot \mathcal{F}(\textrm{LN}(x_l))+x_l
\label{eq:7-25}
\end{eqnarray}
$M=0$代表该子层被丢弃,而$M=1$代表正常进行当前子层的计算。图ref{fig:7-34}展示了这个方法与标准Transformer之间的区别。
$M=0$代表该子层被丢弃,而$M=1$代表正常进行当前子层的计算。图\ref{fig:7-34}展示了这个方法与标准Pre-Norm结构之间的区别。
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter7/Figures/figure-sublayer-skip}
\caption{标准的Pre-Norm结构与基于随机跳跃子层的Pre-Norm结构}
\label{fig:7-34}
\end{figure}
%-------------------------------------------
\parinterval 除此之外,有研究者已经发现残差网络中底层的子网络通过对输入进行抽象得到的表示对最终的输出有很大的影响,上层网络通过对底层网络得到的表示不断修正来拟合训练目标\cite{DBLP:journals/corr/GreffSS16}。该结论同样适用于Transformer模型,比如,在训练中,残差支路以及底层的梯度范数通常比较大,这也间接表明底层网络在整个优化的过程中需要更大的更新。考虑到这个因素,在设计每一个子层被丢弃的概率时可以采用自底向上线性增大的策略,保证底层的网络相比于顶层更容易保留下来。这里用$L$来代表编码端块的个数,$l$代表当前的子层的编号,那么$M$可以通过以下的方式得到:
\begin{eqnarray}
......@@ -1493,14 +1502,14 @@ p_l=\frac{l}{2L}\cdot \varphi
\end{eqnarray}
这里,$1 \leqslant l \leqslant 2L$ ,且$\varphi$是预先设定的超参数。
\parinterval 在Layer Dropout中,一个由$2L$个子层构成的残差网络,其顶层的输出相当于是$2^{2L}$个子网络的聚合结果。通过随机丢弃$n$个子层,则会屏蔽掉$2^n$个子网络的输出,将子网络的总体数量降低至$2^{2L-n}$。如图\ref{fig:7-34}所示的残差网络展开图,当有3个子层时,从输入到输出共存在8条路径,当删除子层sublayer2后,从输入到输出路径的路径则会减少到4条。
\parinterval 在Layer Dropout中,一个由$2L$个子层构成的残差网络,其顶层的输出相当于是$2^{2L}$个子网络的聚合结果。通过随机丢弃$n$个子层,则会屏蔽掉$2^n$个子网络的输出,将子网络的总体数量降低至$2^{2L-n}$。如图\ref{fig:7-35}所示的残差网络展开图,当有3个子层时,从输入到输出共存在8条路径,当删除子层sublayer2后,从输入到输出路径的路径则会减少到4条。
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter7/Figures/figure-expanded-residual-network}
\caption{Layer Dropout中残差网络的展开图}
\label{fig:7-34}
\label{fig:7-35}
\end{figure}
%-------------------------------------------
......@@ -1538,27 +1547,27 @@ p_l=\frac{l}{2L}\cdot \varphi
\vspace{0.5em}
\end{itemize}
\parinterval 使用单语数据构建(双语)伪数据属于后者,它也是一种典型的{\small\bfnew{数据增强}}\index{数据增强}(Data Augmentation)\index{Data Augmentation}方法。一种常用做法是{\small\bfnew{回译}}\index{回译}(Back Translation)\index{Back Translation} \cite{DBLP:conf/acl/SennrichHB16,DBLP:conf/emnlp/EdunovOAG18}:训练一个从目标语翻译到源语的系统,也就是一个反向翻译系统;之后,用这个系统翻译目标语言单语数据;最后将单语数据(目标语言)和翻译的结果(源语言)作为训练数据,送入源语言到目标语言的翻译系统。这种做法不需要更改任何模型结构,就能很好的利用单语数据,因此也被广泛采用。图\ref{fig:7-35}给出了回译方法的一个简要流程。
\parinterval 使用单语数据构建(双语)伪数据属于后者,它也是一种典型的{\small\bfnew{数据增强}}\index{数据增强}(Data Augmentation)\index{Data Augmentation}方法。一种常用做法是{\small\bfnew{回译}}\index{回译}(Back Translation)\index{Back Translation} \cite{DBLP:conf/acl/SennrichHB16,DBLP:conf/emnlp/EdunovOAG18}:训练一个从目标语翻译到源语的系统,也就是一个反向翻译系统;之后,用这个系统翻译目标语言单语数据;最后将单语数据(目标语言)和翻译的结果(源语言)作为训练数据,送入源语言到目标语言的翻译系统。这种做法不需要更改任何模型结构,就能很好的利用单语数据,因此也被广泛采用。图\ref{fig:7-36}给出了回译方法的一个简要流程。
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter7/Figures/figure-application-process-of-back-translation}
\caption{回译方法的流程}
\label{fig:7-35}
\label{fig:7-36}
\end{figure}
%-------------------------------------------
\parinterval 在理想情况下,生成的伪数据和真实数据分布越接近越好。不过,在实践中发现,即使一些简单的策略也能带来性能的增长。比如,在一些低资源的语种,仅仅通过将目标语句子复制到源语端构造的伪数据都能为模型带来增益\cite{DBLP:conf/wmt/CurreyBH17}。相比这些简单的构造策略,利用目标语言单语数据进行回译可以获得更高质量的伪数据。因为目标语是正确的句子,这种方法可以保证译文的流畅度。这也间接达到了对目标语言进行语言建模的目的。在富资源的语种中,通常对回译产生的源语句子添加一些噪音,比如随机删除、替换一些词,或者交换两个词的位置,这样可以为模型提供一些训练噪声。而在低资源的语种上,由于双语数据稀缺,模型需要更多的高质量双语数据,不加噪音反而具有更好的效果。
\parinterval 回译方法的一个问题是:反向翻译模型的训练只依赖于有限的双语数据,生成的源语言端伪数据的质量难以保证。为此,可以采用{\small\bfnew{迭代式回译}}\index{迭代式回译}(Iterative Back Translation)\index{Iterative Back Translation}的方法,同时利用源语端和目标语端的单语数据,不断通过回译的方式来提升前向和反向翻译模型的性能。图\ref{fig:7-36}展示了迭代式回译的框架。首先使用双语数据训练一个前向翻译模型,然后利用源语言单语数据通过回译的方式来提升反向翻译模型的性能,最后由反向翻译模型和目标端单语数据生成的伪数据来提升前向翻译模型的性能。可以看出,这个往复的过程是闭环的,因此可以一直进行下去,直到两个翻译模型的性能不再提升。
\parinterval 回译方法的一个问题是:反向翻译模型的训练只依赖于有限的双语数据,生成的源语言端伪数据的质量难以保证。为此,可以采用{\small\bfnew{迭代式回译}}\index{迭代式回译}(Iterative Back Translation)\index{Iterative Back Translation}的方法,同时利用源语端和目标语端的单语数据,不断通过回译的方式来提升前向和反向翻译模型的性能。图\ref{fig:7-37}展示了迭代式回译的框架。首先使用双语数据训练一个前向翻译模型,然后利用源语言单语数据通过回译的方式来提升反向翻译模型的性能,最后由反向翻译模型和目标端单语数据生成的伪数据来提升前向翻译模型的性能。可以看出,这个往复的过程是闭环的,因此可以一直进行下去,直到两个翻译模型的性能不再提升。
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter7/Figures/figure-example-of-iterative-back-translation}
\caption{迭代式回译方法的流程}
\label{fig:7-36}
\label{fig:7-37}
\end{figure}
%-------------------------------------------
......@@ -1572,14 +1581,14 @@ p_l=\frac{l}{2L}\cdot \varphi
\parinterval 编码器-解码器框架天然就包含了对输入(源语言)和输出(目标语言)进行表示学习的过程。比如,在编码端需要学习一种分布式表示(Distributed Representation)来表示源语言句子的信息,这种分布式表示既包含单词的表示也包括整个序列的表示。因此,可以使用更大规模的源语言单语数据完成编码器的训练。
\parinterval 实现上述想法的一种手段是{\small\bfnew{预训练}}\index{预训练}(Pre-training)\index{Pre-training}。常用的方法是将机器翻译模型中的一部分(比如,编码器)单独提抽取出来,之后用语言建模等方式在大规模单语数据上进行训练。得到优化后的参数后,将其重新放入神经机器翻译模型中,作为模型的初始值。最后,神经机器翻译模型在双语数据上进行{\small\bfnew{微调}}\index{微调}(Fine-tuning)\index{Fine-tuning},以得到最终的翻译模型。图\ref{fig:7-37}给出了机器翻译编码器预训练流程的示意图。
\parinterval 实现上述想法的一种手段是{\small\bfnew{预训练}}\index{预训练}(Pre-training)\index{Pre-training}。常用的方法是将机器翻译模型中的一部分(比如,编码器)单独提抽取出来,之后用语言建模等方式在大规模单语数据上进行训练。得到优化后的参数后,将其重新放入神经机器翻译模型中,作为模型的初始值。最后,神经机器翻译模型在双语数据上进行{\small\bfnew{微调}}\index{微调}(Fine-tuning)\index{Fine-tuning},以得到最终的翻译模型。图\ref{fig:7-38}给出了机器翻译编码器预训练流程的示意图。
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter7/Figures/figure-encoder-fin}
\caption{机器翻译编码器预训练流程}
\label{fig:7-37}
\label{fig:7-38}
\end{figure}
%-------------------------------------------
......@@ -1604,11 +1613,11 @@ p_l=\frac{l}{2L}\cdot \varphi
\centering
\input{./Chapter7/Figures/figure-MASS}
\caption{MASS 预训练方法}
\label{fig:7-38}
\label{fig:7-39}
\end{figure}
%-------------------------------------------
\parinterval 以MASS方法为例\cite{song2019mass},可以直接对整个编码器-解码器的结构进行预训练。训练中采用掩码的方式,将源语词序列中的片段替换成特殊词<mask>,然后在解码器端预测这个未知片段,如图\ref{fig:7-38}所示,\#号表示特殊词<mask>。这种做法可以使得编码器端捕捉上下文信息,同时迫使解码器依赖于编码器,学习编码器和解码器之间的注意力进行预训练。而解码器端片段的预测也使得解码器能够学习到向前依赖的上下文表示。
\parinterval 以MASS方法为例\cite{song2019mass},可以直接对整个编码器-解码器的结构进行预训练。训练中采用掩码的方式,将源语词序列中的片段替换成特殊词<mask>,然后在解码器端预测这个未知片段,如图\ref{fig:7-39}所示,\#号表示特殊词<mask>。这种做法可以使得编码器端捕捉上下文信息,同时迫使解码器依赖于编码器,学习编码器和解码器之间的注意力进行预训练。而解码器端片段的预测也使得解码器能够学习到向前依赖的上下文表示。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
......@@ -1618,14 +1627,14 @@ p_l=\frac{l}{2L}\cdot \varphi
\parinterval {\small\bfnew{多任务学习}}\index{多任务学习}(Multitask Learning)\index{Multitask Learning}是机器学习的一个子领域,是指同时学习多个独立但是相关的任务\cite{DBLP:journals/corr/Ruder17a}。多任务学习通过模型共享的方式,对多个模型进行学习,而这些模型都对应不同的任务,这样不同模型可以互相``促进''。在神经机器翻译中,为了使用单语数据,可以将翻译任务作为主任务,同时设置一些仅使用单语数据的子任务,通过这些子任务来捕捉单语数据中的语言知识\cite{DBLP:conf/emnlp/DomhanH17}
\parinterval 语言模型是使用目标端单语数据最直接的方式,但是翻译模型作为一个受限的语言模型,还需要依赖于源语,并不能直接进行多任务学习。针对这个问题,对原有翻译模型结构进行了修改,在解码器中增加了一个语言模型子层,将这个子层用于语言模型任务(图\ref{fig:7-39})。在训练过程中,分别将双语数据和单语数据送入翻译模型和语言模型进行计算,得到的损失相加用于整体模型参数的梯度计算和参数更新,其中语言模型的参数是翻译模型的一部分。
\parinterval 语言模型是使用目标端单语数据最直接的方式,但是翻译模型作为一个受限的语言模型,还需要依赖于源语,并不能直接进行多任务学习。针对这个问题,对原有翻译模型结构进行了修改,在解码器中增加了一个语言模型子层,将这个子层用于语言模型任务(图\ref{fig:7-40})。在训练过程中,分别将双语数据和单语数据送入翻译模型和语言模型进行计算,得到的损失相加用于整体模型参数的梯度计算和参数更新,其中语言模型的参数是翻译模型的一部分。
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter7/Figures/figure-target-side-multi-task-learning}
\caption{机器翻译中的单任务学习和多任务学习}
\label{fig:7-39}
\label{fig:7-40}
\end{figure}
%-------------------------------------------
......@@ -1698,7 +1707,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\label{eq:7-30}
\end{eqnarray}
这样的损失函数带来最直接的好处是,知识精炼的流程会非常简单。因为只需要利用教师模型将训练数据(源语言)翻译一遍,之后把它的输出替换为训练数据的目标语言部分。之后,利用得到的新的双语数据训练学生模型即可,图\ref{fig:7-40}展示了简化后词级和序列级的不同,其中词级知识精炼的解码端输入为真实双语数据的目标语言,并以teacher模型输出的概率分布作为学习目标,而序列级则直接将teacher推断后得到的结果作为解码端的输入,并将解码结果的One-hot向量作为学习目标。
这样的损失函数带来最直接的好处是,知识精炼的流程会非常简单。因为只需要利用教师模型将训练数据(源语言)翻译一遍,之后把它的输出替换为训练数据的目标语言部分。之后,利用得到的新的双语数据训练学生模型即可,图\ref{fig:7-41}展示了简化后词级和序列级的不同,其中词级知识精炼的解码端输入为真实双语数据的目标语言,并以teacher模型输出的概率分布作为学习目标,而序列级则直接将teacher推断后得到的结果作为解码端的输入,并将解码结果的One-hot向量作为学习目标。
\vspace{0.5em}
\end{itemize}
......@@ -1707,7 +1716,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\centering
\input{./Chapter7/Figures/figure-difference-between-word-level-and-sequence-level-in-knowledge-distillation}
\caption{词级和序列级知识精炼的差异}
\label{fig:7-40}
\label{fig:7-41}
\end{figure}
%-------------------------------------------
......@@ -1734,14 +1743,14 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\vspace{0.5em}
\end{itemize}
\parinterval 此外还可以采用迭代的知识精炼的方式。首先,通过模型集成得到较强的教师模型,再将知识迁移到不同的学生模型上,随后继续使用这些学生模型集成新的教师模型。不断的重复上述过程可以逐步提升集成模型的性能,如图\ref{fig:7-41}所示。值得注意的是,随着迭代次数的增加,集成所带来的收益也会随着子模型之间差异性的减小而减少。
\parinterval 此外还可以采用迭代的知识精炼的方式。首先,通过模型集成得到较强的教师模型,再将知识迁移到不同的学生模型上,随后继续使用这些学生模型集成新的教师模型。不断的重复上述过程可以逐步提升集成模型的性能,如图\ref{fig:7-42}所示。值得注意的是,随着迭代次数的增加,集成所带来的收益也会随着子模型之间差异性的减小而减少。
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter7/Figures/figure-ensemble-knowledge-distillation}
\caption{迭代式知识精炼}
\label{fig:7-41}
\label{fig:7-42}
\end{figure}
%-------------------------------------------
......@@ -1799,14 +1808,14 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\label{eq:7-34}
\end{eqnarray}
\noindent 公式\ref{eq:7-34}假设$\textrm{P}(\mathbf s|\mathbf t)=\textrm{P}(\mathbf s|\mathbf s,\mathbf t)$。这个假设显然是成立的,因为当知道一个句子的译文时,并不需要知道它的源文就可以把它翻译回去。如果直接优化(最大化)公式\ref{eq:7-34}右侧,相当于对这个等式$\textrm{P}(\mathbf s|\mathbf t)$$\textrm{P}(\mathbf t|\mathbf s)$施加了{\small\bfnew{循环一致性}}\index{循环一致性}(Circle Consistency)\index{Circle Consistency}的约束\cite{DBLP:conf/iccv/ZhuPIE17},也就是对于一个句子$\mathbf s$,通过$\textrm{P}(\mathbf t|\mathbf s)$把它翻译成$\mathbf t$后,根据$\textrm{P}(\mathbf s|\mathbf t)$应该能重新翻译出$\mathbf s$,如图\ref{fig:7-42}所示。公式\ref{eq:7-34}给出了同时优化$\textrm{P}(\mathbf s|\mathbf t)$$\textrm{P}(\mathbf t|\mathbf s)$的一个目标函数形式。这个目标函数的一个额外的好处是它本质上是在学习一个由$\textrm{P}(\mathbf s|\mathbf t)$$\textrm{P}(\mathbf t|\mathbf s)$组成的语言模型$\textrm{P}(\mathbf s)$,而$\textrm{P}(\mathbf s)$的学习依赖于单语数据,这意味着这个目标函数可以很自然地直接使用大量单语数据来同时训练两个翻译模型。相同的结论可以推广到$\textrm{P}(\mathbf t)$\cite{DBLP:conf/nips/HeXQWYLM16}
\noindent 公式\ref{eq:7-34}假设$\textrm{P}(\mathbf s|\mathbf t)=\textrm{P}(\mathbf s|\mathbf s,\mathbf t)$。这个假设显然是成立的,因为当知道一个句子的译文时,并不需要知道它的源文就可以把它翻译回去。如果直接优化(最大化)公式\ref{eq:7-34}右侧,相当于对这个等式$\textrm{P}(\mathbf s|\mathbf t)$$\textrm{P}(\mathbf t|\mathbf s)$施加了{\small\bfnew{循环一致性}}\index{循环一致性}(Circle Consistency)\index{Circle Consistency}的约束\cite{DBLP:conf/iccv/ZhuPIE17},也就是对于一个句子$\mathbf s$,通过$\textrm{P}(\mathbf t|\mathbf s)$把它翻译成$\mathbf t$后,根据$\textrm{P}(\mathbf s|\mathbf t)$应该能重新翻译出$\mathbf s$,如图\ref{fig:7-43}所示。公式\ref{eq:7-34}给出了同时优化$\textrm{P}(\mathbf s|\mathbf t)$$\textrm{P}(\mathbf t|\mathbf s)$的一个目标函数形式。这个目标函数的一个额外的好处是它本质上是在学习一个由$\textrm{P}(\mathbf s|\mathbf t)$$\textrm{P}(\mathbf t|\mathbf s)$组成的语言模型$\textrm{P}(\mathbf s)$,而$\textrm{P}(\mathbf s)$的学习依赖于单语数据,这意味着这个目标函数可以很自然地直接使用大量单语数据来同时训练两个翻译模型。相同的结论可以推广到$\textrm{P}(\mathbf t)$\cite{DBLP:conf/nips/HeXQWYLM16}
%----------------------------------------------
\begin{figure}[htp]
\centering
\input{./Chapter7/Figures/figure-cycle-consistency}
\caption{循环一致性}
\label{fig:7-42}
\label{fig:7-43}
\end{figure}
%----------------------------------------------
......
......@@ -6,16 +6,16 @@
\begin{scope}[minimum height = 20pt]
\node [anchor=east] (x1) at (-0.5em, 0) {$x_l$};
\node [anchor=west,draw=green,fill=green!20,inner xsep=5pt] (F1) at ([xshift=2em]x1.east){$\mathcal{F}$};
\node [anchor=west,draw,fill=red!20,inner xsep=5pt,rounded corners=2pt] (F1) at ([xshift=2em]x1.east){\small{$\mathcal{F}$}};
\node [anchor=west,circle,draw,minimum size=1em] (n1) at ([xshift=2em]F1.east) {};
\node [anchor=west,draw=green,fill=green!20,inner xsep=5pt] (ln1) at ([xshift=2em]n1.east){\textrm{LN}};
\node [anchor=west] (x2) at ([xshift=2em]ln1.east) {$x_{l+l}$};
\node [anchor=west,draw,fill=green!20,inner xsep=5pt,rounded corners=2pt] (ln1) at ([xshift=2em]n1.east){\small{\textrm{LN}}};
\node [anchor=west] (x2) at ([xshift=2em]ln1.east) {$x_{l+1}$};
\node [anchor=north] (x3) at ([yshift=-5em]x1.south) {$x_l$};
\node [anchor=west,draw=green,fill=green!20,inner xsep=5pt] (F2) at ([xshift=2em]x3.east){$\mathcal{F}$};
\node [anchor=west,draw=green,fill=green!20,inner xsep=5pt] (ln2) at ([xshift=2em]F2.east){\textrm{LN}};
\node [anchor=west,draw,fill=green!20,inner xsep=5pt,rounded corners=2pt] (F2) at ([xshift=2em]x3.east){\small{\textrm{LN}}};
\node [anchor=west,draw,fill=red!20,inner xsep=5pt,rounded corners=2pt] (ln2) at ([xshift=2em]F2.east){\small{$\mathcal{F}$}};
\node [anchor=west,circle,draw,,minimum size=1em] (n2) at ([xshift=2em]ln2.east){};
\node [anchor=west] (x4) at ([xshift=2em]n2.east) {$x_{l+l}$};
\node [anchor=west] (x4) at ([xshift=2em]n2.east) {$x_{l+1}$};
\draw[->, line width=1pt] ([xshift=-0.1em]x1.east)--(F1.west);
\draw[->, line width=1pt] ([xshift=-0.1em]F1.east)--(n1.west);
......@@ -25,8 +25,8 @@
\draw[->, line width=1pt] ([xshift=-0.1em]F2.east)--(ln2.west);
\draw[->, line width=1pt] ([xshift=0.1em]ln2.east)--node[above]{$y_l$}(n2.west);
\draw[->, line width=1pt] (n2.east)--(x4.west);
\draw[->, line width=1pt] (x1.north) -- ([yshift=1em]x1.north) -- ([yshift=1.4em]n1.north) -- (n1.north);
\draw[->, line width=1pt] (x3.north) -- ([yshift=1em]x3.north) -- ([yshift=1.4em]n2.north) -- (n2.north);
\draw[->,rounded corners,line width=1pt] ([yshift=-0.2em]x1.north) -- ([yshift=1em]x1.north) -- ([yshift=1.4em]n1.north) -- (n1.north);
\draw[->,rounded corners,line width=1pt] ([yshift=-0.2em]x3.north) -- ([yshift=1em]x3.north) -- ([yshift=1.4em]n2.north) -- (n2.north);
\draw[-] (n1.west)--(n1.east);
\draw[-] (n1.north)--(n1.south);
\draw[-] (n2.west)--(n2.east);
......@@ -39,8 +39,8 @@
\node [rectangle,inner sep=0.3em,fill=blue!10] [fit = (x3) (F2) (n2) (ln2) (x4) (k2)] (box1) {};
\end{pgfonlayer}
\node [anchor=north] (c1) at (box0.south){\small (a)后作方式的残差连接};
\node [anchor=north] (c2) at (box1.south){\small (b)前作方式的残差连接};
\node [anchor=north] (c1) at (box0.south){\footnotesize {(a)后作方式的残差连接}};
\node [anchor=north] (c2) at (box1.south){\footnotesize {(b)前作方式的残差连接}};
\end{scope}
\end{tikzpicture}
\end{center}
\ No newline at end of file
%%%------------------------------------------------------------------------------------------------------------
%%% 调序模型1:基于距离的调序
\begin{center}
\begin{tikzpicture}
\begin{scope}[minimum height = 20pt]
\node [anchor=east] (x1) at (-0.5em, 0) {$x_l$};
\node [anchor=west,draw,fill=red!20,inner xsep=5pt,rounded corners=2pt] (ln1) at ([xshift=1em]x1.east){\small{\textrm{LN}}};
\node [anchor=west,draw,fill=green!20,inner xsep=5pt,rounded corners=2pt] (f1) at ([xshift=0.6em]ln1.east){\small{$\mathcal{F}$}};
\node [anchor=west,circle,draw,,minimum size=1em] (n1) at ([xshift=3em]f1.east){};
\node [anchor=west] (x2) at ([xshift=1em]n1.east) {$x_{l+1}$};
\node [anchor=west,draw,fill=red!20,inner xsep=5pt,rounded corners=2pt] (ln12) at ([xshift=1em]x2.east){\small{\textrm{LN}}};
\node [anchor=west,draw,fill=green!20,inner xsep=5pt,rounded corners=2pt] (f12) at ([xshift=0.6em]ln12.east){\small{$\mathcal{F}$}};
\node [anchor=west,circle,draw,,minimum size=1em] (n12) at ([xshift=3em]f12.east){};
\node [anchor=west] (x22) at ([xshift=1em]n12.east) {$x_{l+2}$};
\node [anchor=north] (x3) at ([yshift=-5em]x1.south) {$x_l$};
\node [anchor=west,draw,fill=red!20,inner xsep=5pt,rounded corners=2pt] (ln2) at ([xshift=1em]x3.east){\small{\textrm{LN}}};
\node [anchor=west,draw,fill=green!20,inner xsep=5pt,rounded corners=2pt] (f2) at ([xshift=0.6em]ln2.east){\small{$\mathcal{F}$}};
\node [anchor=west,minimum size=1em] (p1) at ([xshift=1em]f2.east){};
\node [anchor=north] (m1) at ([yshift=0.6em]p1.south){\tiny{\red{$M=1$}}};
\node [anchor=west,circle,draw,,minimum size=1em] (n2) at ([xshift=3em]f2.east){};
\node [anchor=west] (x4) at ([xshift=1em]n2.east) {$x_{l+1}$};
\node [anchor=west,draw,fill=red!20,inner xsep=5pt,rounded corners=2pt] (ln22) at ([xshift=1em]x4.east){\small{\textrm{LN}}};
\node [anchor=west,draw,fill=green!20,inner xsep=5pt,rounded corners=2pt] (f22) at ([xshift=0.6em]ln22.east){\small{$\mathcal{F}$}};
\node [anchor=west,minimum size=1em] (p2) at ([xshift=1em]f22.east){};
\node [anchor=north] (m2) at ([yshift=0.6em]p2.south){\tiny{\red{$M=0$}}};
\node [anchor=west,circle,draw,,minimum size=1em] (n22) at ([xshift=3em]f22.east){};
\node [anchor=west] (x42) at ([xshift=1em]n22.east) {$x_{l+2}$};
\draw[->, line width=1pt] ([xshift=-0.1em]x1.east)--(ln1.west);
\draw[->, line width=1pt] ([xshift=-0.1em]ln1.east)--(f1.west);
\draw[->, line width=1pt] ([xshift=0.1em]f1.east)--(n1.west);
\draw[->, line width=1pt] (n1.east)--(x2.west);
\draw[->, line width=1pt] ([xshift=-0.1em]x3.east)--(ln2.west);
\draw[->, line width=1pt] ([xshift=-0.1em]ln2.east)--(f2.west);
\draw[-, line width=1pt] ([xshift=0.1em]f2.east)--(p1.west);
\draw[*-,red,line width=0.6pt] (p1.west) -- (p1.east);
\draw[->, line width=1pt] (p1.east)--(n2.west);
\draw[->, line width=1pt] (n2.east)--(x4.west);
\draw[->,rounded corners,line width=1pt] ([yshift=-0.2em]x1.north) -- ([yshift=1em]x1.north) -- ([yshift=1.4em]n1.north) -- (n1.north);
\draw[->,rounded corners,line width=1pt] ([yshift=-0.2em]x3.north) -- ([yshift=1em]x3.north) -- ([yshift=1.4em]n2.north) -- (n2.north);
\draw[-] (n1.west)--(n1.east);
\draw[-] (n1.north)--(n1.south);
\draw[-] (n2.west)--(n2.east);
\draw[-] (n2.north)--(n2.south);
\draw[->, line width=1pt] ([xshift=-0.1em]x2.east)--(ln12.west);
\draw[->, line width=1pt] ([xshift=-0.1em]ln12.east)--(f12.west);
\draw[->, line width=1pt] ([xshift=0.1em]f12.east)--(n12.west);
\draw[->, line width=1pt] (n12.east)--(x22.west);
\draw[->, line width=1pt] ([xshift=-0.1em]x4.east)--(ln22.west);
\draw[->, line width=1pt] ([xshift=-0.1em]ln22.east)--(f22.west);
\draw[-, line width=1pt] ([xshift=0.1em]f22.east)--(p2.west);
\draw[*-,red,line width=0.6pt] ([yshift=-0.1em]p2.west) -- (p2.north east);
\draw[->, line width=1pt] (p2.east)--(n22.west);
\draw[->, line width=1pt] (n22.east)--(x42.west);
\draw[->,rounded corners,line width=1pt] ([yshift=-0.2em]x2.north) -- ([yshift=1em]x2.north) -- ([yshift=1.4em]n12.north) -- (n12.north);
\draw[->,rounded corners,line width=1pt] ([yshift=-0.2em]x4.north) -- ([yshift=1em]x4.north) -- ([yshift=1.4em]n22.north) -- (n22.north);
\draw[-] (n12.west)--(n12.east);
\draw[-] (n12.north)--(n12.south);
\draw[-] (n22.west)--(n22.east);
\draw[-] (n22.north)--(n22.south);
\node [anchor=south] (k1) at ([yshift=-0.1em]x1.north){};
\node [anchor=south] (k2) at ([yshift=-0.1em]x3.north){};
\begin{pgfonlayer}{background}
\node [rectangle,inner sep=0.3em,fill=orange!10] [fit = (x1) (f1) (n1) (ln1) (x2) (k1) (f12) (n12) (ln12) (x22)] (box0) {};
\node [rectangle,inner sep=0.3em,fill=blue!10] [fit = (x3) (f2) (n2) (ln2) (x4) (k2) (f22) (n22) (ln22) (x42)] (box1) {};
\end{pgfonlayer}
\node [anchor=north] (c1) at (box0.south){\footnotesize {(a)标准的Pre-Norm}};
\node [anchor=north] (c2) at (box1.south){\footnotesize {(b)基于随机子层跳跃的Pre-Norm}};
\end{scope}
\end{tikzpicture}
\end{center}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论