Commit ece9ca21 by 曹润柘

合并分支 'caorunzhe' 到 'master'

Caorunzhe

查看合并请求 !160
parents 9b486346 76111d72
...@@ -970,7 +970,7 @@ a (\mathbf{s},\mathbf{h}) = \left\{ \begin{array}{ll} ...@@ -970,7 +970,7 @@ a (\mathbf{s},\mathbf{h}) = \left\{ \begin{array}{ll}
\label{eq:6-30} \label{eq:6-30}
\end{eqnarray} \end{eqnarray}
\noindent 其中,$\mathbf{w}_{step}$表示更新前的模型参数,$\mathbf{w}_{step+1}$表示更新后的模型参数,$L(\mathbf{w}_{step})$表示模型相对于$\mathbf{w}_{step}$的损失,$\frac{\partial L(\mathbf{w}_{step})} {\partial \mathbf{w}_{step} }$表示损失函数的梯度,$\alpha$是更新的步进值。也就是说,给定一定量的训练数据,不断运行公式\ref{eq:6-30}的过程。而训练数据也可以反复使用,直至模型参数达到收敛或者损失函数不再变化。通常,把公式的一次执行称为``一步''更新/训练,把访问完所有样本的训练称为``一轮''训练。 \noindent 其中,$\mathbf{w}_{step}$表示更新前的模型参数,$\mathbf{w}_{step+1}$表示更新后的模型参数,$L(\mathbf{w}_{step})$表示模型相对于$\mathbf{w}_{step}$的损失,$\frac{\partial L(\mathbf{w}_{step})} {\partial \mathbf{w}_{step} }$表示损失函数的梯度,$\alpha$是更新的步进值。也就是说,给定一定量的训练数据,不断执行公式\ref{eq:6-30}的过程。反复使用训练数据,直至模型参数达到收敛或者损失函数不再变化。通常,把公式的一次执行称为``一步''更新/训练,把访问完所有样本的训练称为``一轮''训练。
\parinterval 将公式\ref{eq:6-30}应用于神经机器翻译有几个基本问题需要考虑:1)损失函数的选择;2)参数初始化的策略,也就是如何设置$\mathbf{w}_0$;3)优化策略和学习率调整策略;4)训练加速。下面对这些问题进行讨论。 \parinterval 将公式\ref{eq:6-30}应用于神经机器翻译有几个基本问题需要考虑:1)损失函数的选择;2)参数初始化的策略,也就是如何设置$\mathbf{w}_0$;3)优化策略和学习率调整策略;4)训练加速。下面对这些问题进行讨论。
...@@ -1024,7 +1024,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1024,7 +1024,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\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}进行综合考虑,计算出更新步长。 \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}进行综合考虑,计算出更新步长。
\parinterval\ref{tab:6-8}从效果上对比了Adam和SGD的区别。通常,Adam收敛的比较快,不同任务基本上可以使用一套配置进行优化,虽性能不算差,但很难达到最优效果。相反,SGD虽能通过在不同的数据集上进行调整,来达到最优的结果,但是收敛速度慢。因此需要根据不同的需求来选择合适的优化器。若需要快得到模型的初步结果,选择Adam较为合适,若是需要在一个任务上得到最优的结果,选择SGD更为合适。 \parinterval\ref{tab:6-8}从效果上对比了Adam和SGD的区别。通常,Adam收敛的比较快,不同任务基本上可以使用一套配置进行优化,虽性能不算差,但很难达到最优效果。相反,SGD虽能通过在不同的数据集上进行调整,来达到最优的结果,但是收敛速度慢。因此需要根据不同的需求来选择合适的优化器。若需要快得到模型的初步结果,选择Adam较为合适,若是需要在一个任务上得到最优的结果,选择SGD更为合适。
%---------------------------------------------- %----------------------------------------------
\begin{table}[htp] \begin{table}[htp]
...@@ -1096,7 +1096,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1096,7 +1096,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\subsubsection{并行训练} \subsubsection{并行训练}
\parinterval 机器翻译是自然语言处理中很``重''的任务。因为数据量巨大而且模型较为复杂,模型训练的时间往往很长。比如,使用一千万句的训练数据,性能优异的系统往往需要几天甚至一周的时间。更大规模的数据会导致训练时间更长。特别是使用多层网络同时增加模型容量时(比如增加隐层宽度)时,神经机器翻译的训练会更加缓慢。对于这个问题,一个思路是从模型训练算法上进行改进。比如前面提到的Adam就是一种高效的训练策略。另一种思路是利用多设备进行加速,也称作分布式训练。 \parinterval 机器翻译是自然语言处理中很``重''的任务。因为数据量巨大而且模型较为复杂,模型训练的时间往往很长。比如,使用一千万句的训练数据,性能优异的系统往往需要几天甚至一周的时间。更大规模的数据会导致训练时间更长。特别是使用多层网络同时增加模型容量时(比如增加隐层宽度时),神经机器翻译的训练会更加缓慢。对于这个问题,一个思路是从模型训练算法上进行改进。比如前面提到的Adam就是一种高效的训练策略。另一种思路是利用多设备进行加速,也称作分布式训练。
%---------------------------------------------- %----------------------------------------------
\begin{table}[htp] \begin{table}[htp]
...@@ -1157,7 +1157,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1157,7 +1157,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\label{eq:6-35} \label{eq:6-35}
\end{eqnarray} \end{eqnarray}
\noindent 在具体实现时,由于当前目标语单词的生成需要依赖前面单词的生成,因此无法同时生成所有的目标语单词。理论上,可以枚举所有的$\mathbf{y}$,之后利用$\textrm{P}(\mathbf{y} | \mathbf{x})$ 的定义对每个$\mathbf{y}$进行评价,然后找出最好的$\mathbf{y}$。这也被称作{\small\bfnew{全搜索}}\index{全搜索}(Full Search)\index{Full Search}。但是,枚举所有的译文单词序列显然是不现实的。因此,在具体实现时,并不会访问所有可能的译文单词序列,而是用某种策略进行有效的搜索。常用的做法是自左向右逐词生成。比如,对于每一个目标语位置$j$,可以执行 \noindent 在具体实现时,由于当前目标语单词的生成需要依赖前面单词的生成,因此无法同时生成所有的目标语单词。理论上,可以枚举所有的$\mathbf{y}$,之后利用$\textrm{P}(\mathbf{y} | \mathbf{x})$ 的定义对每个$\mathbf{y}$进行评价,然后找出最好的$\mathbf{y}$。这也被称作{\small\bfnew{全搜索}}\index{全搜索}(Full Search)\index{Full Search}。但是,枚举所有的译文单词序列显然是不现实的。因此,在具体实现时,并不会访问所有可能的译文单词序列,而是用某种策略进行有效的搜索。常用的做法是自左向右逐词生成。比如,对于每一个目标语位置$j$,可以执行
\begin{eqnarray} \begin{eqnarray}
\hat{y}_j = \argmax_{y_j} \textrm{P}(y_j | \hat{\mathbf{y}}_{<j} , \mathbf{x}) \hat{y}_j = \argmax_{y_j} \textrm{P}(y_j | \hat{\mathbf{y}}_{<j} , \mathbf{x})
\label{eq:6-36} \label{eq:6-36}
...@@ -1202,7 +1202,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1202,7 +1202,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{figure} \end{figure}
%---------------------------------------------- %----------------------------------------------
\parinterval 贪婪搜索的优点在于速度快。在对翻译速度有较高要求的场景中,贪婪搜索是一种十分有效的加速系统的方法。而且贪婪搜索的原理非常简单,易于快速原型。不过,由于每一步只保留一个最好的局部结果,贪婪搜索往往会带来翻译品质上的损失。 \parinterval 贪婪搜索的优点在于速度快。在对翻译速度有较高要求的场景中,贪婪搜索是一种十分有效的对系统加速的方法。而且贪婪搜索的原理非常简单,易于快速原型。不过,由于每一步只保留一个最好的局部结果,贪婪搜索往往会带来翻译品质上的损失。
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION % NEW SUBSUB-SECTION
...@@ -1217,7 +1217,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1217,7 +1217,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\label{eq:6-38} \label{eq:6-38}
\end{eqnarray} \end{eqnarray}
\noindent 类似的,对``has''和``it''进行同样的操作,分别计算得到$ \textrm{P} (y_2, \textrm{``have''} | \mathbf{x})$$ \textrm{P} (y_2, \textrm{``has''} | \mathbf{x})$\\ $ \textrm{P} (y_2, \textrm{``it''} | \mathbf{x})$,因为$y_2$对应$|V|$种可能,总共可以得到$3 \times |V|$种结果。然后从中选取使序列概率$\textrm{P}(y_2,y_1| \mathbf{x})$最大的前三个$y_2$作为新的输出结果,这样便得到了前两个位置的top-3译文。在预测其他位置时也是如此,不断重复此过程直到推断结束。可以看到,束搜索的搜索空间大小与束宽度有关,也就是:束宽度越大,搜索空间越大,更有可能搜索到质量更高的译文,但搜索会更慢。束宽度等于3,意味着每次只考虑三个最有可能的结果,贪婪搜索实际上便是集束宽度为1的情况。在神经机器翻译系统实现中,一般束宽度设置在4~8之间。 \noindent 类似的,对``has''和``it''进行同样的操作,分别计算得到$ \textrm{P} (y_2, \textrm{``have''} | \mathbf{x})$$ \textrm{P} (y_2, \textrm{``has''} | \mathbf{x})$\\ $ \textrm{P} (y_2, \textrm{``it''} | \mathbf{x})$,因为$y_2$对应$|V|$种可能,总共可以得到$3 \times |V|$种结果。然后从中选取使序列概率$\textrm{P}(y_2,y_1| \mathbf{x})$最大的前三个$y_2$作为新的输出结果,这样便得到了前两个位置的top-3译文。在预测其他位置时也是如此,不断重复此过程直到推断结束。可以看到,束搜索的搜索空间大小与束宽度有关,也就是:束宽度越大,搜索空间越大,更有可能搜索到质量更高的译文,但同时搜索会更慢。束宽度等于3,意味着每次只考虑三个最有可能的结果,贪婪搜索实际上便是集束宽度为1的情况。在神经机器翻译系统实现中,一般束宽度设置在4~8之间。
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -1252,7 +1252,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1252,7 +1252,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\label{eq:6-39} \label{eq:6-39}
\end{eqnarray} \end{eqnarray}
\noindent 其中,$|\mathbf{y}|$代表已经得到的译文长度,$\alpha$是一个固定的常数,用于控制惩罚的强度。同时在计算句子得分时,额外引入覆盖度的因子,如下: \noindent 其中,$|\mathbf{y}|$代表已经得到的译文长度,$\alpha$是一个固定的常数,用于控制惩罚的强度。同时在计算句子得分时,额外引入表示覆盖度的因子,如下:
\begin{eqnarray} \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) \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)
\label{eq:6-40} \label{eq:6-40}
...@@ -1317,7 +1317,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1317,7 +1317,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\parinterval 前面介绍的基于循环神经网络的翻译模型和注意力机制就是研究人员通过长期的实践发现的神经网络架构。除了神经机器翻译,它们也被广泛地应用于语音处理、图像处理等领域。虽然循环神经网络很强大,但是人们也发现了一些弊端。一个突出的问题是,循环神经网络每个循环单元都有向前依赖性,也就是当前时间步的处理依赖前一时间步处理的结果。这个性质可以使序列的``历史''信息不断被传递,但是也造成模型运行效率的下降。特别是对于自然语言处理任务,序列往往较长,无论是传统的RNN结构,还是更为复杂的LSTM结构,都需要很多次循环单元的处理才能够捕捉到单词之间的长距离依赖。由于需要多个循环单元的处理,距离较远的两个单词之间的信息传递变得很复杂。 \parinterval 前面介绍的基于循环神经网络的翻译模型和注意力机制就是研究人员通过长期的实践发现的神经网络架构。除了神经机器翻译,它们也被广泛地应用于语音处理、图像处理等领域。虽然循环神经网络很强大,但是人们也发现了一些弊端。一个突出的问题是,循环神经网络每个循环单元都有向前依赖性,也就是当前时间步的处理依赖前一时间步处理的结果。这个性质可以使序列的``历史''信息不断被传递,但是也造成模型运行效率的下降。特别是对于自然语言处理任务,序列往往较长,无论是传统的RNN结构,还是更为复杂的LSTM结构,都需要很多次循环单元的处理才能够捕捉到单词之间的长距离依赖。由于需要多个循环单元的处理,距离较远的两个单词之间的信息传递变得很复杂。
\parinterval 针对这些问题,谷歌的研究人员提出了一种全新的模型$\ \dash\ $Transformer\cite{NIPS2017_7181}。与循环神经网络等传统模型不同,Transformer模型仅仅使用一种被称作自注意力机制的模型和标准的前馈神经网络,完全不依赖任何循环单元或者卷积操作。自注意力机制的优点在于可以直接对序列中任意两个单元之间的关系进行建模,这使得长距离依赖等问题可以更好地被求解。此外,自注意力机制非常适合在GPU 上进行并行化,因此模型训练的速度更快。表\ref{tab:6-11}对比了RNN、CNN、Transformer三种模型的时间复杂度。 \parinterval 针对这些问题,谷歌的研究人员提出了一种全新的模型$\ \dash\ $Transformer\cite{NIPS2017_7181}。与循环神经网络等传统模型不同,Transformer模型仅仅使用一种被称作自注意力机制的方法和标准的前馈神经网络,完全不依赖任何循环单元或者卷积操作。自注意力机制的优点在于可以直接对序列中任意两个单元之间的关系进行建模,这使得长距离依赖等问题可以更好地被求解。此外,自注意力机制非常适合在GPU 上进行并行化,因此模型训练的速度更快。表\ref{tab:6-11}对比了RNN、CNN、Transformer三种模型的时间复杂度。
%---------------------------------------------- %----------------------------------------------
\begin{table}[htp] \begin{table}[htp]
...@@ -1393,7 +1393,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1393,7 +1393,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\end{figure} \end{figure}
%---------------------------------------------- %----------------------------------------------
\parinterval 举个例子,如图\ref{fig:6-38}所示,一个汉语句子包含5个词。这里,用$\mathbf{h}$(``你'')表示``你''当前的表示结果。如果把``你''看作目标,这时$\mathrm{query}$就是$\mathbf{h}$(``你''),$\mathrm{key}$$\mathrm{value}$\\是图中所有位置的表示,即:{$\mathbf{h}$(``你'')、$\mathbf{h}$(``什么'')、$\mathbf{h}$(``也'')、$\mathbf{h}$(``没'')、$\mathbf{h}$(`` 学'')}。在自注意力模型中,首先计算$\mathrm{query}$$\mathrm{key}$的相关度,这里用$\alpha_i$表示$\mathbf{h}$(``你'')和位置$i$的表示之间的相关性。然后,把$\alpha_i$作为权重,对不同位置上的$\mathrm{value}$进行加权求和。最终,得到新的表示结果$\tilde{\mathbf{h}}$ (``你'' ): \parinterval 举个例子,如图\ref{fig:6-38}所示,一个汉语句子包含5个词。这里,用$\mathbf{h}$(``你'')表示``你''当前的表示结果。如果把``你''看作目标,这时$\mathrm{query}$就是$\mathbf{h}$(``你''),$\mathrm{key}$$\mathrm{value}$是图中所有位置的表示,即:{$\mathbf{h}$(``你'')、$\mathbf{h}$(``什么'')、$\mathbf{h}$(``也'')、$\mathbf{h}$(``没'')、$\mathbf{h}$(`` 学'')}。在自注意力模型中,首先计算$\mathrm{query}$$\mathrm{key}$的相关度,这里用$\alpha_i$表示$\mathbf{h}$(``你'')和位置$i$的表示之间的相关性。然后,把$\alpha_i$作为权重,对不同位置上的$\mathrm{value}$进行加权求和。最终,得到新的表示结果$\tilde{\mathbf{h}}$ (``你'' ):
\begin{eqnarray} \begin{eqnarray}
\tilde{\mathbf{h}} (\textrm{``你''} ) = \alpha_1 {\mathbf{h}} (\textrm{``你''} ) \tilde{\mathbf{h}} (\textrm{``你''} ) = \alpha_1 {\mathbf{h}} (\textrm{``你''} )
+ \alpha_2 {\mathbf{h}} (\textrm{``什么 ''}) + \alpha_2 {\mathbf{h}} (\textrm{``什么 ''})
...@@ -1438,7 +1438,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1438,7 +1438,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\parinterval 以上操作就构成了Transformer的一层,各个模块执行的顺序可以简单描述为:Self-Attention $\to$ Residual Connection $\to$ Layer Normalization $\to$ Feed Forward Network $\to$ Residual Connection $\to$ Layer Normalization。编码器可以包含多个这样的层,比如,可以构建一个六层编码器,每层都执行上面的操作。最上层的结果作为整个编码的结果,会被传入解码器。 \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}给出了这两种不同注意力子层输入的区别。 \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}给出了这两种不同注意力子层输入的区别。
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -1451,7 +1451,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1451,7 +1451,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\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''),这个设计和标准的神经语言模型是完全一样的。 \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''),这个设计和标准的神经语言模型是完全一样的。
\parinterval 了解到这里,可能大家还有很多疑惑,比如,什么是位置编码?Transformer的自注意力机制具体是怎么进行计算的,其结构是怎样的?Add\& LayerNorm又是什么?等等。下面就一一展开介绍。 \parinterval 了解到这里,可能大家还有很多疑惑,比如,什么是位置编码?Transformer的自注意力机制具体是怎么进行计算的,其结构是怎样的?Add\& LayerNorm又是什么?等等。下面就一一展开介绍。
...@@ -1555,7 +1555,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\ ...@@ -1555,7 +1555,7 @@ L(\mathbf{Y},\widehat{\mathbf{Y}}) = \sum_{j=1}^n L_{\textrm{ce}}(\mathbf{y}_j,\
\noindent 首先,通过对$\mathbf{Q}$$\mathbf{K}$的转置进行点乘操作,计算得到一个维度大小为$L \times L$的相关性矩阵,即$\mathbf{Q}\mathbf{K}^{T}$,它表示一个序列上任意两个位置的相关性。再通过系数1/$\sqrt{d_k}$进行放缩操作,放缩可以尽量减少相关性矩阵的方差,具体体现在运算过程中实数矩阵中的数值不会过大,有利于模型训练。 \noindent 首先,通过对$\mathbf{Q}$$\mathbf{K}$的转置进行点乘操作,计算得到一个维度大小为$L \times L$的相关性矩阵,即$\mathbf{Q}\mathbf{K}^{T}$,它表示一个序列上任意两个位置的相关性。再通过系数1/$\sqrt{d_k}$进行放缩操作,放缩可以尽量减少相关性矩阵的方差,具体体现在运算过程中实数矩阵中的数值不会过大,有利于模型训练。
\parinterval 在此基础上,通过对相关性矩阵累加一个掩码矩阵,来屏蔽掉矩阵中的无用信息。比如,在编码端对句子的补齐,在解码端则屏蔽掉未来信息,这一部分内容将在下一小节进行详细介绍。随后,使用Softmax函数对相关性矩阵在行的维度上进行归一化操作,这可以理解为对第$i$行进行归一化,结果对应了$\mathbf{V}$中的不同位置上向量的注意力权重。对于$\mathrm{value}$的加权求和,可以直接用相关性系数和$\mathbf{V}$进行矩阵乘法得到,即$\textrm{Softmax} \parinterval 在此基础上,通过对相关性矩阵累加一个掩码矩阵,来屏蔽掉矩阵中的无用信息。比如,在编码端对句子的补齐,在解码端则屏蔽掉未来信息,这一部分内容将在下一小节进行详细介绍。随后,使用Softmax函数对相关性矩阵在行的维度上进行归一化操作,这可以理解为对第$i$行进行归一化,结果对应了$\mathbf{V}$中的不同位置上向量的注意力权重。对于$\mathrm{value}$的加权求和,可以直接用相关性系数和$\mathbf{V}$进行矩阵乘法得到,即$\textrm{Softmax}
( \frac{\mathbf{Q}\mathbf{K}^{T}} {\sqrt{d_k}} + \mathbf{Mask} )$$\mathbf{V}$进行矩阵乘。最终就到了自注意力的输出,它和输入的$\mathbf{V}$的大小是一模一样的。图\ref{fig:6-45}展示了点乘注意力计算的全过程。 ( \frac{\mathbf{Q}\mathbf{K}^{T}} {\sqrt{d_k}} + \mathbf{Mask} )$$\mathbf{V}$进行矩阵乘。最终得到自注意力的输出,它和输入的$\mathbf{V}$的大小是一模一样的。图\ref{fig:6-45}展示了点乘注意力计算的全过程。
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -1728,7 +1728,7 @@ x_{l+1} = x_l + \mathcal{F} (x_l) ...@@ -1728,7 +1728,7 @@ x_{l+1} = x_l + \mathcal{F} (x_l)
\subsection{训练} \subsection{训练}
\parinterval 与前面介绍的神经机器翻译模型的训练一样,Transformer的训练流程为:首先对模型进行初始化,然后在编码器输入包含结束符的源语言单词序列。前面已经介绍过,解码端每个位置单词的预测都要依赖已经生成的序列。在解码端输入包含起始符号的目标语序列,通过起始符号预测目标语的第一个单词,用真实的目标语第一个单词去预测第二个单词,以此类推,然后用真实的目标语序列和预测的结果比较,计算它的损失。Transformer使用了{\small\bfnew{交叉熵损失}}\index{交叉熵损失}(Cross Entropy Loss)\index{Cross Entropy Loss}函数,损失越小说明模型的预测越接近真实输出。然后利用反向传播来调整模型中的参数。由于Transformer 将任意时刻输入信息之间的距离拉近为1,摒弃了RNN中每一个时刻的计算都要基于前一时刻的计算这种具有时序性的训练方式,因此Transformer中训练的不同位置可以并行化训练,大大提高了训练效率。 \parinterval 与前面介绍的神经机器翻译模型的训练一样,Transformer的训练流程为:首先对模型进行初始化,然后在编码器输入包含结束符的源语言单词序列。前面已经介绍过,解码端每个位置单词的预测都要依赖已经生成的序列。在解码端输入包含起始符号的目标语序列,通过起始符号预测目标语的第一个单词,用真实的目标语第一个单词去预测第二个单词,以此类推,然后用真实的目标语序列和预测的结果比较,计算它的损失。Transformer使用了{\small\bfnew{交叉熵损失}}\index{交叉熵损失}(Cross Entropy Loss)\index{Cross Entropy Loss}函数,损失越小说明模型的预测越接近真实输出。然后利用反向传播来调整模型中的参数。由于Transformer 将任意时刻输入信息之间的距离拉近为1,摒弃了RNN中每一个时刻的计算都要基于前一时刻的计算这种具有时序性的训练方式,因此Transformer中训练的不同位置可以并行化训练,大大提高了训练效率。
%---------------------------------------------- %----------------------------------------------
%\begin{figure}[htp] %\begin{figure}[htp]
...@@ -1739,7 +1739,7 @@ x_{l+1} = x_l + \mathcal{F} (x_l) ...@@ -1739,7 +1739,7 @@ x_{l+1} = x_l + \mathcal{F} (x_l)
%\end{figure} %\end{figure}
%---------------------------------------------- %----------------------------------------------
\parinterval 需要注意的时候,Transformer也包含很多工程方面的技巧。首先,在训练优化器方面,需要注意以下几点: \parinterval 需要注意的,Transformer也包含很多工程方面的技巧。首先,在训练优化器方面,需要注意以下几点:
\begin{itemize} \begin{itemize}
\vspace{0.5em} \vspace{0.5em}
...@@ -1780,7 +1780,7 @@ lrate = d_{model}^{-0.5} \cdot \textrm{min} (step^{-0.5} , step \cdot warmup\_st ...@@ -1780,7 +1780,7 @@ lrate = d_{model}^{-0.5} \cdot \textrm{min} (step^{-0.5} , step \cdot warmup\_st
\end{figure} \end{figure}
%---------------------------------------------- %----------------------------------------------
\vspace{0.5em} \vspace{0.5em}
\item {\small\bfnew{Dropout}}\index{Dropout}:由于Transformer模型网络结构较为复杂,会导致过度拟合训练数据,从而对未见数据的预测结果变差。这种现象也被称作{\small\sffamily\bfseries{过拟合}}\index{过拟合}(Over fitting)\index{Over fitting}。为了避免这种现象,Transformer加入了Dropout操作\cite{JMLR:v15:srivastava14a}。Transformer中这四个地方用到了Dropout:词嵌入和位置编码、残差连接、注意力操作和前馈神经网络。Dropout比例通常设置为$0.1$ \item {\small\bfnew{Dropout}}\index{Dropout}:由于Transformer模型网络结构较为复杂,会导致过度拟合训练数据,从而对未见数据的预测结果变差。这种现象也被称作{\small\sffamily\bfseries{过拟合}}\index{过拟合}(Over Fitting)\index{Over fitting}。为了避免这种现象,Transformer加入了Dropout操作\cite{JMLR:v15:srivastava14a}。Transformer中这四个地方用到了Dropout:词嵌入和位置编码、残差连接、注意力操作和前馈神经网络。Dropout比例通常设置为$0.1$
\vspace{0.5em} \vspace{0.5em}
\item {\small\bfnew{标签平滑}}\index{标签平滑}(Label Smoothing)\index{Label Smoothing}:在计算损失的过程中,需要用预测概率去拟合真实概率。在分类任务中,往往使用One-hot向量代表真实概率,即真实答案位置那一维对应的概率为1,其余维为0,而拟合这种概率分布会造成两个问题:1)无法保证模型的泛化能力,容易造成过拟合;2) 1和0概率鼓励所属类别和其他类别之间的差距尽可能加大,会造成模型过于相信预测的类别。因此Transformer里引入标签平滑\cite{Szegedy_2016_CVPR}来缓解这种现象,简单的说就是给正确答案以外的类别分配一定的概率,而不是采用非0即1的概率。这样,可以学习一个比较平滑的概率分布,从而提升泛化能力。 \item {\small\bfnew{标签平滑}}\index{标签平滑}(Label Smoothing)\index{Label Smoothing}:在计算损失的过程中,需要用预测概率去拟合真实概率。在分类任务中,往往使用One-hot向量代表真实概率,即真实答案位置那一维对应的概率为1,其余维为0,而拟合这种概率分布会造成两个问题:1)无法保证模型的泛化能力,容易造成过拟合;2) 1和0概率鼓励所属类别和其他类别之间的差距尽可能加大,会造成模型过于相信预测的类别。因此Transformer里引入标签平滑\cite{Szegedy_2016_CVPR}来缓解这种现象,简单的说就是给正确答案以外的类别分配一定的概率,而不是采用非0即1的概率。这样,可以学习一个比较平滑的概率分布,从而提升泛化能力。
\vspace{0.5em} \vspace{0.5em}
...@@ -1821,7 +1821,7 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^{6}$ ...@@ -1821,7 +1821,7 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^{6}$
\subsection{推断} \subsection{推断}
\parinterval Transformer解码器生成目标语的过程和前面介绍的循环网络翻译模型类似,都是从左往右生成,且下一个单词的预测依赖已经生成的上一个单词。其具体推断过程如图\ref{fig:6-56}所示,其中$\mathbf{C}_i$是编-解码注意力的结果,解码器首先根据``<eos>''和$\mathbf{C}_1$生成第一个单词``how'',然后根据``how''和$\mathbf{C}_2$生成第二个单词``are'',以此类推,当解码器生成``<eos>''时结束推断。 \parinterval Transformer解码器生成目标语的过程和前面介绍的循环网络翻译模型类似,都是从左往右生成,且下一个单词的预测依赖已经生成的上一个单词。其具体推断过程如图\ref{fig:6-56}所示,其中$\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模型的推断技术将会在第七章进一步深入介绍。 \parinterval 但是,Transformer在推断阶段无法对所有位置进行并行化操作,因为对于每一个目标语单词都需要对前面所有单词进行注意力操作,因此它推断速度非常慢。可以采用的加速手段有:低精度\cite{DBLP:journals/corr/CourbariauxB16}、Cache(缓存需要重复计算的变量)\cite{DBLP:journals/corr/abs-1805-00631}、共享注意力网络等\cite{Xiao2019SharingAW}。关于Transformer模型的推断技术将会在第七章进一步深入介绍。
...@@ -1940,7 +1940,7 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^{6}$ ...@@ -1940,7 +1940,7 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^{6}$
\vspace{0.5em} \vspace{0.5em}
\item 一般来说,神经机器翻译的计算过程是没有人工干预的,翻译流程也无法用人类的知识直接进行解释,因此一个有趣的方向是在神经机器翻译中引入先验知识,使得机器翻译的行为更``像''人。比如,可以使用句法树来引入人类的语言学知识\cite{Yang2017TowardsBH,Wang2019TreeTI},基于句法的神经机器翻译也包含大量的树结构的神经网络建模\cite{DBLP:journals/corr/abs-1809-01854,DBLP:journals/corr/abs-1808-09374}。此外,也可以把用户定义的词典或者翻译记忆加入到翻译过程来\cite{DBLP:journals/corr/ZhangZ16c,Dai2019TransformerXLAL},使得用户的约束可以直接反映到机器翻译的结果上来。先验知识的种类还有很多,包括词对齐\cite{li-etal-2019-word,Zhang2017PriorKI}、篇章信息\cite{Werlen2018DocumentLevelNM,DBLP:journals/corr/abs-1805-10163}等等,都是神经机器翻译中能够使用的信息。 \item 一般来说,神经机器翻译的计算过程是没有人工干预的,翻译流程也无法用人类的知识直接进行解释,因此一个有趣的方向是在神经机器翻译中引入先验知识,使得机器翻译的行为更``像''人。比如,可以使用句法树来引入人类的语言学知识\cite{Yang2017TowardsBH,Wang2019TreeTI},基于句法的神经机器翻译也包含大量的树结构的神经网络建模\cite{DBLP:journals/corr/abs-1809-01854,DBLP:journals/corr/abs-1808-09374}。此外,也可以把用户定义的词典或者翻译记忆加入到翻译过程来\cite{DBLP:journals/corr/ZhangZ16c,Dai2019TransformerXLAL},使得用户的约束可以直接反映到机器翻译的结果上来。先验知识的种类还有很多,包括词对齐\cite{li-etal-2019-word,Zhang2017PriorKI}、篇章信息\cite{Werlen2018DocumentLevelNM,DBLP:journals/corr/abs-1805-10163}等等,都是神经机器翻译中能够使用的信息。
\vspace{0.5em} \vspace{0.5em}
\item 神经机器翻译依赖成本较高的GPU设备,因此对模型的裁剪和加速也是很多系统研发人员所感兴趣的方向。比如,从工程上,可以考虑减少运算强度,比如低精度浮点或者整数计算,或者引入缓存机制来加速模型的推断\cite{DBLP:journals/corr/abs-1906-00532,DBLP:journals/corr/CourbariauxB16};也可以通过对模型参数矩阵的剪枝,甚至对模块的剪枝,来减小整个模型的体积\cite{Zhang2018SpeedingUN,DBLP:journals/corr/SeeLM16};另一种方法是知识精炼。利用大模型训练小模型,这样往往可以得到比单独训练小模型更好的效果\cite{DBLP:journals/corr/ChenLCL17,Hinton2015Distilling,Sun2019PatientKD} \item 神经机器翻译依赖成本较高的GPU设备,因此对模型的裁剪和加速也是很多系统研发人员所感兴趣的方向。比如,从工程上,可以考虑减少运算强度,比如使用低精度浮点数或者整数进行计算,或者引入缓存机制来加速模型的推断\cite{DBLP:journals/corr/abs-1906-00532,DBLP:journals/corr/CourbariauxB16};也可以通过对模型参数矩阵的剪枝,甚至对模块的剪枝,来减小整个模型的体积\cite{Zhang2018SpeedingUN,DBLP:journals/corr/SeeLM16};另一种方法是知识精炼。利用大模型训练小模型,这样往往可以得到比单独训练小模型更好的效果\cite{DBLP:journals/corr/ChenLCL17,Hinton2015Distilling,Sun2019PatientKD}
\vspace{0.5em} \vspace{0.5em}
\end{itemize} \end{itemize}
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
\parinterval 作为机器翻译的前沿方向,神经机器翻译方法是近些年来最受关注的热点之一。凭借其高品质的译文,神经机器翻译的身影在各种机器翻译比赛和产品中随处可见。第六章已经介绍了神经机器翻译的基础模型,包括:基于循环神经网络的翻译模型、基于Transformer的翻译模型、注意力机制等等。但是,简单使用这些模型和方法显然无法取得最好的结果。实际上,先进的系统往往依赖多种技术的综合运用,是一项庞大的系统工程。 \parinterval 作为机器翻译的前沿方向,神经机器翻译方法是近些年来最受关注的热点之一。凭借其高品质的译文,神经机器翻译的身影在各种机器翻译比赛和产品中随处可见。第六章已经介绍了神经机器翻译的基础模型,包括:基于循环神经网络的翻译模型、基于Transformer的翻译模型、注意力机制等等。但是,简单使用这些模型和方法显然无法取得最好的结果。实际上,先进的系统往往依赖多种技术的综合运用,是一项庞大的系统工程。
\parinterval 本章将沿着神经机器翻译框架继续探讨:如何研发性能更为突出的机器翻译系统。这里将介绍若干常用的提升神经机器翻译系统品质和速度的方法。同时,也会讨论一些开放性的前沿课题,旨在使机器翻译的效果达到更加先进的水平。本章的绝大部分内容都经过笔者所在团队的实验,具有实践方面的参考价值。正如本章的副标题一样,希望这里所讨论的内容可以帮助读者了解如何开发出一套足以参加高水平机器翻译比赛的系统,为相关研究建立更加科学、合理的基线,同时为机器翻译的应用提供一些具体可落地的思路。 \parinterval 本章将沿着神经机器翻译框架继续探讨:如何研发性能更为突出的机器翻译系统。这里将介绍若干常用的提升神经机器翻译系统品质和速度的方法。同时,也会讨论一些开放性的前沿课题,旨在使机器翻译达到更加先进的水平。本章的绝大部分内容都经过笔者所在团队的实验,具有实践方面的参考价值。正如本章的副标题一样,希望这里所讨论的内容可以帮助读者了解如何开发出一套足以参加高水平机器翻译比赛的系统,为相关研究建立更加科学、合理的基线,同时为机器翻译的应用提供一些具体可落地的思路。
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
...@@ -32,13 +32,13 @@ ...@@ -32,13 +32,13 @@
\begin{itemize} \begin{itemize}
\vspace{0.5em} \vspace{0.5em}
\item {\small\bfnew{神经网络模型很脆弱}}。神经机器翻译对超参数、训练策略的选择、网络结构的细微差别都非常敏感。比如,学习率、Dropout比率上下浮动一点点都会带来翻译结果的明显区别。这也导致系统研发人员需要花费大量的时间来寻找合理的系统配置。虽然也有一些研究工作探讨自动化调参和结构设计(如:AutoML),但是为了确保翻译品质,现在普遍的做法仍然是``人肉''搜索最佳的网络架构和系统配置。 \item {\small\bfnew{神经网络模型很脆弱}}。神经机器翻译对超参数、训练策略的选择、网络结构的细微差别都非常敏感。比如,学习率、Dropout比率上下浮动一点点都会给翻译结果带来明显区别。这也导致系统研发人员需要花费大量的时间来寻找合理的系统配置。虽然也有一些研究工作探讨自动化调参和结构设计(如:AutoML),但是为了确保翻译品质,现在普遍的做法仍然是``人肉''搜索最佳的网络架构和系统配置。
\vspace{0.5em} \vspace{0.5em}
\item {\small\bfnew{神经机器翻译需要对不同翻译任务进行适应}}。理想中一套``包打天下''的模型和设置是不存在的。针对不同语种、不同领域,机器翻译系统都需要进行调整。比如,一个新闻数据上训练的系统在专利数据上的表现往往不会很好。这里并不否认在很多研究工作中为了缩短研究周期,可以用同一套系统及设置在所有任务上进行实验。但是,具体到每个翻译任务上,高质量翻译都需要对系统进行细致的调整,比如,与语言相关的数据加工等。 \item {\small\bfnew{神经机器翻译需要对不同翻译任务进行适应}}。理想中一套``包打天下''的模型和设置是不存在的。针对不同语种、不同领域,机器翻译系统都需要进行调整。比如,一个在新闻数据上训练的系统在专利数据上的表现往往不会很好。这里并不否认在很多研究工作中为了缩短研究周期,可以用同一套系统及设置在所有任务上进行实验。但是,具体到每个翻译任务上,高质量翻译都离不开对系统细致地调整,比如,与语言相关的数据加工等。
\vspace{0.5em} \vspace{0.5em}
\item {\small\bfnew{神经机器翻译的``最后一公里''仍然很长}}。无论是使用开源系统,还是从论文中进行复现,都可以很容易的得到一个基础版本的机器翻译系统。但是这样的系统离真正的state-of-the-art往往会有距离,离实用系统的距离可能更远。更具挑战的是,很多高水平系统中所使用的技巧甚至都没有被开源或者以论文的形式发表,这大大增加了普通研究者挑战前沿的难度。 \item {\small\bfnew{神经机器翻译的``最后一公里''仍然很长}}。无论是使用开源系统,还是从论文中进行复现,都可以很容易的得到一个基础版本的机器翻译系统。但是这样的系统离真正的state-of-the-art往往会有距离,离实用系统的距离可能更远。更具挑战的是,很多高水平系统中所使用的技巧甚至都没有被开源或者以论文的形式发表,这大大增加了普通研究者挑战前沿的难度。
\vspace{0.5em} \vspace{0.5em}
\item {\small\bfnew{优秀系统的研发需要长时间的打磨,但是很多时候我们仅仅是在快速原型}}。这不是一个技术问题。因为如果有足够的时间,所有人都可以把任何事情做到极致。但是,不论是为了毕业、提职,还是希望在领域占据一席之地,我们总是希望在尽可能短的时间内把系统研发出来,把结果报道出来。这种做法无可厚非,因为科学研究需要对更本质的科学问题进行探索,而非简单的工程开发与调试。但是,对一个初级的系统进行研究往往会掩盖掉``真正的问题'',因为很多问题在更先进的系统中根本就不存在。 \item {\small\bfnew{优秀系统的研发需要长时间的打磨,但是很多时候我们仅仅是在搭建快速原型}}。这不是一个技术问题。因为如果有足够的时间,所有人都可以把任何事情做到极致。但是,不论是为了毕业、提职,还是希望在领域占据一席之地,我们总是希望在尽可能短的时间内把系统研发出来,把结果报道出来。这种做法无可厚非,因为科学研究需要对更本质的科学问题进行探索,而非简单的工程开发与调试。但是,对一个初级的系统进行研究往往会掩盖掉``真正的问题'',因为很多问题在更先进的系统中根本就不存在。
\vspace{0.5em} \vspace{0.5em}
\end{itemize} \end{itemize}
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
\parinterval 一般来说,有三方面因素会影响神经机器翻译系统的性能: \parinterval 一般来说,有三方面因素会影响神经机器翻译系统的性能:
\begin{itemize} \begin{itemize}
\item {\small\bfnew{技术的先进性和成熟度}}。选择什么样的神经网络模型、什么样的训练方法、什么样的模型初始化策略等等,都会对最终的系统产生影响。显然,更加先进、成熟度更高的技术会带来性能的提升。比如,在最近,Transformer架构就受到了很多人的青睐,Adam等训练策略在神经机器翻译中也很流行。当然,未来一定会有更加强大的模型和技术被提出。因此系统研发者也需要紧跟技术的前沿,这样才能保证系统的先进性。 \item {\small\bfnew{技术的先进性和成熟度}}。选择什么样的神经网络模型、什么样的训练方法、什么样的模型初始化策略等等,都会对最终的系统产生影响。显然,更加先进、成熟度更高的技术会带来性能的提升。比如,在最近,Transformer架构就受到了很多人的青睐,Adam等训练策略在神经机器翻译中也很流行。当然,未来一定会有更加强大的模型和更加先进的技术被提出。因此系统研发者也需要紧跟技术的前沿,这样才能保证系统的先进性。
\item {\small\bfnew{数据的质量和规模}}。数据驱动的方法对数据的依赖性不言而喻。虽然技术日新月异,但是``更好更多的数据''是一直被广泛接受的``真理''。所谓数据质量和规模一般都是针对任务而言,因此如何(或者是否可以)获取适合目标任务的高质量、大规模的数据是实践中需要考虑的因素。在机器翻译系统研发的初级阶段,特别是在数据规模受限的情况下,增加高质量数据带来的性能提升往往更容易体现出来(如图\ref{fig:7-1})。 \item {\small\bfnew{数据的质量和规模}}。数据驱动的方法对数据的依赖性不言而喻。虽然技术日新月异,但是``更好更多的数据''是一直被广泛接受的``真理''。所谓数据质量和规模一般都是针对任务而言,因此如何(或者是否可以)获取适合目标任务的高质量、大规模的数据是实践中需要考虑的因素。在机器翻译系统研发的初级阶段,特别是在数据规模受限的情况下,增加高质量数据带来的性能提升往往更容易体现出来(如图\ref{fig:7-1})。
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
\item {\small\bfnew{系统的打磨}}。容易被忽视的是系统的工程打磨,包括对数据的细致处理、参数的精细调整。更重要的是,在应用的过程中需要对发现的问题不断进行修正,这种日积月累的改变最终会带来翻译品质的显著提升。不过,系统打磨所需要的毅力与投入是十分巨大的。甚至从整个系统研发的进程来看,打磨的时间往往会占据主要部分。这对系统研发者来说也是一种考验。 \item {\small\bfnew{系统的打磨}}。容易被忽视的是系统的工程打磨,包括对数据的细致处理、参数的精细调整。更重要的是,在应用的过程中需要对发现的问题不断进行修正,这种日积月累的改变最终会带来翻译品质的显著提升。不过,系统打磨所需要的毅力与投入是十分巨大的。甚至从整个系统研发的进程来看,打磨的时间往往会占据主要部分。这对系统研发者来说也是一种考验。
\end{itemize} \end{itemize}
\parinterval 从应用的角度,评价系统的维度有很多,因此研发系统所使用的策略也会有所不同。比如,如果希望让机器翻译能够在小型离线设备上运行,这时可能同时关心模型的体积和翻译的速度;如果是为了做非实时的文本翻译,翻译品质就是最关键的。 \parinterval 从应用的角度,评价系统的维度有很多,因此研发系统所使用的策略也会有所不同。比如,如果希望让机器翻译能够在小型离线设备上运行,这时可能需要同时关心模型的体积和翻译的速度;如果是为了做非实时的文本翻译,翻译品质就是最关键的。
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
% NEW SUB-SECTION % NEW SUB-SECTION
...@@ -116,7 +116,7 @@ ...@@ -116,7 +116,7 @@
\parinterval 同统计机器翻译一样,神经机器翻译也需要对输入和输出的句子进行分词,目的是得到翻译的最基本单元。但是,这里所说的单词并不是语言学上的单词,更多的是指面向机器翻译任务的最小翻译片段。比如,可以复用第二章中的自动分词系统对句子进行切分,之后在切分得到的``词''序列上完成翻译建模。 \parinterval 同统计机器翻译一样,神经机器翻译也需要对输入和输出的句子进行分词,目的是得到翻译的最基本单元。但是,这里所说的单词并不是语言学上的单词,更多的是指面向机器翻译任务的最小翻译片段。比如,可以复用第二章中的自动分词系统对句子进行切分,之后在切分得到的``词''序列上完成翻译建模。
\parinterval 自然语言的表达非常丰富,因此需要很多的单词才能表达不同的语义。但是,神经机器翻译系统对大词表的处理效率很低,比如,输出层在大规模词表上进行预测会有明显的速度下降,甚至无法进行计算。因此,在神经机器翻译中会使用受限的词表,比如包含30000-50000个单词的词表。另一方面,翻译新的句子时,受限词表会带来大量的{\small\bfnew{未登录词}}\index{未登录词}(Out of Vocabulary Word,OOV Word)\index{Out of Vocabulary Word,OOV Word},系统无法对其进行翻译。实际上,产生未登录词的原因一方面是由于词表大小受限,另一方面的原因在于分词的颗粒度过大。对于后者,一种方法是进一步对``单词''进行切分,以得到更小的单元,这样可以大大缓解单词颗粒度过大造成的数据稀疏问题。这个过程通常被称作{\small\bfnew{子词切分}}\index{子词切分}(Sub-word Segmentation)\index{Sub-word Segmentation}。比如,以BPE为代表的子词切分方法已经成为了当今神经机器翻译所使用的标准方法,翻译效果显著超越基于传统分词的系统。 \parinterval 自然语言的表达非常丰富,因此需要很多的单词才能表达不同的语义。但是,神经机器翻译系统对大词表的处理效率很低,比如,输出层在大规模词表上进行预测会有明显的速度下降,甚至无法进行计算。因此,在神经机器翻译中会使用受限的词表,比如包含30000-50000个单词的词表。另一方面,翻译新的句子时,受限词表会带来大量的{\small\bfnew{未登录词}}\index{未登录词}(Out of Vocabulary Word,OOV Word)\index{Out of Vocabulary Word,OOV Word},系统无法对其进行翻译。实际上,产生未登录词一方面的原因是词表大小受限,另一方面的原因在于分词的颗粒度过大。对于后者,一种解决方法是进一步对``单词''进行切分,以得到更小的单元,这样可以大大缓解单词颗粒度过大造成的数据稀疏问题。这个过程通常被称作{\small\bfnew{子词切分}}\index{子词切分}(Sub-word Segmentation)\index{Sub-word Segmentation}。比如,以BPE为代表的子词切分方法已经成为了当今神经机器翻译所使用的标准方法,翻译效果显著超越基于传统分词的系统。
\parinterval 此外,机器翻译依赖高质量的训练数据。在神经机器翻译时代,模型对训练数据很敏感。由于神经机器翻译的模型较为复杂,因此数据中的噪声会对翻译系统产生较大的影响。特别是在实际应用中,数据的来源繁杂,质量参差不齐。因此,往往需要对原始的训练集进行{\small\bfnew{标准化}}\index{标准化}(Normalization)\index{Normalization}{\small\bfnew{数据清洗}}\index{数据清洗}(Dada Cleaning)\index{Dada Cleaning},从而获得高质量的双语数据用于模型训练。 \parinterval 此外,机器翻译依赖高质量的训练数据。在神经机器翻译时代,模型对训练数据很敏感。由于神经机器翻译的模型较为复杂,因此数据中的噪声会对翻译系统产生较大的影响。特别是在实际应用中,数据的来源繁杂,质量参差不齐。因此,往往需要对原始的训练集进行{\small\bfnew{标准化}}\index{标准化}(Normalization)\index{Normalization}{\small\bfnew{数据清洗}}\index{数据清洗}(Dada Cleaning)\index{Dada Cleaning},从而获得高质量的双语数据用于模型训练。
...@@ -136,7 +136,7 @@ ...@@ -136,7 +136,7 @@
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
\subsection{分词} \subsection{分词}
\parinterval 分词是数据处理的第一步。这部分技术在第二章已经进行了讨论。对于像中文这样没有单词边界的语言,分词的策略通常比较复杂。现在常用的一些中文分词工具有NLTK\cite{DBLP:conf/acl/Bird06}、jieba\footnote{\url{https://github.com/fxsjy/jieba}}等。而像英文这种有单词边界的语言,分词要简单许多,比如,Moses工具包就有可以处理绝大多数拉丁语系语言的分词脚本\cite{Koehn2007Moses}。图\ref{fig:7-4}展示了一个经过分词后的中英文双语对照数据 \parinterval 分词是数据处理的第一步。这部分技术在第二章已经进行了讨论。对于像中文这样没有单词边界的语言,分词的策略通常比较复杂。现在常用的一些中文分词工具有NLTK\cite{DBLP:conf/acl/Bird06}、jieba\footnote{\url{https://github.com/fxsjy/jieba}}等。而像英文这种有单词边界的语言,分词要简单许多,比如,Moses工具包就有可以处理绝大多数拉丁语系语言的分词脚本\cite{Koehn2007Moses}。图\ref{fig:7-4}展示了一个经过分词后的中英文双语数据对照图
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -147,7 +147,7 @@ ...@@ -147,7 +147,7 @@
\end{figure} \end{figure}
%---------------------------------------------- %----------------------------------------------
\parinterval 分词系统的效率是一个容易被忽略的问题,也是研发机器翻译系统需要考虑的因素。比如,对上亿、甚至几十亿个句子进行分词的时候,分词系统过慢会拖慢整个训练进程。因此,在实践中,对于大规模的分词,可以考虑多线程或者其它分布式计算技术,比如Map-Reduce,进行并行处理。 \parinterval 分词系统的效率是一个容易被忽略的问题,也是研发机器翻译系统需要考虑的因素。比如,对上亿、甚至几十亿个句子进行分词的时候,分词系统过慢会拖慢整个训练进程。因此,在实践中,对于大规模的分词,可以考虑使用多线程或者其它分布式计算技术,比如Map-Reduce,进行并行处理。
\parinterval 此外,在很多翻译场景下,需要对特殊的翻译单元单独处理。比如,在金融领域中,需要对企业名、时间、金额等信息进行准确翻译。这时,对分词系统的优化就十分必要,比如利用正则表达式保证特定类型的单词不会被切割得太碎;再比如,专利翻译中,一些化学式的表达、技术专有名词也需要单独处理。特别是,当用户希望通过预定义的词典干预翻译结果时,分词系统需要能配合相应的处理。比如,希望对一个片段强制使用用户指定的译文,这时就要求分词系统也能把这个单元准确的切分出来。这些问题的解决也依赖大量的工程优化。 \parinterval 此外,在很多翻译场景下,需要对特殊的翻译单元单独处理。比如,在金融领域中,需要对企业名、时间、金额等信息进行准确翻译。这时,对分词系统的优化就十分必要,比如利用正则表达式保证特定类型的单词不会被切割得太碎;再比如,专利翻译中,一些化学式的表达、技术专有名词也需要单独处理。特别是,当用户希望通过预定义的词典干预翻译结果时,分词系统需要能配合相应的处理。比如,希望对一个片段强制使用用户指定的译文,这时就要求分词系统也能把这个单元准确的切分出来。这些问题的解决也依赖大量的工程优化。
...@@ -177,11 +177,11 @@ ...@@ -177,11 +177,11 @@
\end{table} \end{table}
%-------------------------------------- %--------------------------------------
\parinterval 符号标准化,主要是指的全角或者半角符号的统一。如表\ref{tab:7-1}所示,虽然其中的百分号、字母‘A’和数字‘9’表示的含义没有变,但是在Unicode标准中存在不同的编码表示。因此,需要将不同的编码进行统一。在中英翻译中,通常会根据映射规则将符号全部统一成半角符号。 \parinterval 符号标准化,主要指的是全角或者半角符号的统一。如表\ref{tab:7-1}所示,虽然其中的百分号、字母‘A’和数字‘9’表示的含义没有变,但是在Unicode标准中存在不同的编码表示。因此,需要将不同的编码进行统一。在中英翻译中,通常会根据映射规则将符号全部统一成半角符号。
\parinterval 在英语等一些大小写敏感的语言中,一些专有名词和特殊用法,以及每个句子的首字母都需要进行大写。此外,训练数据中也会包括一些大小写错误的用法。这导致许多单词由于大小写的区分存在多种形式。一种简单的做法是将数据全部进行小写化,这样可以使所有的单词进行统一,大大提升模型预测的准确性。然而,用小写化数据训练的模型翻译结果也都是小写的,需要额外的还原模型对结果进行处理。 \parinterval 在英语等一些大小写敏感的语言中,一些专有名词和有特殊用法的单词,以及每个句子的首字母都需要进行大写。此外,训练数据中也会包括一些大小写错误的用法。这导致许多单词由于大小写的区分存在多种形式。一种简单的做法是将数据全部进行小写化,这样可以使所有的单词进行统一,大大提升模型预测的准确性。然而,用小写化数据训练的模型翻译结果也都是小写的,需要额外的还原模型对结果进行处理。
\parinterval 现在更常用的做法是保留句子中每个单词的正确大小写形式。但是对于句子的首字母,需将其转换成这个单词最常见的形式,如图\ref{fig:7-5}所示。通过这种方式,训练数据中只包含单词的正确大小写形式,大写的单词只有一些专有名词或者特殊用法,在一定程度上减小了词表大小,同时,也去除了一部分数据中由于错误大小写形式所产生的噪音。在翻译结束后,对首字母进行大写就能得到大小写合理的翻译结果。另外,中文存在简繁体两种形式的汉字,训练数据中可能会同时包含这两种形式。因此通常也会考虑把繁体中文转化为简体中文,以统一汉字的编码。 \parinterval 现在更常用的做法是保留句子中每个单词的正确大小写形式。但是对于句子的首字母,需将其转换成这个单词最常见的形式,如图\ref{fig:7-5}所示。通过这种方式,训练数据中只包含单词的正确大小写形式,大写单词只存在于一些专有名词或者有特殊用法的单词中,在一定程度上减小了词表大小,同时,也去除了一部分数据中由于错误大小写形式所产生的噪音。在翻译结束后,对首字母进行大写就能得到大小写合理的翻译结果。另外,中文存在简繁体两种形式的汉字,训练数据中可能会同时包含这两种形式。因此通常也会考虑把繁体中文转化为简体中文,以统一汉字的编码。
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -208,7 +208,7 @@ ...@@ -208,7 +208,7 @@
\vspace{0.5em} \vspace{0.5em}
\end{itemize} \end{itemize}
\parinterval 数据选择认为所有样本都是有用的,只是作用大小不同。因此,如果可以更充分的利用对机器翻译帮助更大的那部分数据,系统性能应该可以得到提升\cite{wang-etal-2018-dynamic} 比如,很多比赛系统中会使用测试数据与训练数据(源语言部分)进行匹配,选择一部分与测试集更相关的数据,之后用这部分数据微调系统\cite{DBLP:conf/wmt/LiLXLLLWZXWFCLL19,wang-etal-2018-tencent};也可以对不同训练数据的集合进行加权,之后进行权重敏感的训练,以期望权重大的数据对模型产生更大的影响\cite{wang-etal-2018-dynamic} \parinterval 数据选择认为所有样本都是有用的,只是作用大小不同。因此,如果可以更充分的利用对机器翻译帮助更大的那部分数据,系统性能应该可以得到提升\cite{wang-etal-2018-dynamic} 比如,很多比赛系统中会测试数据与训练数据(源语言部分)进行匹配,选择一部分与测试集更相关的数据,之后用这部分数据微调系统\cite{DBLP:conf/wmt/LiLXLLLWZXWFCLL19,wang-etal-2018-tencent};也可以对不同训练数据的集合进行加权,之后进行权重敏感的训练,以期望权重大的数据对模型产生更大的影响\cite{wang-etal-2018-dynamic}
\parinterval 数据过滤则认为数据中存在不太多的噪声,可以通过去除这种噪声提高数据整体的质量,进而提升训练效果。有很多方法,比如:过滤掉非对齐的样本、翻译质量极低的样本、重复样本等等。图\ref{fig:7-6}展示了数据过滤的实例。通常数据过滤需要很多工程手段的综合运用,因此也非常考验系统研发团队对系统打磨的能力。 \parinterval 数据过滤则认为数据中存在不太多的噪声,可以通过去除这种噪声提高数据整体的质量,进而提升训练效果。有很多方法,比如:过滤掉非对齐的样本、翻译质量极低的样本、重复样本等等。图\ref{fig:7-6}展示了数据过滤的实例。通常数据过滤需要很多工程手段的综合运用,因此也非常考验系统研发团队对系统打磨的能力。
...@@ -246,7 +246,7 @@ ...@@ -246,7 +246,7 @@
\vspace{0.5em} \vspace{0.5em}
\item 翻译长度比是否合理。有缺失成分的句子,会造成译文和源语言句子的长度比过大或者过小,因此可以设定一个区间,过滤掉长度落在这个区间外的所有句子。 \item 翻译长度比是否合理。有缺失成分的句子,会造成译文和源语言句子的长度比过大或者过小,因此可以设定一个区间,过滤掉长度落在这个区间外的所有句子。
\vspace{0.5em} \vspace{0.5em}
\item 单词对应是否合理。两个互为译文的句子之间的单词应该具有较好的对应关系。因此,可以考虑使用自动词对齐的结果,对句对的对齐质量进行评价。统计机器翻译中,这类方法已经广泛被用于短语翻译质量的度量,这里可以直接复用类似的方法(见第四章)。 \item 单词对应是否合理。两个互为译文的句子之间的单词应该具有较好的对应关系。因此,可以考虑使用自动词对齐的结果,对句对的对齐质量进行评价。统计机器翻译中,这类方法已经被广泛用于短语翻译质量的度量,这里可以直接复用类似的方法(见第四章)。
\vspace{0.5em} \vspace{0.5em}
\item 译文是否流畅。译文的流畅度是评价译文质量的重要指标。通常,在数据过滤中也会使用语言模型对译文流畅度进行评价。 \item 译文是否流畅。译文的流畅度是评价译文质量的重要指标。通常,在数据过滤中也会使用语言模型对译文流畅度进行评价。
\vspace{0.5em} \vspace{0.5em}
...@@ -303,7 +303,7 @@ ...@@ -303,7 +303,7 @@
\parinterval 但是字符级翻译也面临着新的问题\ \dash\ 使用字符增加了系统捕捉不同语言单元之间搭配的难度。假设平均一个单词由5个字符组成,所处理的序列长度便增大5倍。这使得具有独立意义的不同语言单元需要跨越更远的距离才能产生联系。此外,基于字符的方法也破坏了单词中天然存在的构词规律,或者说破坏了单词内字符的局部依赖。比如,英文单词``telephone''中的``tele''和``phone''都是有具体意义的词缀,但是如果把它们打散为字符就失去了这些含义。 \parinterval 但是字符级翻译也面临着新的问题\ \dash\ 使用字符增加了系统捕捉不同语言单元之间搭配的难度。假设平均一个单词由5个字符组成,所处理的序列长度便增大5倍。这使得具有独立意义的不同语言单元需要跨越更远的距离才能产生联系。此外,基于字符的方法也破坏了单词中天然存在的构词规律,或者说破坏了单词内字符的局部依赖。比如,英文单词``telephone''中的``tele''和``phone''都是有具体意义的词缀,但是如果把它们打散为字符就失去了这些含义。
\parinterval 那么有没有一种方式能够兼顾基于单词和基于字符方法的优点呢?常用的手段包括两种,一种是采用字词融合的方式构建词表,将未知单词转换为字符的序列并通过特殊的标记将其与普通的单词区分开来\cite{luong2016acl_hybrid}。而另一种方式将单词切分为{\small\bfnew{子词}}\index{子词}(Sub-word)\index{Sub-word},它是介于单词和字符中间的一种语言单元表示形式。比如,将英文单词``doing''切分为``do''+``ing''。对于形态学丰富的语言来说,子词体现了一种具有独立意义的构词基本单元。比如,如图\ref{fig:7-8},子词``do'',和``new''在可以用于组成其他不同形态的单词。 \parinterval 那么有没有一种方式能够兼顾基于单词和基于字符方法的优点呢?常用的手段包括两种,一种是采用字词融合的方式构建词表,将未知单词转换为字符的序列并通过特殊的标记将其与普通的单词区分开来\cite{luong2016acl_hybrid}。而另一种方式将单词切分为{\small\bfnew{子词}}\index{子词}(Sub-word)\index{Sub-word},它是介于单词和字符中间的一种语言单元表示形式。比如,将英文单词``doing''切分为``do''+``ing''。对于形态学丰富的语言来说,子词体现了一种具有独立意义的构词基本单元。比如,如图\ref{fig:7-8},子词``do'',和``new''在可以用于组成其他不同形态的单词。
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -334,7 +334,7 @@ ...@@ -334,7 +334,7 @@
\subsubsection{双字节编码(BPE)} \subsubsection{双字节编码(BPE)}
\parinterval {\small\bfnew{字节对编码}}\index{字节对编码}{\small\bfnew{双字节编码}}\index{双字节编码}(Byte Pair Encoding,BPE)\index{Byte Pair Encoding,BPE}是一种常用的子词词表构建方法\cite{DBLP:conf/acl/SennrichHB16a}。BPE方法最早用于数据压缩,对于数据中常见的连续字符串替换为一个不存在的字符,之后通过构建一个替换关系的对应表,对压缩后的数据进行还原。机器翻译借用了这种思想,把子词切分看作是学习对自然语言句子进行压缩编码表示的问题\cite{philipAlgorithmfordataCompression}。其目的是,保证编码后的结果(即子词切分)占用的字节尽可能少。这样,子词单元会尽可能被不同单词复用,同时又不会因为使用过小的单元造成子词切分序列过长。使用BPE算法构建子词词表可以分为如下几个步骤: \parinterval {\small\bfnew{字节对编码}}\index{字节对编码}{\small\bfnew{双字节编码}}\index{双字节编码}(Byte Pair Encoding,BPE)\index{Byte Pair Encoding,BPE}是一种常用的子词词表构建方法\cite{DBLP:conf/acl/SennrichHB16a}。BPE方法最早用于数据压缩,该方法将数据中常见的连续字符串替换为一个不存在的字符,之后通过构建一个替换关系的对应表,对压缩后的数据进行还原。机器翻译借用了这种思想,把子词切分看作是学习对自然语言句子进行压缩编码表示的问题\cite{philipAlgorithmfordataCompression}。其目的是,保证编码后的结果(即子词切分)占用的字节尽可能少。这样,子词单元会尽可能被不同单词复用,同时又不会因为使用过小的单元造成子词切分序列过长。使用BPE算法构建子词词表可以分为如下几个步骤:
\begin{itemize} \begin{itemize}
\vspace{0.5em} \vspace{0.5em}
...@@ -390,7 +390,7 @@ ...@@ -390,7 +390,7 @@
\subsubsection{其他方法} \subsubsection{其他方法}
\parinterval 与基于统计的BPE算法不同,基于Word Piece和1-gram Language Model(ULM)的方法则是利用语言模型进行子词词表的构造\cite{DBLP:conf/acl/Kudo18}。本质上,基于语言模型的方法和基于BPE的方法的思路是一样的,即通过合并字符和子词不断生成新的子词。它们的区别仅在于合并子词的方式不同。基于BPE的方法选择出现频次最高的连续字符2-gram合并为新的子词,而基于语言模型的方法中则是根据语言模型概率选择要合并哪些子词。 \parinterval 与基于统计的BPE算法不同,基于Word Piece和1-gram Language Model(ULM)的方法则是利用语言模型进行子词词表的构造\cite{DBLP:conf/acl/Kudo18}。本质上,基于语言模型的方法和基于BPE的方法的思路是一样的,即通过合并字符和子词不断生成新的子词。它们的区别仅在于合并子词的方式不同。基于BPE的方法选择出现频次最高的连续字符2-gram合并为新的子词,而基于语言模型的方法则是根据语言模型输出的概率选择要合并哪些子词。
\parinterval 具体来说,基于Word Piece的方法首先将句子切割为字符表示的形式\cite{6289079},并利用该数据训练一个1-gram语言模型,记为$\textrm{logP}(\cdot)$。假设两个相邻的子词单元$a$$b$被合并为新的子词$c$,则整个句子的语言模型得分的变化为$\triangle=\textrm{logP}(c)-\textrm{logP}(a)-\textrm{logP}(b)$。这样,可以不断的选择使$\triangle$最大的两个子词单元进行合并,直到达到预设的词表大小或者句子概率的增量低于某个阈值。而ULM方法以最大化整个句子的概率为目标构建词表\cite{DBLP:conf/acl/Kudo18},具体实现上也不同于基于Word Piece的方法,这里不做详细介绍。 \parinterval 具体来说,基于Word Piece的方法首先将句子切割为字符表示的形式\cite{6289079},并利用该数据训练一个1-gram语言模型,记为$\textrm{logP}(\cdot)$。假设两个相邻的子词单元$a$$b$被合并为新的子词$c$,则整个句子的语言模型得分的变化为$\triangle=\textrm{logP}(c)-\textrm{logP}(a)-\textrm{logP}(b)$。这样,可以不断的选择使$\triangle$最大的两个子词单元进行合并,直到达到预设的词表大小或者句子概率的增量低于某个阈值。而ULM方法以最大化整个句子的概率为目标构建词表\cite{DBLP:conf/acl/Kudo18},具体实现上也不同于基于Word Piece的方法,这里不做详细介绍。
...@@ -420,7 +420,7 @@ y = f(x) ...@@ -420,7 +420,7 @@ y = f(x)
\parinterval 理想的情况下,我们希望反问题的解是{\small\bfnew{适定的}}\index{适定的}(Well-posed)\index{Well-posed}。所谓适定解,需要满足三个条件:解是存在的、解是唯一的、解是稳定的(即$y$微小的变化会导致$x$微小的变化,也被称作解连续)。所有不存在唯一稳定解的问题都被称作{\small\bfnew{不适定问题}}\index{不适定问题}(Ill-posed Problem)\index{Ill-posed Problem}。对于机器学习问题,解的存在性比较容易理解。解的唯一性大多由问题决定。比如,如果把描述问题的函数$f(\cdot)$看作一个$n\times n$矩阵$\mathbf{A}$$x$$y$都看作是$n$维向量。那么$x$不唯一的原因在于$\mathbf{A}$不满秩(非奇异矩阵)。不过,存在性和唯一性并不会对机器学习方法造成太大困扰,因为在实践中往往会找到近似的解。 \parinterval 理想的情况下,我们希望反问题的解是{\small\bfnew{适定的}}\index{适定的}(Well-posed)\index{Well-posed}。所谓适定解,需要满足三个条件:解是存在的、解是唯一的、解是稳定的(即$y$微小的变化会导致$x$微小的变化,也被称作解连续)。所有不存在唯一稳定解的问题都被称作{\small\bfnew{不适定问题}}\index{不适定问题}(Ill-posed Problem)\index{Ill-posed Problem}。对于机器学习问题,解的存在性比较容易理解。解的唯一性大多由问题决定。比如,如果把描述问题的函数$f(\cdot)$看作一个$n\times n$矩阵$\mathbf{A}$$x$$y$都看作是$n$维向量。那么$x$不唯一的原因在于$\mathbf{A}$不满秩(非奇异矩阵)。不过,存在性和唯一性并不会对机器学习方法造成太大困扰,因为在实践中往往会找到近似的解。
\parinterval 但是,解的稳定性却给神经机器翻译带来了很大的挑战。因为神经机器翻译模型非常复杂,里面存在大量的矩阵乘法和非线性变化。这导致$f(\cdot)$往往是不稳定的,也就是说,神经机器翻译中输出$y$ 的微小变化会导致输入$x$的巨大变化。比如,在系统研发中经常会发现,即使训练样本发生很小的变化,模型训练得到的参数会有非常明显的区别。不仅如此,神经机器翻译模型参数解的稳定性还存在两方面问题: \parinterval 但是,解的稳定性却给神经机器翻译带来了很大的挑战。因为神经机器翻译模型非常复杂,里面存在大量的矩阵乘法和非线性变化。这导致$f(\cdot)$往往是不稳定的,也就是说,神经机器翻译中输出$y$ 的微小变化会导致输入$x$的巨大变化。比如,在系统研发中经常会发现,即使训练样本发生很小的变化,模型训练得到的参数会有非常明显的区别。不仅如此,神经机器翻译模型参数解的稳定性还存在两方面问题:
\begin{itemize} \begin{itemize}
\vspace{0.5em} \vspace{0.5em}
...@@ -538,7 +538,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -538,7 +538,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\end{figure} \end{figure}
%---------------------------------------------- %----------------------------------------------
\parinterval 对于新的样本,可以使用Dropout训练之后的模型对其进行推断,但是每个神经元的输出要乘以$1-p$,以保证每层神经元输出的期望和训练时是一样的。另一种常用的做法是,在训练时对于每个神经元的输出乘以$\frac{1}{1-p}$,然后在推断时神经网络可以不经过任何调整即可直接使用。 \parinterval 对于新的样本,可以使用Dropout训练之后的模型对其进行推断,但是每个神经元的输出要乘以$1-p$,以保证每层神经元输出的期望和训练时是一样的。另一种常用的做法是,在训练时对每个神经元的输出乘以$\frac{1}{1-p}$,然后在推断时神经网络可以不经过任何调整就直接使用。
\parinterval Dropout方法的另一种解释是,训练中屏蔽掉一些神经元相当于从原始的神经网络中抽取出了一个子网络。这样,每次训练都在一个随机生成的子网络上进行,而不同子网络之间的参数是共享的。在推断时,则把所有的子网络集成到一起。这种思想也有一些{\small\bfnew{集成学习}}\index{集成学习}(Ensemble Learning)\index{Ensemble Learning}的味道。只不过Dropout中子模型(或子网络)是在指数级空间中采样出来的。由于Dropout可以很好的缓解复杂神经模型的过拟合问题,因此也成为了大多数神经机器翻译系统的标配。 \parinterval Dropout方法的另一种解释是,训练中屏蔽掉一些神经元相当于从原始的神经网络中抽取出了一个子网络。这样,每次训练都在一个随机生成的子网络上进行,而不同子网络之间的参数是共享的。在推断时,则把所有的子网络集成到一起。这种思想也有一些{\small\bfnew{集成学习}}\index{集成学习}(Ensemble Learning)\index{Ensemble Learning}的味道。只不过Dropout中子模型(或子网络)是在指数级空间中采样出来的。由于Dropout可以很好的缓解复杂神经模型的过拟合问题,因此也成为了大多数神经机器翻译系统的标配。
...@@ -559,7 +559,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -559,7 +559,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\end{figure} \end{figure}
%---------------------------------------------- %----------------------------------------------
\parinterval Layer Dropout可以被理解为在一个深网络(即原始网络)中随机采样出一个由若干层网络构成的``浅''网络。不同``浅''网络所对应的同一层的模型参数是共享的。这也达到了对指数级子网络高效训练的目的。需要注意的是,在推断阶段,每层的输出需要乘以$1-p$,确保训练时每层输出的期望和解码是一致的。Layer Dropout可以非常有效的缓解深层网路中的过拟合问题。在\ref{subsection-7.3.1}节还会看到Layer Dropout可以成功帮助我们训练Deep Transformer模型。 \parinterval Layer Dropout可以被理解为在一个深网络(即原始网络)中随机采样出一个由若干层网络构成的``浅''网络。不同``浅''网络所对应的同一层的模型参数是共享的。这也达到了对指数级子网络高效训练的目的。需要注意的是,在推断阶段,每层的输出需要乘以$1-p$,确保训练时每层输出的期望和解码是一致的。Layer Dropout可以非常有效的缓解深层网路中的过拟合问题。在\ref{subsection-7.3.1}节还会看到Layer Dropout可以成功帮助我们训练Deep Transformer模型。
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
% NEW SUB-SECTION % NEW SUB-SECTION
...@@ -623,7 +623,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -623,7 +623,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\parinterval 虽然,理论上宽网络有能力拟合任意的函数,但是获得这种能力的代价是非常高的。在实践中,往往需要增加相当的宽度,以极大的训练代价才能换来少量的性能提升。当神经网络达到一定宽度后这种现象更为严重。``无限''增加宽度显然是不现实的。 \parinterval 虽然,理论上宽网络有能力拟合任意的函数,但是获得这种能力的代价是非常高的。在实践中,往往需要增加相当的宽度,以极大的训练代价才能换来少量的性能提升。当神经网络达到一定宽度后这种现象更为严重。``无限''增加宽度显然是不现实的。
\parinterval 因此,另一种思路是使用更深的网络以增加模型的容量。深网络是指包含更多层的神经网络。相比宽网络的参数量随着宽度呈平方增长,深网络的参数量深度呈线性增长。这带给深网络一个优点:在同样参数量下可以通过更多的非线性变换来对问题进行描述。这也赋予了深网络对复杂问题建模的能力。比如,在图像识别领域,很多先进的系统都是基于很深的神经网络,甚至在一些任务上最好的的结果需要1000 层以上的神经网络。 \parinterval 因此,另一种思路是使用更深的网络以增加模型的容量。深网络是指包含更多层的神经网络。相比宽网络的参数量随着宽度呈平方增长,深网络的参数量随着深度呈线性增长。这带给深网络一个优点:在同样参数量下可以通过更多的非线性变换来对问题进行描述。这也赋予了深网络对复杂问题建模的能力。比如,在图像识别领域,很多先进的系统都是基于很深的神经网络,甚至在一些任务上最好的的结果需要1000 层以上的神经网络。
\parinterval 宽网络和深网络是增加模型表示能力的两个维度。宽网络相当于增强了模型线性变换的能力,将模型的输入在更高维度的空间上进行抽象;深网络通过引入更多的层构建了多个表示空间,通过逐层的变换,在多个表示空间上对输入进行多次抽象。二者在有些情况下甚至可以相互转换。 \parinterval 宽网络和深网络是增加模型表示能力的两个维度。宽网络相当于增强了模型线性变换的能力,将模型的输入在更高维度的空间上进行抽象;深网络通过引入更多的层构建了多个表示空间,通过逐层的变换,在多个表示空间上对输入进行多次抽象。二者在有些情况下甚至可以相互转换。
...@@ -690,7 +690,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -690,7 +690,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\parinterval 然而,批次也不是越大越好,要根据训练数据集的规模与模型的容量做出合理的选择。此外,GPU显存的大小也对批次大小有约束,因为过大的批次可能无法放入GPU显存中。另一方面,在一些场景例中,如增量式训练、领域迁移,往往需要对模型进行微调。这时,常用的做法是使用小批次并固定较小的学习率,防止现有的模型参数发生较大的偏离。 \parinterval 然而,批次也不是越大越好,要根据训练数据集的规模与模型的容量做出合理的选择。此外,GPU显存的大小也对批次大小有约束,因为过大的批次可能无法放入GPU显存中。另一方面,在一些场景例中,如增量式训练、领域迁移,往往需要对模型进行微调。这时,常用的做法是使用小批次并固定较小的学习率,防止现有的模型参数发生较大的偏离。
\parinterval 大多数情况下讨论批次的大小是指单独一块GPU上的数据量,然而考虑到利用数据并行进行分布式训练时,批次大小等于所有GPU 中批次大小的和。下面以Transformer模型为例。通常Transformer-Base模型使用4096词/GPU的批次在8张GPU上进行训练,此时真实批次大小为$4096\times 8=32768$词。伴随着模型容量的进一步增加,例如Transformer-Big模型,由于训练过程中网络的中间表示要消耗大量的GPU显存,可能会考虑减小批次的大小并使用累计梯度的方式来保证稳定的训练。累计梯度是一种大批量训练的常用手段,即按照一定频率缓存多个相邻批次的梯度后再进行参数的更新。比如,为了获取大批次,可以考虑将累计的更新频率设置为2或4。图\ref{fig:7-17}给出了累计梯度的参数更新方法,可以看到使用累积梯度的方式可以减少设备的空闲时间。 \parinterval 大多数情况下批次的大小是指单独一块GPU上的数据量,然而考虑到利用数据并行进行分布式训练时,批次大小等于所有GPU 中批次大小的和。下面以Transformer模型为例。通常Transformer-Base模型使用4096词/GPU的批次在8张GPU上进行训练,此时真实批次大小为$4096\times 8=32768$词。伴随着模型容量的进一步增加,例如Transformer-Big模型,由于训练过程中网络的中间表示要消耗大量的GPU显存,可能会考虑减小批次的大小并使用累计梯度的方式来保证稳定的训练。累计梯度是一种大批量训练的常用手段,即按照一定频率缓存多个相邻批次的梯度后再进行参数的更新。比如,为了获取大批次,可以考虑将累计的更新频率设置为2或4。图\ref{fig:7-17}给出了累计梯度的参数更新方法,可以看到使用累积梯度的方式可以减少设备的空闲时间。
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -701,7 +701,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -701,7 +701,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\end{figure} \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] \begin{table}[htp]
...@@ -727,7 +727,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -727,7 +727,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\begin{itemize} \begin{itemize}
\vspace{0.5em} \vspace{0.5em}
\item 随机生成:最简单的方式是从整个数据集中随机生成批次。这种方式可以有效地保证样本间的随机性,但随机生成的批次中不同句子之间的长度会有较大区别,因此Padding数量较多导致显卡的利用率较低。 \item 随机生成:最简单的方式是从整个数据集中随机生成批次。这种方式可以有效地保证样本间的随机性,但随机生成的批次中不同句子之间的长度会有较大区别,因此Padding数量较多导致显卡的利用率较低。
\vspace{0.5em} \vspace{0.5em}
\item 按句长排序:为了减少显卡利用率低的问题,可以根据源语言或者目标语言的句子长度进行排序,让相邻句长的样本更为相近(图\ref{fig:7-18} )。这样在同一个批次中不会因为句长差异过大造成设备利用率的降低。 \item 按句长排序:为了减少显卡利用率低的问题,可以根据源语言或者目标语言的句子长度进行排序,让相邻句长的样本更为相近(图\ref{fig:7-18} )。这样在同一个批次中不会因为句长差异过大造成设备利用率的降低。
...@@ -807,7 +807,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -807,7 +807,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\vspace{0.5em} \vspace{0.5em}
\item 预测模块,也就是根据已经翻译的历史和源语言句子,预测下一个要生成单词的概率 \footnote{在统计机器翻译中,翻译的每一步也可以预测短语。在神经机器翻译中也有类似于生成短语的方法,但是主流的方法还是按单词为单位进行生成。}。因此预测模块实际上就是一个模型打分装置; \item 预测模块,也就是根据已经翻译的历史和源语言句子,预测下一个要生成单词的概率 \footnote{在统计机器翻译中,翻译的每一步也可以预测短语。在神经机器翻译中也有类似于生成短语的方法,但是主流的方法还是按单词为单位进行生成。}。因此预测模块实际上就是一个模型打分装置;
\vspace{0.5em} \vspace{0.5em}
\item 搜索模块,它会利用预测结果,当前的翻译假设进行打分,并根据模型得分对翻译假设进行排序和剪枝。 \item 搜索模块,它会利用预测结果,当前的翻译假设进行打分,并根据模型得分对翻译假设进行排序和剪枝。
\vspace{0.5em} \vspace{0.5em}
\end{itemize} \end{itemize}
...@@ -853,15 +853,15 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -853,15 +853,15 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\subsubsection{推断加速} \subsubsection{推断加速}
\label{subsection-7.4.1.3} \label{subsection-7.4.1.3}
\parinterval 很多时候,我们需要在翻译速度和翻译精度之间进行平衡。即使是以提升翻译品质为目标的任务(如用BLEU评价),也不得不考虑翻译速度的影响。比如,在WMT和CCMT的一些任务中可能会使用反向翻译构造伪数据,需要大量的机器翻译;无指导机器翻译中也会频繁使用神经机器翻译系统构造训练数据。如果翻译速度过慢会增大实验的周期。从应用的角度看,在很多场景下翻译速度甚至比品质更重要。比如,在线翻译和一些小设备上的机器翻译系统都需要保证相对低的翻译延时,以满足用户体验的最基本要求。虽然,我们希望能有一套又好又快的翻译系统,但是现实的情况是:往往需要通过牺牲一些翻译品质来换取速度的提升。 \parinterval 很多时候,我们需要在翻译速度和翻译精度之间进行平衡。即使是以提升翻译品质为目标的任务(如用BLEU评价),也不得不考虑翻译速度的影响。比如,在WMT和CCMT的一些任务中可能会使用反向翻译构造伪数据,需要大量的机器翻译;无指导机器翻译中也会频繁使用神经机器翻译系统构造训练数据。如果翻译速度过慢会增大实验的周期。从应用的角度看,在很多场景下翻译速度甚至比品质更重要。比如,在线翻译和一些小设备上的机器翻译系统都需要保证相对低的翻译延时,以满足用户体验的最基本要求。虽然,我们希望能有一套又好又快的翻译系统,但是现实的情况是:往往需要通过牺牲一些翻译品质来换取速度的提升。
\parinterval 下面就列举一些常用的神经机器翻译加速方法。这些方法通常是应用在解码器端,因为相比编码器,神经机器翻译的解码端是推断过程中最耗时的部分。 \parinterval 下面就列举一些常用的神经机器翻译加速方法。这些方法通常是应用在解码端,因为相比编码端,神经机器翻译的解码端是推断过程中最耗时的部分。
\vspace{0.5em} \vspace{0.5em}
\noindent {\small\bfnew{a) 输出层的词汇选择}} \noindent {\small\bfnew{a) 输出层的词汇选择}}
\vspace{0.5em} \vspace{0.5em}
\parinterval 神经机器翻译需要对输入和输出的单词进行分布式表示,比如,每一个单词都用一个512维向量进行表示。但是,由于真实的词表通常很大,因此计算并保存这些单词向量表示就会消耗较多的计算和存储资源。特别是对于基于Softmax的输出层,使用大词表往往会占用较多的系统运算时间。虽然可以通过BPE和限制词汇表规模的方法降低输出层计算的负担,但是为了获得可接受的翻译品质,词汇表也不能过小(比如小于10000),输出层仍然十分耗时。 \parinterval 神经机器翻译需要对输入和输出的单词进行分布式表示,比如,每一个单词都用一个512维向量进行表示。但是,由于真实的词表通常很大,因此计算并保存这些单词向量表示就会消耗较多的计算和存储资源。特别是对于基于Softmax的输出层,使用大词表往往会占用较多的系统运算时间。虽然可以通过BPE和限制词汇表规模的方法降低输出层计算的负担,但是为了获得可接受的翻译品质,词汇表也不能过小(比如小于10000),因此输出层仍然十分耗时。
\parinterval 对于这个问题,可以通过改变输出层的网络结构进行缓解\cite{DBLP:conf/acl/JeanCMB15}。一种比较简单的方法是对可能输出的单词进行筛选,简称词汇选择。这里,可以利用类似于统计机器翻译的翻译表,获得每个源语言单词最可能的译文。在翻译过程中,利用注意力机制找到每个目标语位置对应的源语言位置,之后获得这些源语言单词最可能的翻译候选。之后,Softmax只需要在这个有限的翻译候选单词集合上计算,大大降低了输出层的计算量。尤其是对于CPU上的系统,这个方法往往会带来明显的速度提升,同时保证翻译品质。图\ref{fig:7-20}给出了词汇选择方法的示意图。 \parinterval 对于这个问题,可以通过改变输出层的网络结构进行缓解\cite{DBLP:conf/acl/JeanCMB15}。一种比较简单的方法是对可能输出的单词进行筛选,简称词汇选择。这里,可以利用类似于统计机器翻译的翻译表,获得每个源语言单词最可能的译文。在翻译过程中,利用注意力机制找到每个目标语位置对应的源语言位置,之后获得这些源语言单词最可能的翻译候选。之后,Softmax只需要在这个有限的翻译候选单词集合上计算,大大降低了输出层的计算量。尤其是对于CPU上的系统,这个方法往往会带来明显的速度提升,同时保证翻译品质。图\ref{fig:7-20}给出了词汇选择方法的示意图。
...@@ -902,7 +902,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -902,7 +902,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\end{figure} \end{figure}
%---------------------------------------------- %----------------------------------------------
\parinterval 另一种方法是对不同层的参数进行共享。这种方法虽然不能带来直接的提速,但是可以大大减小模型的体积。比如,可以重复使用同一层的参数完成多层的计算。极端一些的情况下,六层网络可以只用一层网络的参数\cite{DBLP:conf/aaai/DabreF19}。不过,在深层模型中(层数$>20$),浅层部分的差异往往较大,而深层(远离输出)之间的相似度会更高。这时可以考虑对深层的部分进行更多的共享。 \parinterval 另一种方法是对不同层的参数进行共享。这种方法虽然不能带来直接的提速,但是可以大大减小模型的体积。比如,可以重复使用同一层的参数完成多层的计算。极端一些的情况下,六层网络可以只使用一层网络的参数\cite{DBLP:conf/aaai/DabreF19}。不过,在深层模型中(层数$>20$),浅层部分的差异往往较大,而深层(远离输出)之间的相似度会更高。这时可以考虑对深层的部分进行更多的共享。
\vspace{0.5em} \vspace{0.5em}
\noindent {\small\bfnew{c) 轻量解码端及小模型}} \noindent {\small\bfnew{c) 轻量解码端及小模型}}
...@@ -928,7 +928,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -928,7 +928,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\vspace{0.5em} \vspace{0.5em}
\item 批次生成策略。对于源语言文本预先给定的情况,通常是按句子长度组织每个批次,即:把长度相似的句子放到一个批次里。这样做的好处是可以尽可能保证一个批次中的内容是``满''的,否则如果句长差异过大会造成批次中有很多位置用占位符填充,产生无用计算。对于实时翻译的情况,批次的组织较为复杂。由于有翻译延时的限制,可能无法等到有足够多的句子就要进行翻译。常见的做法是,设置一个等待的时间,在同一个时间段中的句子可以放到一个批次中(或者几个批次中)。对于高并发的情况,也可以考虑使用不同的Bucket保存不同长度范围的句子,之后将同一个Bucket中的句子进行批量推断。 \item 批次生成策略。对于源语言文本预先给定的情况,通常是按句子长度组织每个批次,即:把长度相似的句子放到一个批次里。这样做的好处是可以尽可能保证一个批次中的内容是``满''的,否则如果句长差异过大会造成批次中有很多位置用占位符填充,产生无用计算。对于实时翻译的情况,批次的组织较为复杂。由于有翻译延时的限制,可能无法等到有足够多的句子就要进行翻译。常见的做法是,设置一个等待的时间,在同一个时间段中的句子可以放到一个批次中(或者几个批次中)。对于高并发的情况,也可以考虑使用不同的Bucket保存不同长度范围的句子,之后将同一个Bucket中的句子进行批量推断。
\vspace{0.5em} \vspace{0.5em}
\item 批次大小的选择。一个批次中的句子数量越多,GPU设备的利用率越高,系统吞吐越大。但是,一个批次中所有句子翻译结束后才能拿到翻译结果,因此批次中有些句子即使已经翻译结束也要等待其它没有完成的句子。也就是说,从单个句子来看,批次越大翻译的延时越长,这也导致在翻译实时性要求较高的场景中,不能使用过大的批次。而且,大批次对GPU显存的消耗更大。因此合理选择批次大小也需要根据具体任务进行调整。为了说明这些问题,图\ref{fig:7-23}展示了不同批次大小下的吞吐、延时和显存消耗。 \item 批次大小的选择。一个批次中的句子数量越多,GPU设备的利用率越高,系统吞吐越大。但是,一个批次中所有句子翻译结束后才能拿到翻译结果,因此批次中有些句子即使已经翻译结束也要等待其它没有完成的句子。也就是说,从单个句子来看,批次越大翻译的延时越长,这也导致在翻译实时性要求较高的场景中,不能使用过大的批次。而且,大批次对GPU显存的消耗更大,因此也需要根据具体任务合理选择批次大小。为了说明这些问题,图\ref{fig:7-23}展示了不同批次大小下的吞吐、延时和显存消耗。
\vspace{0.5em} \vspace{0.5em}
\end{itemize} \end{itemize}
...@@ -1021,7 +1021,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -1021,7 +1021,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\vspace{0.5em} \vspace{0.5em}
\item 交互式翻译。机器翻译的一个应用场景就是交互式机器翻译\cite{Domingo2017Segment,Alvaro2017Interactive,DBLP:conf/emnlp/NepveuLLF04},即机器翻译会根据用户的行为实时进行调整,这时机器翻译的延时会影响用户体验。 \item 交互式翻译。机器翻译的一个应用场景就是交互式机器翻译\cite{Domingo2017Segment,Alvaro2017Interactive,DBLP:conf/emnlp/NepveuLLF04},即机器翻译会根据用户的行为实时进行调整,这时机器翻译的延时会影响用户体验。
\vspace{0.5em} \vspace{0.5em}
\item 互联网机器翻译服务和产品。在大并发时如何保证翻译的低延时也是开发这类应用中必须要考虑的。 \item 互联网机器翻译服务和产品。在大并发时如何保证翻译的低延时也是开发这类应用的过程中必须要考虑的。
\vspace{0.5em} \vspace{0.5em}
\item 机器同声传译。同声传译是机器翻译的一个重要的应用场景。由于同传对实时性的要求,机器翻译的速度是影响整个系统的关键要素。此外,为了保证更好的用户体验,往往需要在讲话者没说完前就开始翻译,也就是根据一句话的前缀进行翻译,当得到后面的内容后再对翻译进行调整。这些都对机器翻译提出了新的要求\cite{DBLP:journals/corr/abs-1810-08398} \item 机器同声传译。同声传译是机器翻译的一个重要的应用场景。由于同传对实时性的要求,机器翻译的速度是影响整个系统的关键要素。此外,为了保证更好的用户体验,往往需要在讲话者没说完前就开始翻译,也就是根据一句话的前缀进行翻译,当得到后面的内容后再对翻译进行调整。这些都对机器翻译提出了新的要求\cite{DBLP:journals/corr/abs-1810-08398}
\vspace{0.5em} \vspace{0.5em}
...@@ -1081,7 +1081,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q ...@@ -1081,7 +1081,7 @@ y_{j}^{ls}=(1-\alpha) \cdot \tilde{y}_j + \alpha \cdot q
\subsubsection{译文长度范围约束} \subsubsection{译文长度范围约束}
\parinterval 神经机器翻译系统进行推断时,可以依靠生成结束符$<$eos$>$来判断一个句子是否翻译完毕。不过,经常会出现生成了很长的译文仍然没有$<$eos$>$出现。另一种极端的情况是,刚刚生成了几个词,$<$eos$>$就出现了。这两种情况对应了译文过长或者过短的情况。为了让译文的长度落在合理的范围,神经机器翻译的推断也会有一个译文长度约束。令$[a,b]$表示一个长度范围,可以定义: \parinterval 神经机器翻译系统进行推断时,可以依靠生成结束符$<$eos$>$来判断一个句子是否翻译完毕。不过,经常会出现生成了很长的译文仍然没有出现$<$eos$>$的问题。另一种极端的情况是,刚刚生成了几个词,$<$eos$>$就出现了。这两种情况对应了译文过长或者过短的情况。为了让译文的长度落在合理的范围,神经机器翻译的推断也会有一个译文长度约束。令$[a,b]$表示一个长度范围,可以定义:
\begin{eqnarray} \begin{eqnarray}
a &=& \omega_{\textrm{low}}\cdot |\mathbf{x}| \\ a &=& \omega_{\textrm{low}}\cdot |\mathbf{x}| \\
b &=& \omega_{\textrm{high}}\cdot |\mathbf{x}| b &=& \omega_{\textrm{high}}\cdot |\mathbf{x}|
...@@ -1105,7 +1105,7 @@ b &=& \omega_{\textrm{high}}\cdot |\mathbf{x}| ...@@ -1105,7 +1105,7 @@ b &=& \omega_{\textrm{high}}\cdot |\mathbf{x}|
\vspace{0.5em} \vspace{0.5em}
\item 机器翻译自动评价指标对过翻译和欠翻译并不敏感。众所周知,在机器翻译系统开发和调试过程中,使用较多的是BLEU等自动评价指标。但是,过翻译和欠翻译在BLEU这样的指标中是没有明确体现的\footnote{BLEU中也有准确率和长度惩罚因子,但是并没有考虑源语言句子和译文之间的对应关系,因此无法捕捉过翻译和欠翻译。}。一个典型的例子是实词漏翻。在人翻译一个句子的时候,如果漏掉一个实词会带来很差甚至不正确的翻译结果,但是在BLEU等指标中可能只是影响几个$n$-gram的匹配。特别是,极大似然训练会使模型对过翻译和欠翻译``更加''不敏感,因为目标函数对这两个问题没有显性的考虑。 \item 机器翻译自动评价指标对过翻译和欠翻译并不敏感。众所周知,在机器翻译系统开发和调试过程中,使用较多的是BLEU等自动评价指标。但是,过翻译和欠翻译在BLEU这样的指标中是没有明确体现的\footnote{BLEU中也有准确率和长度惩罚因子,但是并没有考虑源语言句子和译文之间的对应关系,因此无法捕捉过翻译和欠翻译。}。一个典型的例子是实词漏翻。在人翻译一个句子的时候,如果漏掉一个实词会带来很差甚至不正确的翻译结果,但是在BLEU等指标中可能只是影响几个$n$-gram的匹配。特别是,极大似然训练会使模型对过翻译和欠翻译``更加''不敏感,因为目标函数对这两个问题没有显性的考虑。
\vspace{0.5em} \vspace{0.5em}
\item 神经机器翻译没有对过翻译和欠翻译建模。在统计机器翻译中,由于覆盖度模型会保证所有单词都可以被翻译,且只被翻译一次,因此过翻译和欠翻译等问题很少出现。这也对应了翻译{\small\bfnew{ 充分性}}\index{充分性}(Adequacy)\index{Adequacy}的问题,也就是机器翻译结果能否准确、完整表达源文的意思。而在神经机器翻译中这个问题没有明确的模型与之对应。 \item 神经机器翻译没有对过翻译和欠翻译建模。在统计机器翻译中,由于覆盖度模型会保证所有单词都可以被翻译,且只被翻译一次,因此过翻译和欠翻译等问题很少出现。这也对应了翻译{\small\bfnew{ 充分性}}\index{充分性}(Adequacy)\index{Adequacy}的问题,也就是机器翻译结果能否准确、完整表达源文的意思。而在神经机器翻译中这个问题没有明确的模型与之对应。
\vspace{0.5em} \vspace{0.5em}
\end{itemize} \end{itemize}
...@@ -1124,7 +1124,7 @@ b &=& \omega_{\textrm{high}}\cdot |\mathbf{x}| ...@@ -1124,7 +1124,7 @@ b &=& \omega_{\textrm{high}}\cdot |\mathbf{x}|
\label{eq:7-14} \label{eq:7-14}
\end{eqnarray} \end{eqnarray}
\noindent 公式\ref{eq:7-14}将公式\ref{eq:7-12}中的向下截断方式换为了向上截断。这样,模型可以对过翻译(或重复翻译)有更好的建模能力。不过,这个模型需要在开发集上细致调整$\beta$,也带来了一定的额外工作量。 \noindent 公式\ref{eq:7-14}将公式\ref{eq:7-12}中的向下截断方式换为了向上截断。这样,模型可以对过翻译(或重复翻译)有更好的建模能力。不过,这个模型需要在开发集上细致调整$\beta$,也带来了一定的额外工作量。
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
% NEW SUB-SECTION % NEW SUB-SECTION
...@@ -1191,7 +1191,7 @@ b &=& \omega_{\textrm{high}}\cdot |\mathbf{x}| ...@@ -1191,7 +1191,7 @@ b &=& \omega_{\textrm{high}}\cdot |\mathbf{x}|
\end{figure} \end{figure}
%---------------------------------------------- %----------------------------------------------
\parinterval 公式\ref{eq:7-15}是一种典型的线性插值模型,这类模型在语言建模等任务中已经得到成功应用。从统计学习的角度,多个模型的插值可以有效的降低经验错误率。不过,多模型集成依赖一个假设:这些模型之间需要有一定的互补性。这种互补性有时也体现在多个模型预测的上限上,称为Oracle。比如,可以把这$K$个模型输出中BLEU最高的结果作为Oracle,也可以选择每个预测结果中使BLEU达到最高的译文单词,这样构成的句子作为Oracle。当然,并不是说Oracle提高,模型集成的结果一定会变好。因为Oracle是最理想情况下的结果,而实际预测的结果与Oracle往往有很大差异。如何使用Oracle进行模型优化也是很多研究者在探索的问题。 \parinterval 公式\ref{eq:7-15}是一种典型的线性插值模型,这类模型在语言建模等任务中已经得到成功应用。从统计学习的角度,多个模型的插值可以有效的降低经验错误率。不过,多模型集成依赖一个假设:这些模型之间需要有一定的互补性。这种互补性有时也体现在多个模型预测的上限上,称为Oracle。比如,可以把这$K$个模型输出中BLEU最高的结果作为Oracle,也可以选择每个预测结果中使BLEU达到最高的译文单词,这样构成的句子作为Oracle。当然,并不是说Oracle提高,模型集成的结果一定会变好。因为Oracle是最理想情况下的结果,而实际预测的结果与Oracle往往有很大差异。如何使用Oracle进行模型优化也是很多研究者在探索的问题。
\parinterval 此外,如何构建集成用的模型也是非常重要的,甚至说这部分工作会成为模型集成方法中最困难的部分。绝大多数时候,模型生成并没有固定的方法。系统研发者大多也是``八仙过海、各显神通''。一些常用的方法有: \parinterval 此外,如何构建集成用的模型也是非常重要的,甚至说这部分工作会成为模型集成方法中最困难的部分。绝大多数时候,模型生成并没有固定的方法。系统研发者大多也是``八仙过海、各显神通''。一些常用的方法有:
...@@ -1344,7 +1344,7 @@ z_{l}=\textrm{LN}(x_{l+1}) ...@@ -1344,7 +1344,7 @@ z_{l}=\textrm{LN}(x_{l+1})
g_l=\sum_{i=0}^{l}z_i\times \mathbf{W}_{l,i} g_l=\sum_{i=0}^{l}z_i\times \mathbf{W}_{l,i}
\label{eq:7-21} \label{eq:7-21}
\end{eqnarray} \end{eqnarray}
$g_l$会作为输入的一部分送入第$l+1$层。其网络的结构图\ref{fig:7-29}所示 $g_l$会作为输入的一部分送入第$l+1$层。其网络的结构\ref{fig:7-29}所示
\end{itemize} \end{itemize}
%--------------------------------------------- %---------------------------------------------
...@@ -1366,7 +1366,7 @@ $g_l$会作为输入的一部分送入第$l+1$层。其网络的结构图\ref{fi ...@@ -1366,7 +1366,7 @@ $g_l$会作为输入的一部分送入第$l+1$层。其网络的结构图\ref{fi
\subsubsection{深层模型的训练加速} \subsubsection{深层模型的训练加速}
\parinterval 尽管训练这种窄而深的神经网络对比宽网络有更快的收敛速度,但伴随着训练数据的增加,以及模型进一步的加深,神经网络的训练代价成为不可忽视的问题。例如,在几千万甚至上亿的双语平行语料上训练一个48层的Transformer模型需要将几周的时间能达到收敛\footnote[14]{训练时间的估算是在单台8卡Titan V GPU服务器上得到的}。因此,在保证模型精度不变的前提下如何高效地完成深层网络的训练也是至关重要的。在实践中能够发现,深层网络中相邻层之间具有一定的相似性。因此,一个想法是:能否通过不断复用浅层网络的参数来初始化更深层的网络,渐进式的训练深层网络,避免从头训练整个网络,进而达到加速深层网络训练的目的。 \parinterval 尽管训练这种窄而深的神经网络对比宽网络有更快的收敛速度,但伴随着训练数据的增加,以及模型进一步的加深,神经网络的训练代价成为不可忽视的问题。例如,在几千万甚至上亿的双语平行语料上训练一个48层的Transformer模型需要将几周的时间能达到收敛\footnote[14]{训练时间的估算是在单台8卡Titan V GPU服务器上得到的}。因此,在保证模型精度不变的前提下如何高效地完成深层网络的训练也是至关重要的。在实践中能够发现,深层网络中相邻层之间具有一定的相似性。因此,一个想法是:能否通过不断复用浅层网络的参数来初始化更深层的网络,渐进式的训练深层网络,避免从头训练整个网络,进而达到加速深层网络训练的目的。
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION % NEW SUBSUB-SECTION
...@@ -1395,7 +1395,7 @@ $g_l$会作为输入的一部分送入第$l+1$层。其网络的结构图\ref{fi ...@@ -1395,7 +1395,7 @@ $g_l$会作为输入的一部分送入第$l+1$层。其网络的结构图\ref{fi
\subsubsection{分组稠密连接} \subsubsection{分组稠密连接}
\parinterval 很多研究者已经发现深层网络不同层之间的稠密连接能够很明显地提高信息传递的效率\cite{WangLearning,DBLP:conf/cvpr/HuangLMW17,DBLP:conf/emnlp/DouTWSZ18,DBLP:conf/acl/WuWXTGQLL19}。与此同时,对之前层信息的不断复用有助于得到更好的表示,但随之而来的是网络计算代价过大的问题。由于动态线性层聚合方法(DLCL)在每一次聚合时都需要重新计算之前每一层表示对当前层网络输入的贡献度,因此伴随着编码端整体深度的不断增加,这部分的计算代价变不可忽略。例如,一个基于动态层聚合的48层Transformer模型的训练时间比不使用动态层聚合慢近1.9倍。同时,缓存中间结果也增加了显存的使用量,尽管使用了FP16计算,每张12G显存的GPU上计算的词也不能超过2048个,这导致训练开销急剧增大。 \parinterval 很多研究者已经发现深层网络不同层之间的稠密连接能够很明显地提高信息传递的效率\cite{WangLearning,DBLP:conf/cvpr/HuangLMW17,DBLP:conf/emnlp/DouTWSZ18,DBLP:conf/acl/WuWXTGQLL19}。与此同时,对之前层信息的不断复用有助于得到更好的表示,但随之而来的是网络计算代价过大的问题。由于动态线性层聚合方法(DLCL)在每一次聚合时都需要重新计算之前每一层表示对当前层网络输入的贡献度,因此伴随着编码端整体深度的不断增加,这部分的计算代价变不可忽略。例如,一个基于动态层聚合的48层Transformer模型的训练时间比不使用动态层聚合慢近1.9倍。同时,缓存中间结果也增加了显存的使用量,尽管使用了FP16计算,每张12G显存的GPU上计算的词也不能超过2048个,这导致训练开销急剧增大。
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -1445,7 +1445,7 @@ lr=d_{model}^{-0.5}\cdot step\_num^{-0.5} ...@@ -1445,7 +1445,7 @@ lr=d_{model}^{-0.5}\cdot step\_num^{-0.5}
这里$step\_num$代表学习率重置后更新的步数。 这里$step\_num$代表学习率重置后更新的步数。
\end{itemize} \end{itemize}
\parinterval 综合使用渐进式训练、分组稠密连接、学习率重置策略可以在保证翻译品质不变的前提下,缩减近40\%的训练时间(40层编码器)。同时,加速比伴随着模型的加深与数据集的增大会进一步扩大。 \parinterval 综合使用渐进式训练、分组稠密连接、学习率重置策略可以在保证翻译品质不变的前提下,缩减近40\%的训练时间(40层编码器)。同时,加速比伴随着模型的加深与数据集的增大会进一步扩大。
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION % NEW SUBSUB-SECTION
...@@ -1453,7 +1453,7 @@ lr=d_{model}^{-0.5}\cdot step\_num^{-0.5} ...@@ -1453,7 +1453,7 @@ lr=d_{model}^{-0.5}\cdot step\_num^{-0.5}
\subsubsection{深层模型的鲁棒性训练} \subsubsection{深层模型的鲁棒性训练}
\parinterval 伴随着网络的加深的同时,还会面临另外一个比较严峻的问题\ \dash \ 过拟合。由于参数量的增大,深层网络的输入与输出分布之间的差异也会越来越大,然而不同子层之间的{\small\bfnew{相互适应}}\index{相互适应}(Co-adaptation)\index{Co-adaptation}也会更加的明显,导致任意子层网络对其他子层的依赖过大。这对于训练阶段是有帮助的,因为不同子层可以协同工作从而更好地拟合训练数据。然而这种方式也降低了模型的泛化能力,即深层网络更容易陷入过拟合问题。 \parinterval 伴随着网络的加深,还会面临另外一个比较严峻的问题\ \dash \ 过拟合。由于参数量的增大,深层网络的输入与输出分布之间的差异也会越来越大,然而不同子层之间的{\small\bfnew{相互适应}}\index{相互适应}(Co-adaptation)\index{Co-adaptation}也会更加的明显,导致任意子层网络对其他子层的依赖过大。这对于训练阶段是有帮助的,因为不同子层可以协同工作从而更好地拟合训练数据。然而这种方式也降低了模型的泛化能力,即深层网络更容易陷入过拟合问题。
\parinterval 通常,可以使用Dropout手段用来缓解过拟合问题(见\ref{subsection-7.3.1}节)。不幸的是,尽管目前Transformer模型使用了多种Dropout手段(如Residual Dropout、Attention Dropout、 ReLU Dropout等),过拟合问题在深层网络中仍然存在。从图\ref{fig:7-33}中可以看到,深层网络对比浅层网络在训练集和校验集的困惑度上都有显著的优势,然而网络在训练一段时间后出现校验集困惑度上涨的现象,说明模型已经过拟合于训练数据。 \parinterval 通常,可以使用Dropout手段用来缓解过拟合问题(见\ref{subsection-7.3.1}节)。不幸的是,尽管目前Transformer模型使用了多种Dropout手段(如Residual Dropout、Attention Dropout、 ReLU Dropout等),过拟合问题在深层网络中仍然存在。从图\ref{fig:7-33}中可以看到,深层网络对比浅层网络在训练集和校验集的困惑度上都有显著的优势,然而网络在训练一段时间后出现校验集困惑度上涨的现象,说明模型已经过拟合于训练数据。
...@@ -1593,11 +1593,11 @@ p_l=\frac{l}{2L}\cdot \varphi ...@@ -1593,11 +1593,11 @@ p_l=\frac{l}{2L}\cdot \varphi
\noindent {\small\bfnew{编码器预训练}} \noindent {\small\bfnew{编码器预训练}}
\parinterval 编码器在神经机器翻译中的作用是对源语句子中的信息进行抽象和提取,将离散的词序列编码成一组上下文相关的向量表示,本质上就是一个源语端的句子表示模型。因此,可以使用预训练好的句子级表示模型(比如,BERT和XLM等),来初始化编码器参数。然而在实践中发现,这种参数初始化的方法在一些富资源语种上提升效果并不明显甚至反而有些下降\cite{DBLP:journals/corr/abs-2002-06823}。原因可能在于预训练模型和编码器虽然都是对句子进行表示,但是由于目标任务不一致,二者的参数状态还是存在区别的。因此,也有一些做法将预训练模型和翻译模型在结构上进行融合,将预训练句子模型作为一个独立的模块来为编码器或者解码器提供句子级表示信息\cite{DBLP:journals/corr/abs-2002-06823} \parinterval 编码器在神经机器翻译中的作用是对源语句子中的信息进行抽象和提取,将离散的词序列编码成一组上下文相关的向量表示,本质上就是一个源语端的句子表示模型。因此,可以使用预训练好的句子级表示模型(比如,BERT和XLM等),来初始化编码器参数。然而在实践中发现,这种参数初始化的方法在一些富资源语种上提升效果并不明显甚至反而有些下降\cite{DBLP:journals/corr/abs-2002-06823}。原因可能在于预训练模型和编码器虽然都是对句子进行表示,但是由于目标任务不一致,二者的参数状态还是存在区别的。因此,也有一些做法将预训练模型和翻译模型在结构上进行融合,将预训练句子模型作为一个独立的模块来为编码器或者解码器提供句子级表示信息\cite{DBLP:journals/corr/abs-2002-06823}
\noindent {\small\bfnew{序列到序列预训练}} \noindent {\small\bfnew{序列到序列预训练}}
\parinterval 传统的预训练模型都是针对自然语言理解任务设计的,比如情感分类和命名实体识别等任务。其目的是获得更好的句子表示结果,并用于下游任务。而在机器翻译和文本摘要等序列到序列的语言生成任务,不只包含源语言表示学习的问题,还有序列到序列的映射,以及目标端序列生成的问题,这些知识是无法通过(源语言)单语数据学习到的。为了能够在序列到序列任务上更好的使用单语数据,可以同时使用编码器和解码器的结构完成对单语数据的预训练。 \parinterval 传统的预训练模型都是针对自然语言理解任务设计的,比如情感分类和命名实体识别等任务。其目的是获得更好的句子表示结果,并用于下游任务。而在机器翻译和文本摘要等序列到序列的语言生成任务中,不只包含源语言表示学习的问题,还有序列到序列的映射,以及目标端序列生成的问题,这些知识是无法通过(源语言)单语数据学习到的。为了能够在序列到序列任务上更好地使用单语数据,可以同时使用编码器和解码器的结构完成对单语数据的预训练。
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -1692,7 +1692,7 @@ L_{\textrm{seq}} = - \sum_{\textrm{y}}\textrm{P}_{\textrm{t}} (\mathbf{y}|\mathb ...@@ -1692,7 +1692,7 @@ L_{\textrm{seq}} = - \sum_{\textrm{y}}\textrm{P}_{\textrm{t}} (\mathbf{y}|\mathb
\label{eq:7-29} \label{eq:7-29}
\end{eqnarray} \end{eqnarray}
公式\ref{eq:7-29}要求遍历所有可能的译文序列,并进行求和,当词表大小为$V$,序列长度为$L$时则可能的序列的数量有$V$$L$次幂,这么多的译文将消耗大量的计算资源。因此,会考虑用教师模型的真实输出序列$\hat{\mathbf{y}}$来代替整个空间,即假设$\textrm{P}_{\textrm{t}}(\hat{\mathbf{y}}|\mathbf{x})=1$。于是,目标函数变为: 公式\ref{eq:7-29}要求遍历所有可能的译文序列,并进行求和,当词表大小为$V$,序列长度为$L$则可能的序列的数量有$V$$L$次幂,这么多的译文将消耗大量的计算资源。因此,会考虑用教师模型的真实输出序列$\hat{\mathbf{y}}$来代替整个空间,即假设$\textrm{P}_{\textrm{t}}(\hat{\mathbf{y}}|\mathbf{x})=1$。于是,目标函数变为:
\begin{eqnarray} \begin{eqnarray}
L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x}) L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\label{eq:7-30} \label{eq:7-30}
...@@ -1754,7 +1754,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x}) ...@@ -1754,7 +1754,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\subsection{双向训练} \subsection{双向训练}
\label{subsection-7.5.4} \label{subsection-7.5.4}
\parinterval 到目前为止,神经机器翻译系统都是每次一次训练一个方向的模型,比如,给定中英的双语数据,一次只训练一个中到英或者英到中的翻译系统。既然两个方向的系统都使用同样的双语数据进行训练,那么是否可以一次训练同时得到两个方向的翻译系统呢? \parinterval 到目前为止,神经机器翻译系统都是每次一次只训练一个方向的模型。比如,给定中英的双语数据,一次只训练一个中到英或者英到中的翻译系统。既然两个方向的系统都使用同样的双语数据进行训练,那么是否可以一次训练同时得到两个方向的翻译系统呢?
\parinterval 回顾神经机器翻译系统的建模过程,给定一个互译的句对$(\mathbf s,\mathbf t)$,一个从源语言句子$\mathbf s$到目标语言句子$\mathbf t$的翻译被表示为求条件概率$\textrm{P}(\mathbf t|\mathbf s)$的问题。类似地,一个从目标语言句子$\mathbf t$到源语言句子$\mathbf s$的翻译可以表示为$\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|\mathbf t)$之间是互相独立的。$\textrm{P}(\mathbf t|\mathbf s)$$\textrm{P}(\mathbf s|\mathbf t)$是否真的没有关系呢?比如,$\mathbf s$$\mathbf t$是相同大小的向量,且$\mathbf s$$\mathbf t$的变换是一个线性变换,也就是与一个方阵$\mathbf{W}$做矩阵乘法: \parinterval 回顾神经机器翻译系统的建模过程,给定一个互译的句对$(\mathbf s,\mathbf t)$,一个从源语言句子$\mathbf s$到目标语言句子$\mathbf t$的翻译被表示为求条件概率$\textrm{P}(\mathbf t|\mathbf s)$的问题。类似地,一个从目标语言句子$\mathbf t$到源语言句子$\mathbf s$的翻译可以表示为$\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|\mathbf t)$之间是互相独立的。$\textrm{P}(\mathbf t|\mathbf s)$$\textrm{P}(\mathbf s|\mathbf t)$是否真的没有关系呢?比如,$\mathbf s$$\mathbf t$是相同大小的向量,且$\mathbf s$$\mathbf t$的变换是一个线性变换,也就是与一个方阵$\mathbf{W}$做矩阵乘法:
...@@ -1828,7 +1828,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x}) ...@@ -1828,7 +1828,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\parinterval 重新回顾公式\ref{eq:7-34}对应的目标函数,无监督对偶学习跟回译(假设现在只在一个句对$(\mathbf s,\mathbf t)$上做回译)之间有着很深的内在联系:给定一个句子$\mathbf s$,无监督对偶学习和回译都首先用$\textrm{P}(\mathbf t|\mathbf s)$$\mathbf s$翻译成$\mathbf t$,然后无监督对偶学习最大化$\textrm{P}(\mathbf s|\mathbf t)\textrm{P}(\mathbf t|\mathbf s)$,而回译则是最大化$\textrm{P}(\mathbf s|\mathbf t)$。可以看到,当无监督对偶学习假设$\textrm{P}(\mathbf t|\mathbf s)$是一个完美的翻译模型的时候,它与回译是等价的。此外,在共享两个方向的模型参数$\theta$的情况下,可以看到无监督对偶学习的梯度为$\frac{\partial \textrm{P}(\mathbf s)}{\partial \theta} =\textrm{P}(\mathbf t|\mathbf s) \frac{\partial \textrm{P}(\mathbf s|\mathbf t)}{\partial \theta}+\textrm{P}(\mathbf s|\mathbf t) \frac{\partial \textrm{P}(\mathbf t|\mathbf s)}{\partial \theta} $,而回译的梯度为$\frac{\partial \textrm{P}(\mathbf s|\mathbf t)}{\partial \theta}$。从这个角度出发,无监督对偶学习与回译都在优化语言模型$\textrm{P}(\mathbf s)$这个目标函数,只不过回译使用对$\theta$有偏的梯度估计。 \parinterval 重新回顾公式\ref{eq:7-34}对应的目标函数,无监督对偶学习跟回译(假设现在只在一个句对$(\mathbf s,\mathbf t)$上做回译)之间有着很深的内在联系:给定一个句子$\mathbf s$,无监督对偶学习和回译都首先用$\textrm{P}(\mathbf t|\mathbf s)$$\mathbf s$翻译成$\mathbf t$,然后无监督对偶学习最大化$\textrm{P}(\mathbf s|\mathbf t)\textrm{P}(\mathbf t|\mathbf s)$,而回译则是最大化$\textrm{P}(\mathbf s|\mathbf t)$。可以看到,当无监督对偶学习假设$\textrm{P}(\mathbf t|\mathbf s)$是一个完美的翻译模型的时候,它与回译是等价的。此外,在共享两个方向的模型参数$\theta$的情况下,可以看到无监督对偶学习的梯度为$\frac{\partial \textrm{P}(\mathbf s)}{\partial \theta} =\textrm{P}(\mathbf t|\mathbf s) \frac{\partial \textrm{P}(\mathbf s|\mathbf t)}{\partial \theta}+\textrm{P}(\mathbf s|\mathbf t) \frac{\partial \textrm{P}(\mathbf t|\mathbf s)}{\partial \theta} $,而回译的梯度为$\frac{\partial \textrm{P}(\mathbf s|\mathbf t)}{\partial \theta}$。从这个角度出发,无监督对偶学习与回译都在优化语言模型$\textrm{P}(\mathbf s)$这个目标函数,只不过回译使用对$\theta$有偏的梯度估计。
\parinterval 这个事实说明对回译进行适当的增广后应该能取得与无监督对偶学习相似的结果。{\small\bfnew{ 翻译中回译}}\index{翻译中回译}(On-the-fly Back-translation)\index{On-the-fly Back-translation}就是这样一个例子。一般回译的过程是先把数据集里所有$\mathbf s$都翻译出来,然后只训练$\textrm{P}(\mathbf s|\mathbf t)$。区别于回译,从数据集中采集到一个$\mathbf s$之后,翻译中回译立刻把$\mathbf s$翻译成$\mathbf t$,然后训练$\textrm{P}(\mathbf s|\mathbf t)$,并且下一步迭代中采集一个$\mathbf t$然后训练$\textrm{P}(\mathbf t|\mathbf s)$,这样交替更新$\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|\mathbf t)$$\textrm{P}(\mathbf t|\mathbf s)$的策略允许$\textrm{P}(\mathbf s|\mathbf t)$在两个样本间通过其产生的输出$\mathbf s$来把信息传递到$\textrm{P}(\mathbf t|\mathbf s)$,因此也能获得相近的效果,并且在实现和计算上都非常高效。翻译中回译已经在无监督神经机器翻译系统训练中被广泛使用\cite{lample2019cross} \parinterval 这个事实说明对回译进行适当的增广后应该能取得与无监督对偶学习相似的结果。{\small\bfnew{ 翻译中回译}}\index{翻译中回译}(On-the-fly Back-translation)\index{On-the-fly Back-translation}就是这样一个例子。一般回译的过程是先把数据集里所有$\mathbf s$都翻译出来,然后只训练$\textrm{P}(\mathbf s|\mathbf t)$。区别于回译,从数据集中采集到一个$\mathbf s$之后,翻译中回译立刻把$\mathbf s$翻译成$\mathbf t$,然后训练$\textrm{P}(\mathbf s|\mathbf t)$,并且下一步迭代中采集一个$\mathbf t$然后训练$\textrm{P}(\mathbf t|\mathbf s)$,这样交替更新$\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|\mathbf t)$$\textrm{P}(\mathbf t|\mathbf s)$的策略允许$\textrm{P}(\mathbf s|\mathbf t)$在两个样本间通过其产生的输出$\mathbf s$来把信息传递到$\textrm{P}(\mathbf t|\mathbf s)$,因此也能获得相近的效果,并且在实现和计算上都非常高效。翻译中回译已经在无监督神经机器翻译系统训练中被广泛使用\cite{lample2019cross}
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
% NEW SECTION % NEW SECTION
...@@ -1837,7 +1837,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x}) ...@@ -1837,7 +1837,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\sectionnewpage \sectionnewpage
\section{小结及深入阅读} \section{小结及深入阅读}
\parinterval 神经机器翻译的模型和技术方法已经十分丰富,无论是对基础问题的研究,还是研发实际可用的系统,人们都会面临很多选择。本章,从构建一个足以参加机器翻译比赛的系统出发,对神经机器翻译的数据处理、建模与训练、推断基本问题进行了介绍。其中的许多方法已经在实践中得到验证,具有较好的参考意义。此外,本章也对一些前沿方法进行了讨论,旨在挖掘更具潜力的方向。 \parinterval 神经机器翻译的模型和技术方法已经十分丰富,无论是对基础问题的研究,还是研发实际可用的系统,人们都会面临很多选择。本章,从构建一个足以参加机器翻译比赛的系统出发,对神经机器翻译的数据处理、建模与训练、推断基本问题进行了介绍。其中的许多方法已经在实践中得到验证,具有较好的参考意义。此外,本章也对一些前沿方法进行了讨论,旨在挖掘更具潜力的方向。
\parinterval 除了以上内容,还有一些方向值得关注: \parinterval 除了以上内容,还有一些方向值得关注:
...@@ -1857,7 +1857,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x}) ...@@ -1857,7 +1857,7 @@ L_{\textrm{seq}} = - \textrm{logP}_{\textrm{s}}(\hat{\mathbf{y}} | \mathbf{x})
\vspace{0.5em} \vspace{0.5em}
\item 结构搜索。除了由研究人员手工设计神经网络结构之外,近些年{\small\bfnew{网络结构搜索技术}}\index{网络结构搜索技术}(Neural Architecture Search;NAS)\index{Neural Architecture Search;NAS}也逐渐在包括机器翻译在内的自然语言处理任务中得到广泛关注\cite{elsken2019neural}。不同于前文提到的基于循环神经网络、Transformer结构的机器翻译模型,网络结构搜索旨在通过自动的方式根据提供的训练数据自动学习到最适合于当前任务的神经网络模型结构。目前而言,网络结构搜索的方法已经在自然语言处理的各项任务中崭露头角,在语言模型、命名实体识别等任务中获得优异的成绩\cite{DBLP:conf/iclr/ZophL17,DBLP:conf/emnlp/JiangHXZZ19,liyinqiaoESS},但对于机器翻译任务而言,由于其任务的复杂性,网络结构的搜索空间往往比较大,很难直接对其空间进行搜索,因此研究人员更倾向于对基于现有经验设计的模型结构进行改良。谷歌大脑团队在The Evolved Transformer文章中提出使用进化算法,在Transformer结构基础上对模型结构进行演化,得到更加高效且建模能力更强的机器翻译模型。微软团队也在Neural Architecture Optimization\cite{DBLP:conf/nips/LuoTQCL18}论文中提出NAO的方法,通过将神经网络结构映射到连续空间上进行优化来获得优于初始结构的模型,NAO方法在WMT19机器翻译评测任务中也进行了使用,在英语-芬兰语以及芬兰语-英语的任务上均取得了优异的成绩。 \item 结构搜索。除了由研究人员手工设计神经网络结构之外,近些年{\small\bfnew{网络结构搜索技术}}\index{网络结构搜索技术}(Neural Architecture Search;NAS)\index{Neural Architecture Search;NAS}也逐渐在包括机器翻译在内的自然语言处理任务中得到广泛关注\cite{elsken2019neural}。不同于前文提到的基于循环神经网络、Transformer结构的机器翻译模型,网络结构搜索旨在通过自动的方式根据提供的训练数据自动学习到最适合于当前任务的神经网络模型结构。目前而言,网络结构搜索的方法已经在自然语言处理的各项任务中崭露头角,在语言模型、命名实体识别等任务中获得优异的成绩\cite{DBLP:conf/iclr/ZophL17,DBLP:conf/emnlp/JiangHXZZ19,liyinqiaoESS},但对于机器翻译任务而言,由于其任务的复杂性,网络结构的搜索空间往往比较大,很难直接对其空间进行搜索,因此研究人员更倾向于对基于现有经验设计的模型结构进行改良。谷歌大脑团队在The Evolved Transformer文章中提出使用进化算法,在Transformer结构基础上对模型结构进行演化,得到更加高效且建模能力更强的机器翻译模型。微软团队也在Neural Architecture Optimization\cite{DBLP:conf/nips/LuoTQCL18}论文中提出NAO的方法,通过将神经网络结构映射到连续空间上进行优化来获得优于初始结构的模型,NAO方法在WMT19机器翻译评测任务中也进行了使用,在英语-芬兰语以及芬兰语-英语的任务上均取得了优异的成绩。
\vspace{0.5em} \vspace{0.5em}
\item 与统计机器翻译的结合。尽管神经机器翻译在自动评价和人工评价上都取得比统计机器翻译优异的结果,神经机器翻译仍然面临一些统计机器翻译没有的问题\cite{DBLP:conf/aclnmt/KoehnK17},如神经机器翻译系统会产生漏译的现象,也就是源语句子的一些短语甚至从句没有被翻译,而统计机器翻译因为是把源语里所有短语都翻译出来后进行拼装,因此不会产生这种译文对原文的忠实度低的问题。一个解决的思路就是把统计机器翻译系统和神经机器翻译系统进行结合。目前的方法主要分为两种,一种是模型的改进,比如在神经机器翻译里建模统计机器翻译的概念或者使用统计机器翻译系统的模块,如词对齐,覆盖度等等\cite{DBLP:conf/aaai/HeHWW16},或者是把神经机器翻译系统结合到统计机器翻译系统中,如作为一个特征\cite{DBLP:conf/aclwat/NeubigMN15};第二种是系统融合,在不改变模型的情况下,把来自神经机器翻译系统的输出和统计机器翻译系统的输出进行融合,得到更好的结果,如使用重排序\cite{DBLP:conf/ijcnlp/KhayrallahKDPK17,DBLP:conf/aclwat/NeubigMN15},后处理\cite{niehues-etal-2016-pre},或者把统计机器翻译系统的输出作为神经机器翻译系统解码的约束条件等等\cite{DBLP:conf/eacl/GispertBHS17}。除此之外,也可以把神经机器翻译与翻译记忆相融合\cite{DBLP:conf/aaai/XiaHLS19,DBLP:conf/nlpcc/HeHLL19},这在机器翻译应用中也是非常有趣的方向。 \item 与统计机器翻译的结合。尽管神经机器翻译在自动评价和人工评价上都取得比统计机器翻译优异的结果,神经机器翻译仍然面临一些统计机器翻译没有的问题\cite{DBLP:conf/aclnmt/KoehnK17},如神经机器翻译系统会产生漏译的现象,也就是源语句子的一些短语甚至从句没有被翻译,而统计机器翻译因为是把源语里所有短语都翻译出来后进行拼装,因此不会产生这种译文对原文的忠实度低的问题。一个解决的思路就是把统计机器翻译系统和神经机器翻译系统进行结合。目前的方法主要分为两种,一种是模型的改进,比如在神经机器翻译里建模统计机器翻译的概念或者使用统计机器翻译系统的模块,如词对齐,覆盖度等等\cite{DBLP:conf/aaai/HeHWW16},或者是把神经机器翻译系统结合到统计机器翻译系统中,如作为一个特征\cite{DBLP:conf/aclwat/NeubigMN15};第二种是系统融合,在不改变模型的情况下,把来自神经机器翻译系统的输出和统计机器翻译系统的输出进行融合,得到更好的结果,如使用重排序\cite{DBLP:conf/ijcnlp/KhayrallahKDPK17,DBLP:conf/aclwat/NeubigMN15},后处理\cite{niehues-etal-2016-pre},或者把统计机器翻译系统的输出作为神经机器翻译系统解码的约束条件等等\cite{DBLP:conf/eacl/GispertBHS17}。除此之外,也可以把神经机器翻译与翻译记忆相融合\cite{DBLP:conf/aaai/XiaHLS19,DBLP:conf/nlpcc/HeHLL19},这在机器翻译应用中也是非常有趣的方向。
\end{itemize} \end{itemize}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论