Commit 9e83bb9f by zengxin

chapter6

parent d9df9f99
......@@ -55,7 +55,7 @@
\parinterval 从广义上讲,神经机器翻译是一种基于人工神经网络的方法,它把翻译过程描述为可以用人工神经网络表示的函数。所有的训练和推断都在这些函数上进行。由于神经机器翻译中的神经网络可以用连续可微函数表示,因此这类方法也可以用基于梯度的方法进行优化,相关技术非常成熟。更为重要的是,在神经网络的设计中,研究者引入了{\small\bfnew{分布式表示}}(Distributed Representation)的概念,这也是近些年自然语言处理领域的重要成果之一。传统统计机器翻译仍然把词序列看作离散空间里的由多个特征函数描述的点,类似于$n$-gram语言模型,这类模型对数据稀疏问题非常敏感。此外,人工设计特征也在一定程度上限制了模型对问题的表示能力。神经机器翻译把文字序列表示为实数向量,一方面避免了特征工程繁重的工作,另一方面使得系统可以对文字序列的``表示''进行学习。可以说,神经机器翻译的成功很大程度上源自`` 表示学习''这种自然语言处理的新范式的出现。在表示学习的基础上,注意力机制、深度神经网络等技术都被应用于神经机器翻译,使其得以进一步发展。
\parinterval 虽然神经机器翻译中大量的使用了人工神经网络方法,但是它并不是最早在机器翻译中使用人工神经网络的框架。实际上,人工神经网络在机器翻译中应用的历史要远早于现在的神经机器翻译。 在统计机器翻译时代,也有很多利用人工神经网络进行进行机器翻译系统模块的构建\cite{devlin-etal-2014-fast}\cite{Schwenk_continuousspace},比如,Jacob Devlin等人就成功的在统计机器翻译系统中使用了基于神经网络的联合表示模型,取得了令人振奋的结果,这项工作也获得了ACL2014的最佳论文奖(best paper award)。
\parinterval 虽然神经机器翻译中大量的使用了人工神经网络方法,但是它并不是最早在机器翻译中使用人工神经网络的框架。实际上,人工神经网络在机器翻译中应用的历史要远早于现在的神经机器翻译。 在统计机器翻译时代,也有很多利用人工神经网络进行机器翻译系统模块的构建\cite{devlin-etal-2014-fast}\cite{Schwenk_continuousspace},比如,Jacob Devlin等人就成功地在统计机器翻译系统中使用了基于神经网络的联合表示模型,取得了令人振奋的结果,这项工作也获得了ACL2014的最佳论文奖(best paper award)。
\parinterval 不过,以上这些工作大多都是在系统的局部模块中使用人工神经网络和深度学习方法。与之不同的是,神经机器翻译是用人工神经网络完成整个翻译过程的建模,这样做的一个好处是,整个系统可以进行端到端学习,无需引入对任何翻译的隐含结构假设。这种利用端到端学习对机器翻译进行神经网络建模的方式也就成为了现在大家所熟知的神经机器翻译。这里简单列出部分代表性的工作:
......@@ -86,7 +86,7 @@
\label{fig:6-61}
\end{figure}
%----------------------------------------------
\parinterval 可以明显的看到到译文2更加的通顺,意思的表达更加准确,翻译质量明显高于译文1。这个例子基本反应出统计机器翻译和神经机器翻译的差异性。当然,这里并不是要讨论统计机器翻译和神经机器翻译孰优孰劣。但是,很多场景中都不难发现神经机器翻译可以生成非常流畅的译文,易于人工阅读和修改。
\parinterval 可以明显地看到译文2更加的通顺,意思的表达更加准确,翻译质量明显高于译文1。这个例子基本反应出统计机器翻译和神经机器翻译的差异性。当然,这里并不是要讨论统计机器翻译和神经机器翻译孰优孰劣。但是,很多场景中都不难发现神经机器翻译可以生成非常流畅的译文,易于人工阅读和修改。
\parinterval 在很多量化的评价中也可以看到神经机器翻译的优势。回忆一下第一章提到的机器翻译质量的自动评估指标中,使用最广泛的一种指标是BLEU。在统计机器翻译时代,在由美国国家标准和科技机构(NIST)举办的汉英机器翻译评测中(比如汉英MT08数据集),基于统计方法的翻译系统能够得到30\%以上的BLEU值已经是当时最顶尖的结果了,而现在神经机器翻译系统,则可以轻松的将BLEU提高至45\%以上。
......@@ -293,9 +293,9 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\end{figure}
%----------------------------------------------
\parinterval 翻译过程的神经网络结构如图\ref{fig:6-6}所示,其中左边是编码器,右边是解码器。编码器会顺序处理源语言单词,将每个单词都表示成一个实数向量,也就是每个单词的词嵌入结果(绿色方框)。在词嵌入的基础上运行循环神经网络(蓝色方框)。在编码下一个时间步状态的时候,上一个时间步的隐藏状态会作为历史信息传入给循环神经网络。这样,句子中每个位置的信息都被向后传递,最后一个时间步的隐藏状态(红色方框)就包含了整个源语言句子的信息,也就得到了编码器的编码结果$\ \dash\ $源语言句子的分布式表示。
\parinterval 翻译过程的神经网络结构如图\ref{fig:6-6}所示,其中左边是编码器,右边是解码器。编码器会顺序处理源语言单词,将每个单词都表示成一个实数向量,也就是每个单词的词嵌入结果(绿色方框)。在词嵌入的基础上运行循环神经网络(蓝色方框)。在编码下一个时间步状态的时候,上一个时间步的隐藏状态会作为历史信息传入给循环神经网络。这样,句子中每个位置的信息都被向后传递,最后一个时间步的隐藏状态(红色方框)就包含了整个源语言句子的信息,也就得到了编码器的编码结果$\ \dash\ $源语言句子的分布式表示。
\parinterval 编码器直接把源语言句子的分布式表示作为输入的隐层状态,之后像编码器一样依次读入目标语言单词,这是一个标准的循环神经网络的执行过程。与编码器不同的是,解码器会有一个输出层,用于根据当前时间步的隐层状态生成目标语单词及其概率分布。可以看到,解码端一个时刻的输出单词与下一个时刻的输入单词是一样的。从这个角度说,解码器也是一种神经语言模型,只不过它会从另外一种语言(源语言)获得一些信息,而不是仅仅做单语句子的生成。具体来说,当生成第一个单词``I''时,解码器利用了源语言句子表示(红色方框)和目标语的起始词``<sos>''。在生成第二个单词``am''时,解码器利用了上一个时间步的隐藏状态(隐藏层变量)和已经生成的``I''的信息。这个过程会循环执行直到生成完整的目标语句子。
\parinterval 编码器直接把源语言句子的分布式表示作为输入的隐层状态,之后像编码器一样依次读入目标语言单词,这是一个标准的循环神经网络的执行过程。与编码器不同的是,解码器会有一个输出层,用于根据当前时间步的隐层状态生成目标语单词及其概率分布。可以看到,解码端当前时刻的输出单词与下一个时刻的输入单词是一样的。从这个角度说,解码器也是一种神经语言模型,只不过它会从另外一种语言(源语言)获得一些信息,而不是仅仅做单语句子的生成。具体来说,当生成第一个单词``I''时,解码器利用了源语言句子表示(红色方框)和目标语的起始词``<sos>''。在生成第二个单词``am''时,解码器利用了上一个时间步的隐藏状态(隐藏层变量)和已经生成的``I''的信息。这个过程会循环执行直到生成完整的目标语句子。
\parinterval 从这个例子可以看出,神经机器翻译的流程其实并不复杂:首先通过编码器神经网络将源语言句子编码成实数向量,然后解码器神经网络利用源语言句子的表示结果逐词生成译文。几乎所有的神经机器翻译系统都是类似架构。
......@@ -434,7 +434,7 @@ NMT & $ 21.7^{\ast}$ & $18.7^{\ast}$ & -1
\label{eqC6.4}
\end{eqnarray}
$\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Softmax的输入是循环神经网络$j$时刻的输出。在具体实现时,$\mathbf{C}$可以被简单的作为第一个时刻循环单元的输入,即,当$j=1$ 时,解码器的循环神经网络会读入编码器最后一个隐层状态$ \mathbf{h}_m$(也就是$\mathbf{C}$),而其他时刻的隐层状态不直与$\mathbf{C}$相关。最终,$\textrm{P} (y_j | \mathbf{y}_{<j},\mathbf{x})$ 被表示为:
$\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Softmax的输入是循环神经网络$j$时刻的输出。在具体实现时,$\mathbf{C}$可以被简单的作为第一个时刻循环单元的输入,即,当$j=1$ 时,解码器的循环神经网络会读入编码器最后一个隐层状态$ \mathbf{h}_m$(也就是$\mathbf{C}$),而其他时刻的隐层状态不直$\mathbf{C}$相关。最终,$\textrm{P} (y_j | \mathbf{y}_{<j},\mathbf{x})$ 被表示为:
\begin{eqnarray}
\textrm{P} (y_j | \mathbf{y}_{<j},\mathbf{x}) \equiv
\left \{ \begin{array}{ll}
......@@ -472,7 +472,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\noindent 这里,$\mathbf{E}$也被称作词嵌入矩阵,它可以作为模型的一部分参数共同参与机器翻译系统的训练,也可以由外部其他模块训练得到(如预训练模型)。$\mathbf{E}$的大小为$|V| \times d$,这里$|V|$表示词表$V$的大小,$d$表示循环神经网络输入和输出向量的维度。
\parinterval\ref{fig:6-11}以单词``you''为例,展示了词嵌入的生成过程。词嵌入层首先将输入的单词``you''转化成One-hot表示,对应虚线框中的0-1向量,即除了you在词表中的索引位置为1,其余位置均为0。然后词嵌入层将这个0-1向量乘以$\mathbf{E}$就得到了词嵌入的结果(绿色圆角框框起来部分),这里用$\textrm{e}_y (\cdot)$表示这个过程,即you的词嵌入表示$\textrm{e}_y (``\textrm{you}'')$。最后,将单词的词嵌入表示作为当前时间步循环单元(蓝色方框)的输入。
\parinterval\ref{fig:6-11}以单词``you''为例,展示了词嵌入的生成过程。词嵌入层首先将输入的单词``you''转化成One-hot表示,对应虚线框中的0-1向量,即除了you在词表中的索引位置为1,其余位置均为0。然后词嵌入层将这个0-1向量乘以$\mathbf{E}$就得到了词嵌入的结果(绿色圆角框框起来部分),这里用$\textrm{e}_y (\cdot)$表示这个过程,即you的词嵌入表示$\textrm{e}_y (\textrm{``you''})$。最后,将单词的词嵌入表示作为当前时间步循环单元(蓝色方框)的输入。
%----------------------------------------------
% 图3.10
......@@ -546,7 +546,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\label{eqC6.10}
\end{eqnarray}
\parinterval 最终得到在整个词表上的概率分布$(0.00260.23080.7666)$,其中概率最大的单词``学习'',便是得到最终的译文单词。
\parinterval 最终得到在整个词表上的概率分布$(0.00260.23080.7666)$,其中概率最大的单词``学习'',便是最终的译文单词。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{循环神经网络结构}\index{Chapter6.3.3}
\label{sec:6.3.3}
......@@ -561,7 +561,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\noindent 其中$\mathbf{x}_t$是当前时刻的输入,$\mathbf{h}_{t-1}$是上一时刻循环单元的输出,$f(\cdot)$是激活函数,$\mathbf{U}$$\mathbf{W}$是参数矩阵,$\mathbf{b}$是偏置。
\parinterval 虽然RNN的结构很简单,但是已经具有了对序列信息进行记忆的能力。实际上,基于RNN结构的神经语言模型已经能够取得比传统$n$-gram语言模型更优异的性能。在机器翻译中,RNN也可以做为入门或者快速原型所使用的神经网络结构。
\parinterval 虽然RNN的结构很简单,但是已经具有了对序列信息进行记忆的能力。实际上,基于RNN结构的神经语言模型已经能够取得比传统$n$-gram语言模型更优异的性能。在机器翻译中,RNN也可以做为入门或者快速原型所使用的神经网络结构。
%%%%%%%%%%%%%%%%%%
\subsubsection{长短时记忆网络(LSTM)}\index{Chapter6.3.3.2}
\label{sec:6.3.3.2}
......@@ -592,7 +592,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\label{eqC6.12}
\end{eqnarray}
这里,$\mathbf{W}_f$是权值,$\mathbf{b}_f$是偏置,$[\mathbf{h}_{t-1},\mathbf{x}_{t}]$表示两个向量的拼接。该公式可以解释为,对$[\mathbf{h}_{t-1},\mathbf{x}_{t}]$进行变换,并得到一个实数向量$\mathbf{f}_t$$\mathbf{f}_t$的每一维都可以被理解为一个``门'',它决定可以有多少信息被留下(或遗忘)。
这里,$\mathbf{W}_f$是权值,$\mathbf{b}_f$是偏置,$[\mathbf{h}_{t-1},\mathbf{x}_{t}]$表示两个向量的拼接。该公式可以解释为,对$[\mathbf{h}_{t-1},\mathbf{x}_{t}]$进行变换,并得到一个实数向量$\mathbf{f}_t$$\mathbf{f}_t$的每一维都可以被理解为一个``门'',它决定可以有多少信息被留下(或遗忘)。
\item {\small\sffamily\bfseries{记忆更新}}。首先,要生成当前时刻需要新增加的信息,该部分由输入门完成,其结构如图\ref{fig:6-14}(b)红色线部分,图中``$\bigotimes$''表示进行点乘操作。输入门的计算分为两部分,首先利用$\sigma$决定门控参数$\mathbf{i}_t$,然后通过Tanh函数得到新的信息$\hat{\mathbf{c}}_t$,具体公式如下:
\begin{eqnarray}
......@@ -611,7 +611,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\label{eqC6.15}
\end{eqnarray}
\item {\small\sffamily\bfseries{输出}}。该部分使用输出门计算最终的输出信息$\mathbf{h}_t$,其结构如图\ref{fig:6-14}(d)红色线部分所示。在输出门中,首先将$\mathbf{x}_t$$\mathbf{h}_{t-1}$通过$\sigma$函数变换得到$\mathbf{o}_t$。其次,将上一步得到的新记忆信息$\mathbf{c}_t$通过Tanh函数进行变换,得到值范围在[-1,1]的向量。最后将这两部分进行点乘,具体公式如下:
\item {\small\sffamily\bfseries{输出}}。该部分使用输出门计算最终的输出信息$\mathbf{h}_t$,其结构如图\ref{fig:6-14}(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{eqC6.16} \\
......@@ -670,7 +670,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
%%%%%%%%%%%%%%%%%%
\subsubsection{双向模型}\index{Chapter6.3.3.4}
\parinterval 前面提到的循环神经网络都是自左向右运行的,也就是说在处理一个单词的时候只能访问它前面的序列信息。但是,只根据句子的前文来生成一个序列的表示是不全面的,因为从最后一个词来看,第一个词的信息可能已经很微弱了。为了同时考虑前文和后文的信息,一种解决办法是使用双向循环网络,其结构如图\ref{fig:6-17}所示。这里,编码器可以看作有两个循环神经网络,第一个网络,即红色虚线框里的网络,从句子的右边进行处理,第二个网络从句子左边开始处理,最终将正向和反向得到的结果都融合后传递给码器。
\parinterval 前面提到的循环神经网络都是自左向右运行的,也就是说在处理一个单词的时候只能访问它前面的序列信息。但是,只根据句子的前文来生成一个序列的表示是不全面的,因为从最后一个词来看,第一个词的信息可能已经很微弱了。为了同时考虑前文和后文的信息,一种解决办法是使用双向循环网络,其结构如图\ref{fig:6-17}所示。这里,编码器可以看作有两个循环神经网络,第一个网络,即红色虚线框里的网络,从句子的右边进行处理,第二个网络从句子左边开始处理,最终将正向和反向得到的结果都融合后传递给码器。
%----------------------------------------------
% 图3.10
......@@ -682,13 +682,13 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\end{figure}
%----------------------------------------------
\parinterval 双向模型是自然语言处理领域的常用模型,包括前面提到的词对齐对称化、语言模型等中都大量使用了类似的思路。实际上,这里也体现了建模时的非对称思想。也就是,建模时如果设计一个对称模型可能会导致问题复杂度增加,因此往往先对问题进行化简,从某一个角度解决问题。之后再融合多个模型,从不同角度得到相对合理的最终方案。
\parinterval 双向模型是自然语言处理领域的常用模型,包括前面提到的词对齐对称化、语言模型等中都大量使用了类似的思路。实际上,这里也体现了建模时的非对称思想。也就是,建模时如果设计一个对称模型可能会导致问题复杂度增加,因此往往先对问题进行化简,从某一个角度解决问题。之后再融合多个模型,从不同角度得到相对合理的最终方案。
%%%%%%%%%%%%%%%%%%
\subsubsection{多层循环神经网络}\index{Chapter6.3.3.5}
\parinterval 实际上,对于单词序列所使用的循环神经网络是一种很``深''的网络,因为从第一个单词到最后一个单词需要经过至少句子长度相当层数的神经元。比如,一个包含几十个词的句子也会对应几十个神经元层。但是,在很多深度学习应用中,更习惯把对输入序列的同一种处理作为``一层''。比如,对于输入序列,构建一个RNN,那么这些循环单元就构成了网络的``一层''。当然,这里并不是要混淆概念。只是要明确,在随后的讨论中,``层''并不是指一组神经元的全连接,它更多的代表的是对网络的拓扑结构的说法。
\parinterval 单层循环神经网络对输入序列进行了抽象,为了到更深入的抽象能力,可以把多个循环神经网络叠在一起,构成多层循环神经网络。比如,图\ref{fig:6-18}就展示基于两层循环神经网络的解码器和编码器结构。通常来说,层数越多模型的表示能力越强,因此在很多基于循环神经网络的机器翻译系统中一般会使用4$\sim$8层的网络。但是,过多的层也会增加模型训练的难度,甚至导致模型无法进行训练。第七章还会对这个问题进行深入讨论。
\parinterval 单层循环神经网络对输入序列进行了抽象,为了到更深入的抽象能力,可以把多个循环神经网络叠在一起,构成多层循环神经网络。比如,图\ref{fig:6-18}就展示基于两层循环神经网络的解码器和编码器结构。通常来说,层数越多模型的表示能力越强,因此在很多基于循环神经网络的机器翻译系统中一般会使用4$\sim$8层的网络。但是,过多的层也会增加模型训练的难度,甚至导致模型无法进行训练。第七章还会对这个问题进行深入讨论。
%----------------------------------------------
% 图3.10
......@@ -704,13 +704,13 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{注意力机制}\index{Chapter6.3.4}
\label{sec:6.3.4}
\parinterval 第二章提到过``上帝是不公平的'',这个观点主要是表达了:世界上事物之间的联系不是均匀的,有些事物之间的联系会很强,而其他的联系可能很弱。自然语言也完美的契合了这个观点。比如,再重新看一下前面提到的根据上下文补缺失单词的例子,
\parinterval 第二章提到过``上帝是不公平的'',这个观点主要是表达了:世界上事物之间的联系不是均匀的,有些事物之间的联系会很强,而其他的联系可能很弱。自然语言也完美地契合了这个观点。比如,再重新看一下前面提到的根据上下文补全缺失单词的例子,
\vspace{0.8em}
\centerline{中午\ \ 吃饭\ \ \ \ \ \ \ 下午\ 篮球\ \ \ 现在\ \ 饿\ \ \ \underline{\quad \quad \quad}}
\vspace{0.8em}
\noindent 之所以能想到在横线处填``吃饭''、``吃东西''很有可能是因为看到了``没\ 吃饭''、 ``很\ 饿''等关键信息。也就是这些关键的片段对预测缺失的单词起着关键性作用。而预测``吃饭''与前文中的`` 中午''、``又''之间的联系似乎不那么紧密。也就是说,在形成 ``吃饭''的逻辑时,在潜意识里会更注意``没吃饭''、``很饿''等关键信息。也就是我们的关注度并不是均匀分布在整个句子上的。
\noindent 之所以能想到在横线处填``吃饭''、``吃东西''很有可能是因为看到了``没\ 吃饭''、 ``很\ 饿''等关键信息。也就是这些关键的片段对预测缺失的单词起着关键性作用。而预测``吃饭''与前文中的`` 中午''、``又''之间的联系似乎不那么紧密。也就是说,在形成 ``吃饭''的逻辑时,在潜意识里会更注意``没吃饭''、``很饿''等关键信息。也就是我们的关注度并不是均匀分布在整个句子上的。
\parinterval 这个现象可以用注意力机制进行解释。注意力机制的概念来源于生物学的一些现象:当待接收的信息过多时,人类会选择性地关注部分信息而忽略其他信息。它在人类的视觉、听觉、嗅觉等方面均有体现,当我们在感受事物时,大脑会自动过滤或衰减部分信息,仅关注其中少数几个部分。例如,当我们看到图\ref{fig:6-19}时,往往不是``均匀地''看图像中的所有区域,可能最先注意到的是大狗头上带的的帽子,然后才会关注图片中其他部分。
......@@ -747,7 +747,7 @@ $\textrm{P}({y_j | \mathbf{s}_{j-1} ,y_{j-1},\mathbf{C}})$由Softmax实现,Sof
\end{figure}
%----------------------------------------------
\parinterval 显然,以上的问题的根本原因在于所使用的表示模型还比较``弱''。因此需要一个更强大的表示模型,在生成目标语单词时能够有选择的获取源语言句子中的更有用的部分。更准确的说,对于要生成的目标语单词,相关性更高的源语言片段应该在源语言句子的表示中体现出来,而不是将所有的源语言单词一视同仁。在神经机器翻译中引入注意力机制正是为了达到这个目的\cite{bahdanau2014neural}\cite{DBLP:journals/corr/LuongPM15}。实际上,除了机器翻译,注意力机制也被成功应用于图像处理、语音识别、自然语言处理的其他任务。而正是注意力机制的引入,使得包括机器翻译在内很多自然语言处理系统得到了新的飞跃。
\parinterval 显然,以上的问题的根本原因在于所使用的表示模型还比较``弱''。因此需要一个更强大的表示模型,在生成目标语单词时能够有选择的获取源语言句子中的更有用的部分。更准确的说,对于要生成的目标语单词,相关性更高的源语言片段应该在源语言句子的表示中体现出来,而不是将所有的源语言单词一视同仁。在神经机器翻译中引入注意力机制正是为了达到这个目的\cite{bahdanau2014neural}\cite{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-21}对比了未引入注意力机制和引入了注意力机制的编码器-解码器结构。可以看出,在注意力模型中,对于每一个目标单词的生成,都会额外引入一个单独的上下文向量参与运算。
......@@ -865,7 +865,7 @@ a (\mathbf{s},\mathbf{h}) = \left\{ \begin{array}{ll}
%%%%%%%%%%%%%%%%%%
\subsubsection{注意力机制的解读}\index{Chapter6.3.4.3}
\label{sec:6.3.4.3}
\parinterval 从前面的描述可以看出,注意力机制在机器翻译中就是要回答一个问题:给定一个目标语位置$j$和一系列源语言的不同位置上的表示\{${\mathbf{h}_i}$\},如何得到一个新的表示$\hat{\mathbf{h}}$,使得它与目标语位置$j$对应最好?
\parinterval 从前面的描述可以看出,注意力机制在机器翻译中就是要回答一个问题:给定一个目标语位置$j$和一系列源语言的不同位置上的表示\{${\mathbf{h}_i}$\},如何得到一个新的表示$\hat{\mathbf{h}}$,使得它与目标语位置$j$对应最好?
\parinterval 那么,如何理解这个过程?注意力机制的本质又是什么呢?换一个角度来看,实际上,目标语位置$j$本质上是一个查询,我们希望从源语言端找到与之最匹配的源语言位置,并返回相应的表示结果。为了描述这个问题,可以建立一个查询系统。假设有一个库,里面包含若干个$\mathrm{key}$-$\mathrm{value}$单元,其中$\mathrm{key}$代表这个单元的索引关键字,$\mathrm{value}$代表这个单元的值。比如,对于学生信息系统,$\mathrm{key}$可以是学号,$\mathrm{value}$可以是学生的身高。当输入一个查询$\mathrm{query}$,我们希望这个系统返回与之最匹配的结果。也就是,希望找到匹配的$\mathrm{key}$,并输出其对应的$\mathrm{value}$。比如,当查询某个学生的身高信息时,可以输入学生的学号,之后在库中查询与这个学号相匹配的记录,并把这个记录中的$\mathrm{value}$(即身高)作为结果返回。
......@@ -929,7 +929,7 @@ a (\mathbf{s},\mathbf{h}) = \left\{ \begin{array}{ll}
\parinterval 将公式\ref{eqC6.29}应用于神经机器翻译有几个基本问题需要考虑:1)损失函数的选择;2)参数初始化的策略,也就是如何设置$\mathbf{w}_0$;3)优化策略和学习率调整策略;4)训练加速。下面对这些问题进行讨论。
%%%%%%%%%%%%%%%%%%
\subsubsection{损失函数}\index{Chapter6.3.5.1}
\parinterval 因为神经机器翻译在每个目标语位置都会输出一个概率分布,表示这个位置上不同单词出现的可能性,因此需要知道当前位置输出的分布相比于标准答案的``损失''。对于这个问题,常用的是交叉熵损失函数。令$\mathbf{y}$表示机器翻译模型输出的分布,$\hat{\mathbf{y}}$ 表示标准答案,则交叉熵损失可以被定义为$L_{\textrm{ce}}(\mathbf{y},\hat{\mathbf{y}}) = - \sum_{k=1}^{|V|} \mathbf{y}[k] \textrm{log} (\hat{\mathbf{y}}[k])$,其中$\mathbf{y}[k]$$\hat{\mathbf{y}}[k]$分别表示向量$\mathbf{y}$$\hat{\mathbf{y}}$的第$k$维,$|V|$表示输出向量维度(等于词表大小)。对于一个模型输出的概率分布$\mathbf{Y} = \{ \mathbf{y}_1,\mathbf{y}_2,..., \mathbf{y}_n \}$和标准答案分布$\widehat{\mathbf{Y}}=\{ \hat{\mathbf{y}}_1, \hat{\mathbf{y}}_2,...,\hat{\mathbf{y}}_n \}$,损失函数可以被定义为
\parinterval 因为神经机器翻译在每个目标语位置都会输出一个概率分布,表示这个位置上不同单词出现的可能性,因此需要知道当前位置输出的分布相比于标准答案的``损失''。对于这个问题,常用的是交叉熵损失函数。令$\mathbf{y}$表示机器翻译模型输出的分布,$\hat{\mathbf{y}}$ 表示标准答案,则交叉熵损失可以被定义为$L_{\textrm{ce}}(\mathbf{y},\hat{\mathbf{y}}) = - \sum_{k=1}^{|V|} \mathbf{y}[k] \textrm{log} (\hat{\mathbf{y}}[k])$,其中$\mathbf{y}[k]$$\hat{\mathbf{y}}[k]$分别表示向量$\mathbf{y}$$\hat{\mathbf{y}}$的第$k$维,$|V|$表示输出向量维度(等于词表大小)。对于一个模型输出的概率分布$\mathbf{Y} = \{ \mathbf{y}_1,\mathbf{y}_2,..., \mathbf{y}_n \}$和标准答案分布$\widehat{\mathbf{Y}}=\{ \hat{\mathbf{y}}_1, \hat{\mathbf{y}}_2,...,\hat{\mathbf{y}}_n \}$,损失函数可以被定义为
%-------------
\begin{eqnarray}
L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\hat{\mathbf{y}}_j)
......@@ -938,7 +938,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\parinterval 公式\ref{eqC6.30}是一种非常通用的损失函数形式,除了交叉熵,也可以使用其他的损失函数,这时只需要替换$L_{ce} (\cdot)$即可。这里使用交叉熵损失函数的好处在于,它非常容易优化,特别是与Softmax组合,其反向传播的实现非常高效。此外,交叉熵损失(在一定条件下)也对应了极大似然的思想,这种方法在自然语言处理中已经被证明是非常有效的。
\parinterval 除了交叉熵,很多系统也使用了面向评价的损失函数,比如,直接利用评价指标BLEU定义损失函数。不过这类损失函数往往不可微分,因此无法直接获取梯度。这时可以引入强化学习技术,通过策略梯度等方法进行优化。不过这类方法需要采样等手段,这里不做重点讨论,相关内容会在后面前言技术部分进行介绍。
\parinterval 除了交叉熵,很多系统也使用了面向评价的损失函数,比如,直接利用评价指标BLEU定义损失函数。不过这类损失函数往往不可微分,因此无法直接获取梯度。这时可以引入强化学习技术,通过策略梯度等方法进行优化。不过这类方法需要采样等手段,这里不做重点讨论,相关内容会在后面技术部分进行介绍。
%%%%%%%%%%%%%%%%%%
\subsubsection{长参数初始化}\index{Chapter6.3.5.2}
\parinterval 神经网络的参数主要是各层中的线性变换矩阵和偏置。在训练开始时,需要对参数进行初始化。但是,由于神经机器翻译的网络结构复杂,因此损失函数往往不是凸函数,不同初始化会导致不同的优化结果。而且在大量实践中已经发现,神经机器翻译模型对初始化方式非常敏感,性能优异的系统往往需要特定的初始化方式。
......@@ -990,7 +990,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\noindent 其中$\gamma$是手工设定的梯度大小阈值, $\| \cdot \|_2$是L2范数,$\mathbf{w}'$表示梯度裁剪后的参数。这个公式的含义在于只要梯度大小超过阈值,就按照阈值与当前梯度大小的比例进行放缩。
%%%%%%%%%%%%%%%%%%
\subsubsection{学习率策略}\index{Chapter6.3.5.5}
\parinterval 在公式\ref{eqC6.29}中, $\alpha$决定了每次参数更新时更新的步幅大小,称之为{\small\bfnew{学习率}}(Learning Rate)。学习率作为基于梯度方法中的重要超参数,它决定目标函数能否收敛到较好的局部最优点以及收敛的速度。合理的学习率能够使模型快速、稳定达到较好的状态。但是,如果学习率太小,收敛过程会很慢;而学习率太大,则模型的状态可能会出现震荡,很难达到稳定,甚至使模型无法收敛。图\ref{fig:6-27} 对比了不同学习率对损失函数的影响。
\parinterval 在公式\ref{eqC6.29}中, $\alpha$决定了每次参数更新时更新的步幅大小,称之为{\small\bfnew{学习率}}(Learning Rate)。学习率作为基于梯度方法中的重要超参数,它决定目标函数能否收敛到较好的局部最优点以及收敛的速度。合理的学习率能够使模型快速、稳定达到较好的状态。但是,如果学习率太小,收敛过程会很慢;而学习率太大,则模型的状态可能会出现震荡,很难达到稳定,甚至使模型无法收敛。图\ref{fig:6-27} 对比了不同学习率对损失函数的影响。
%----------------------------------------------
% 图3.10
......@@ -1058,7 +1058,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{figure}
%----------------------------------------------
\item {\small\bfnew{模型并行}}。另一种思路是,把较大的模型分成若干小模型,之后在不同设备上训练小模型。对于循环神经网络,不同层的网络天然就是一个相对独立的模型,因此非常适合使用这种方法。比如,对于$l$层的循环神经网络,把每层都看做一个小模型,然后分发到$l$个设备上并行计算。在序列较长的时候,该方法使其运算时间变为原来的${1}/{l}$。图\ref{fig:6-30}以三层循环网络为例展示了对句子``你\ \ 不错\ 。''进行模型并行的过程。其中,每一层网络都被放到了一个设备上。当模型根据已经生成的第一个词``你''预测下一个词时(图\ref{fig:6-30}(a)),同层的下一个时刻的计算和对``你''的第二层的计算就可以同时开展(图\ref{fig:6-30}(b))。以此类推,就完成了模型的并行计算。
\item {\small\bfnew{模型并行}}。另一种思路是,把较大的模型分成若干小模型,之后在不同设备上训练小模型。对于循环神经网络,不同层的网络天然就是一个相对独立的模型,因此非常适合使用这种方法。比如,对于$l$层的循环神经网络,把每层都看做一个小模型,然后分发到$l$个设备上并行计算。在序列较长的时候,该方法使其运算时间变为原来的${1}/{l}$。图\ref{fig:6-30}以三层循环网络为例展示了对句子``你\ \ 不错\ 。''进行模型并行的过程。其中,每一层网络都被放到了一个设备上。当模型根据已经生成的第一个词``你''预测下一个词时(图\ref{fig:6-30}(a)),同层的下一个时刻的计算和对``你''的第二层的计算就可以同时开展(图\ref{fig:6-30}(b))。以此类推,就完成了模型的并行计算。
\end{itemize}
%-------------------------------------------
......@@ -1171,7 +1171,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\label{eqC6.37}
\end{eqnarray}
\noindent 其中,$|\mathbf{y}|$代表已经得到的译文长度,$\alpha$是一个固定的常数,用于控制惩罚的强度。同时在句子得分的计算时,额外引入覆盖度的因子,如下:
\noindent 其中,$|\mathbf{y}|$代表已经得到的译文长度,$\alpha$是一个固定的常数,用于控制惩罚的强度。同时在计算句子得分时,额外引入覆盖度的因子,如下:
\begin{eqnarray}
\textrm{cp}(\mathbf{y} , \mathbf{x}) = \beta \cdot \sum_{i=1}^{|\mathbf{x}|} \textrm{log} \big(\textrm{min}(\sum_j^{|\mathbf{y}|} \alpha_{ij},1 ) \big)
......@@ -1193,7 +1193,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\subsection{实例-GNMT}\index{Chapter6.3.7}
\parinterval 循环神经网络在机器翻译中有很多成功的应用,比如、RNNSearch\cite{bahdanau2014neural}、Nematus\cite{DBLP:journals/corr/SennrichFCBHHJL17}等系统就被很多研究者作为实验系统。在众多基于循环神经网络的系统中,Google's Neural Machine Translation System(GNMT)系统是非常成功的一个\cite{Wu2016GooglesNM}。GNMT是谷歌2016年发布的神经机器翻译系统。当时,神经机器翻译有三个弱点:训练和推理速度较慢、在翻译稀有单词上缺乏鲁棒性和有时无法完整翻译源语言句子中的所有单词。GNMT的提出有效的缓解了上述问题。
\parinterval GNMT使用了编码器解码器结构,构建了一个8层的深度网络,每层网络均由LSTM组成,且在编码器解码器之间使用了多层注意力连接。其结构如图\ref{fig:6-59},编码器只有最下面2层为双向LSTM。GNMT在束搜索中也加入了长度惩罚和覆盖度因子来确保输出高质量的翻译结果(公式\ref{eqC6.39})。
\parinterval GNMT使用了编码器-解码器结构,构建了一个8层的深度网络,每层网络均由LSTM组成,且在编码器-解码器之间使用了多层注意力连接。其结构如图\ref{fig:6-59},编码器只有最下面2层为双向LSTM。GNMT在束搜索中也加入了长度惩罚和覆盖度因子来确保输出高质量的翻译结果(公式\ref{eqC6.39})。
%----------------------------------------------
% 图3.10
......@@ -1230,9 +1230,9 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\parinterval 编码器-解码器框架提供了一个非常灵活的机制,因为开发者只需要设计编码器和解码器的结构就能完成机器翻译。但是,架构的设计是深度学习中最具挑战的工作,优秀的架构往往需要长时间的探索和大量的实验验证,而且还需要一点点``灵感''。
\parinterval 前面介绍的基于循环神经网络的翻译模型和注意力机制就是研究人员通过长期的实践发现的神经网络架构。除了神经机器翻译,它们也被广泛应用于语音处理、图像处理等领域。虽然循环神经网络很强大,但是人们也发现了一些弊端。一个突出的问题是,循环神经网络每个循环单元都有向前依赖性,也就是当前时间步的处理依赖前一时间步处理的结果。这个性质可以使序列的``历史''信息不断被传递,但是也造成模型运行效率的下降。特别是对于自然语言处理任务,序列往往较长,无论是传统的RNN结构,还是更为复杂的LSTM结构,都需要很多次循环单元的处理才能够捕捉到单词之间的长距离依赖。由于需要多个循环单元的处理,距离较远的两个单词之间的信息传递变得很复杂。
\parinterval 前面介绍的基于循环神经网络的翻译模型和注意力机制就是研究人员通过长期的实践发现的神经网络架构。除了神经机器翻译,它们也被广泛应用于语音处理、图像处理等领域。虽然循环神经网络很强大,但是人们也发现了一些弊端。一个突出的问题是,循环神经网络每个循环单元都有向前依赖性,也就是当前时间步的处理依赖前一时间步处理的结果。这个性质可以使序列的``历史''信息不断被传递,但是也造成模型运行效率的下降。特别是对于自然语言处理任务,序列往往较长,无论是传统的RNN结构,还是更为复杂的LSTM结构,都需要很多次循环单元的处理才能够捕捉到单词之间的长距离依赖。由于需要多个循环单元的处理,距离较远的两个单词之间的信息传递变得很复杂。
\parinterval 针对这些问题,谷歌的研究人员提出了一种全新的模型$\ \dash\ $Transformer\cite{NIPS2017_7181}。与循环神经网络等传统模型不同,Transformer模型仅仅使用一种被称作自注意力机制的模型和标准的前馈神经网络,完全不依赖任何循环单元或者卷积操作。自注意力机制的优点在于可以直接对序列中任意两个单元之间的关系进行建模,这使得长距离依赖等问题可以更好被求解。此外,自注意力机制非常适合在GPU 上进行并行化,因此模型训练的速度更快。表\ref{tab:rnn vs cnn vs trf}对比了RNN、CNN、Transformer三种模型的时间复杂度。
\parinterval 针对这些问题,谷歌的研究人员提出了一种全新的模型$\ \dash\ $Transformer\cite{NIPS2017_7181}。与循环神经网络等传统模型不同,Transformer模型仅仅使用一种被称作自注意力机制的模型和标准的前馈神经网络,完全不依赖任何循环单元或者卷积操作。自注意力机制的优点在于可以直接对序列中任意两个单元之间的关系进行建模,这使得长距离依赖等问题可以更好被求解。此外,自注意力机制非常适合在GPU 上进行并行化,因此模型训练的速度更快。表\ref{tab:rnn vs cnn vs trf}对比了RNN、CNN、Transformer三种模型的时间复杂度。
%----------------------------------------------
% 表
......@@ -1250,7 +1250,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{table}
%--------------------------------------
\parinterval 在Transformer被提出之后,很快就席卷了整个自然语言处理领域。实际上,Transformer也可以当作一种表示模型,因此也被大量的使用在自然语言处理的其他领域,甚至图像处理和语音处理中也能看到它的影子。比如,目前非常流行的BERT等预训练模型就是基于Transformer。表\ref{tab:performence form different models}展示了Transformer在WMT英德和英法机器翻译任务上的性能。它能用更少的计算量(FLOPS)达到比其他模型更好的翻译品质\footnote{FLOPS = floating-point operations per second,即每秒浮点运算次数。它是度量计算机运算规模的常用单位}
\parinterval Transformer在被提出之后,很快就席卷了整个自然语言处理领域。实际上,Transformer也可以当作一种表示模型,因此也被大量地使用在自然语言处理的其他领域,甚至图像处理和语音处理中也能看到它的影子。比如,目前非常流行的BERT等预训练模型就是基于Transformer。表\ref{tab:performence form different models}展示了Transformer在WMT英德和英法机器翻译任务上的性能。它能用更少的计算量(FLOPS)达到比其他模型更好的翻译品质\footnote{FLOPS = floating-point operations per second,即每秒浮点运算次数。它是度量计算机运算规模的常用单位}
%----------------------------------------------
% 表
......@@ -1271,7 +1271,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{table}
%--------------------------------------
\parinterval 注意,Transformer并不简单等同于自注意力机制。Transformer模型还包含了很多优秀的技术,比如:多头注意力、新的训练学习率调整策略等等。这些因素一起组成了真正的Transformer。下面就一起看一看自注意力机制和Transformer是如何工作的。
\parinterval 注意,Transformer并不简单等同于自注意力机制。Transformer模型还包含了很多优秀的技术,比如:多头注意力、新的训练学习率调整策略等等。这些因素一起组成了真正的Transformer。下面就一起看一看自注意力机制和Transformer是如何工作的。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{自注意力模型}\index{Chapter6.4.1}
......@@ -1288,7 +1288,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{figure}
%----------------------------------------------
\parinterval 那么能否摆脱这种顺序传递信息的方式,直接对不同位置单词之间的关系进行建模,即将信息传递的距离拉近为1?{\small\sffamily\bfseries{自注意力机制}}(Self-Attention)的提出便有效解决了这个问题\cite{DBLP:journals/corr/LinFSYXZB17}。图\ref{fig:6-35}给出了自注意力机制对序列进行建模的示例。对于单词$w_m$,自注意力机制直接建立它与前$m-1$个单词之间的关系。也就是说,$w_m$与序列中所有其他单词的距离都是1。这种方式很好解决了长距离依赖问题,同时由于单词之间的联系都是相互独立的,因此也大大提高了模型的并行度。
\parinterval 那么能否摆脱这种顺序传递信息的方式,直接对不同位置单词之间的关系进行建模,即将信息传递的距离拉近为1?{\small\sffamily\bfseries{自注意力机制}}(Self-Attention)的提出便有效解决了这个问题\cite{DBLP:journals/corr/LinFSYXZB17}。图\ref{fig:6-35}给出了自注意力机制对序列进行建模的示例。对于单词$w_m$,自注意力机制直接建立它与前$m-1$个单词之间的关系。也就是说,$w_m$与序列中所有其他单词的距离都是1。这种方式很好解决了长距离依赖问题,同时由于单词之间的联系都是相互独立的,因此也大大提高了模型的并行度。
%----------------------------------------------
% 图3.10
......@@ -1365,7 +1365,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-38}简单了解一下Transformer模型是如何进行翻译的。首先,Transformer将源语``我\ \ 好''的{\small\bfnew{词嵌入}}(Word Embedding)融合{\small\bfnew{位置编码}}(Position Embedding)后作为输入。然后,编码器对输入的源语言句子进行逐层抽象,得到包含丰富的上下文信息的源语表示并传递给解码器。解码器的每一层,使用自注意力子层对输入的解码端表示进行加工,之后再使用编码-解码注意力子层融合源语言句子的表示信息。就这样逐词生成目标语译文单词序列。解码器的每个位置的输入是当前单词(比如,``I''),而这个位置输出是下一个单词(比如,``am''),这个设计和标准的神经语言模型是完全一样的。
......@@ -1457,7 +1457,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\parinterval 具体来看,在注意力机制的计算过程中,包含三个重要的参数,分别是Query,\\Key和Value。在下面的描述中,分别用$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$对它们进行表示,其中$\mathbf{Q}$$\mathbf{K}$的维度为$L\times d_k$$\mathbf{V}$的维度为$L\times d_v$。这里,$L$为序列的长度,$d_k$$d_v$分别表示每个Key和Value的大小,通常设置为$d_k=d_v=d_{model}$
\parinterval 在自注意力机制中,$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$都是相同的,对应着源语言或目标语言的表示。而在编码解码注意力机制中,由于要对双语之间的信息进行建模,因此,将目标语每个位置的表示视为编码-解码注意力机制的$\mathbf{Q}$,源语言句子的表示视为$\mathbf{K}$$\mathbf{V}$
\parinterval 在自注意力机制中,$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$都是相同的,对应着源语言或目标语言的表示。而在编码-解码注意力机制中,由于要对双语之间的信息进行建模,因此,将目标语每个位置的表示视为编码-解码注意力机制的$\mathbf{Q}$,源语言句子的表示视为$\mathbf{K}$$\mathbf{V}$
\parinterval 在得到$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$后,便可以进行注意力机制的运算,这个过程可以被形式化为:
......@@ -1482,7 +1482,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{figure}
%----------------------------------------------
\parinterval 下面举个简单的例子介绍点乘注意力的具体计算过程。如图\ref{fig:6-44}所示,用黄色、蓝色和橙色的矩阵分别表示$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$中的每一个小格都对应一个单词在模型中的表示(即一个向量)。首先,通过点乘、放缩、掩码等操作得到相关性矩阵,即粉色部分。其次,将得到的中间结果矩阵(粉色)的每一行使用Softmax激活函数进行归一化操作,得到最终的权重矩阵,也就是图中的红色矩阵。红色矩阵中的每一行都对应一个注意力分布。最后,按行对$\mathbf{V}$进行加权求和,便得到了每个单词通过点乘注意力机制计算得到的表示。这里面,主要的计算消耗是两次矩阵乘法,即$\mathbf{Q}$$\mathbf{K}^{T}$的乘法、相关性矩阵和$\mathbf{V}$的乘法。这两个操作都可以在GPU上高效完成,因此可以一次性计算出序列中所有单词之间的注意力权重,并完成所有位置表示的加权求和过程,这样大大提高了模型的计算速度。
\parinterval 下面举个简单的例子介绍点乘注意力的具体计算过程。如图\ref{fig:6-44}所示,用黄色、蓝色和橙色的矩阵分别表示$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$中的每一个小格都对应一个单词在模型中的表示(即一个向量)。首先,通过点乘、放缩、掩码等操作得到相关性矩阵,即粉色部分。其次,将得到的中间结果矩阵(粉色)的每一行使用Softmax激活函数进行归一化操作,得到最终的权重矩阵,也就是图中的红色矩阵。红色矩阵中的每一行都对应一个注意力分布。最后,按行对$\mathbf{V}$进行加权求和,便得到了每个单词通过点乘注意力机制计算得到的表示。这里面,主要的计算消耗是两次矩阵乘法,即$\mathbf{Q}$$\mathbf{K}^{T}$的乘法、相关性矩阵和$\mathbf{V}$的乘法。这两个操作都可以在GPU上高效完成,因此可以一次性计算出序列中所有单词之间的注意力权重,并完成所有位置表示的加权求和过程,这样大大提高了模型的计算速度。
%----------------------------------------------
% 图3.10
......@@ -1518,14 +1518,14 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\subsection{多头注意力}\index{Chapter6.4.6}
\parinterval Transformer中使用的另一项重要技术是{\small\sffamily\bfseries{多头注意力}}(Multi-head Attention)。``多头''可以理解成将原来的$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$按照隐层维度平均切分成多份。假设切分$h$份,那么最终会得到$\mathbf{Q} = \{ \mathbf{q}_1, \mathbf{q}_2,...,\mathbf{q}_h \}$$\mathbf{K}=\{ \mathbf{k}_1,\mathbf{k}_2,...,\mathbf{k}_h \}$$\mathbf{V}=\{ \mathbf{v}_1, \mathbf{v}_2,...,\mathbf{v}_h \}$。多头注意力机制就是用每一个切分得到的$\mathbf{q}$$\mathbf{k}$$\mathbf{v}$独立的进行注意力计算。即第$i$个头的注意力计算结果$\mathbf{head}_i = \textrm{Attention}(\mathbf{q}_i,\mathbf{k}_i, \mathbf{v}_i)$
\parinterval 下面根据\ref{fig:6-46}详细介绍多头注意力的计算过程:
\parinterval 下面根据图\ref{fig:6-46}详细介绍多头注意力的计算过程:
\begin{itemize}
\item 首先将$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$分别通过线性变换的方式映射为$h$个子集(机器翻译任务中,$h$一般为8)。即$\mathbf{q}_i = \mathbf{Q}\mathbf{W}_i^Q $$\mathbf{k}_i = \mathbf{K}\mathbf{W}_i^K $$\mathbf{v}_i = \mathbf{V}\mathbf{W}_i^V $,其中$i$表示第$i$个头, $\mathbf{W}_i^Q \in \mathbb{R}^{d_{model} \times d_k}$, $\mathbf{W}_i^K \in \mathbb{R}^{d_{model} \times d_k}$, $\mathbf{W}_i^V \in \mathbb{R}^{d_{model} \times d_v}$是参数矩阵; $d_k=d_v=d_{model} / h$,对于不同的头采用不同的变换矩阵,这里$d_{model}$是Transformer的一个参数,表示每个隐层向量的维度;
\item 首先将$\mathbf{Q}$$\mathbf{K}$$\mathbf{V}$分别通过线性变换的方式映射为$h$个子集(机器翻译任务中,$h$一般为8)。即$\mathbf{q}_i = \mathbf{Q}\mathbf{W}_i^Q $$\mathbf{k}_i = \mathbf{K}\mathbf{W}_i^K $$\mathbf{v}_i = \mathbf{V}\mathbf{W}_i^V $,其中$i$表示第$i$个头, $\mathbf{W}_i^Q \in \mathbb{R}^{d_{model} \times d_k}$, $\mathbf{W}_i^K \in \mathbb{R}^{d_{model} \times d_k}$, $\mathbf{W}_i^V \in \mathbb{R}^{d_{model} \times d_v}$是参数矩阵; $d_k=d_v=d_{model} / h$,对于不同的头采用不同的变换矩阵,这里$d_{model}$是Transformer的一个参数,表示每个隐层向量的维度;
\item 其次对每个头分别执行点乘注意力操作,得到每个头的注意力操作的输出$\mathbf{head}_i$
\item 最后将$h$个头的注意力输出在最后一维$d_v$进行拼接(Concat)重新得到维度为$h \times d_v$的输出,并通过对其左乘一个权重矩阵$\mathbf{W}^o$进行线性变换,从而对多头计算得到的信息进行融合同时将多头注意力输出的维度映射为模型的隐层大小(即$d_{model}$),这里参数矩阵$\mathbf{W}^o \in \mathbb{R}^{h \times d_v \times d_{model}}$
\item 最后将$h$个头的注意力输出在最后一维$d_v$进行拼接(Concat)重新得到维度为$h \times d_v$的输出,并通过对其左乘一个权重矩阵$\mathbf{W}^o$进行线性变换,从而对多头计算得到的信息进行融合,且将多头注意力输出的维度映射为模型的隐层大小(即$d_{model}$),这里参数矩阵$\mathbf{W}^o \in \mathbb{R}^{h \times d_v \times d_{model}}$
\end{itemize}
%----------------------------------------------
......@@ -1717,7 +1717,7 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^{6}$
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{推断}\index{Chapter6.4.10}
\parinterval Transformer解码器生成目标语的过程和前面介绍的循环网络翻译模型类似,都是从左往右生成,且下一个单词的预测依赖已经生成的上一个单词。其具体推断过程如图\ref{fig:6-54}所示,其中$\mathbf{C}_i$是编解码注意力的结果,解码器首先根据``<eos>''和$\mathbf{C}_1$生成第一个单词``how'',然后根据``how''和$\mathbf{C}_2$生成第二个单词``are'',以此类推,当解码器生成``<eos>''时结束推断。
\parinterval Transformer解码器生成目标语的过程和前面介绍的循环网络翻译模型类似,都是从左往右生成,且下一个单词的预测依赖已经生成的上一个单词。其具体推断过程如图\ref{fig:6-54}所示,其中$\mathbf{C}_i$是编-解码注意力的结果,解码器首先根据``<eos>''和$\mathbf{C}_1$生成第一个单词``how'',然后根据``how''和$\mathbf{C}_2$生成第二个单词``are'',以此类推,当解码器生成``<eos>''时结束推断。
\parinterval 但是,Transformer在推断阶段无法对所有位置进行并行化操作,因为对于每一个目标语单词都需要对前面所有单词进行注意力操作,因此它推断速度非常慢。可以采用的加速手段有:低精度\cite{DBLP:journals/corr/CourbariauxB16}、Cache(缓存需要重复计算的变量)\cite{DBLP:journals/corr/abs-1805-00631}、共享注意力网络等\cite{Xiao2019SharingAW}。关于Transformer模型的推断技术将会在第七章进一步深入介绍。
......@@ -1755,7 +1755,7 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^{6}$
%---------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{文言文翻译}\index{Chapter6.5.3}
\parinterval 文言文翻译,即能够根据输入的文言文,输出相应的现代汉语翻译。中国几千年的文化都是用文言文记载的,不同时代的古文之间存在巨大差异,普通人在阅读古籍时会面临很大困难。为此,有研究者致力于将古籍翻译成现代汉语。实际上,文言文翻译也是机器翻译的一个典型应用。想要训练一个文言文翻译系统并不难,只需要将文言文看作源语言,将现代文看作目标语言,并送入机器翻译模型,就可以获得一个古文翻译系统。不过,由于古文短,现代文长,过翻译或欠翻译等问题会在机器翻译中表现得更为突出。在此,如果想要获得一个性能优异的文言文翻译系统,就需要考虑如何对长度进行更精准的建模。另外,不同时代语言差异性大,因此还需要能够进行自动适应和风格迁移。下图展示了使用神经机器翻译模型得到的文言文翻译系统的实例。输入古文,系统就能生成其现代文翻译。当然,也可以用类似的方法训练现代文-古文的翻译系统。
\parinterval 文言文翻译,即能够根据输入的文言文,输出相应的现代汉语翻译。中国几千年的文化都是用文言文记载的,不同时代的古文之间存在巨大差异,普通人在阅读古籍时会面临很大困难。为此,有研究者致力于将古籍翻译成现代汉语。实际上,文言文翻译也是机器翻译的一个典型应用。想要训练一个文言文翻译系统并不难,只需要将文言文看作源语言,将现代文看作目标语言,并送入机器翻译模型,就可以获得一个古文翻译系统。不过,由于古文短,现代文长,过翻译或欠翻译等问题会在古文翻译中表现得更为突出。在此,如果想要获得一个性能优异的文言文翻译系统,就需要考虑如何对长度进行更精准的建模。另外,不同时代语言差异性大,因此还需要能够进行自动适应和风格迁移。下图展示了使用神经机器翻译模型得到的文言文翻译系统的实例。输入古文,系统就能生成其现代文翻译。当然,也可以用类似的方法训练现代文-古文的翻译系统。
%----------------------------------------------
% 图3.6.1
\begin{figure}[htp]
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论