Commit 3517a4c8 by 单韦乔

第六章部分内容修正

parent d960fd20
...@@ -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}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论