Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
M
mtbookv2
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
NiuTrans
mtbookv2
Commits
ef167b14
Commit
ef167b14
authored
Nov 06, 2020
by
曹润柘
Browse files
Options
Browse Files
Download
Plain Diff
合并分支 'caorunzhe' 到 'master'
Caorunzhe 查看合并请求
!345
parents
7d05e01f
5a7d0eb4
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
70 行增加
和
70 行删除
+70
-70
Chapter10/chapter10.tex
+68
-68
Chapter12/chapter12.tex
+2
-2
Chapter9/chapter9.tex
+0
-0
没有找到文件。
Chapter10/chapter10.tex
查看文件 @
ef167b14
...
...
@@ -415,7 +415,7 @@ NMT & 21.7 & 18.7 & -13.7 \\
\parinterval
显然,根据上下文中提到的“没/吃饭”、“很/饿”,最佳的答案是“吃饭”或者“吃东西”。也就是,对序列中某个位置的答案进行预测时需要记忆当前时刻之前的序列信息,因此,循环神经网络应运而生。实际上循环神经网络有着极为广泛的应用,例如语音识别、语言建模以及即将要介绍的神经机器翻译。
\parinterval
{
\chapternine
}
已经对循环神经网络的基本知识进行过介绍。这里再回顾一下。简单来说,循环神经网络由循环单元组成。对于序列中的任意时刻,都有一个循环单元与之对应,它会融合当前时刻的输入和上一时刻循环单元的输出,生成当前时刻的输出。这样每个时刻的信息都会被传递到下一时刻,这也间接达到了记录历史信息的目的。比如,对于序列
$
\seq
{
x
}
=
\{
x
_
1
, x
_
2
,..., x
_
m
\}
$
,循环神经网络会按顺序输出一个序列
$
\seq
{
h
}
=
\{
\
vectorn
{
\emph
{
h
}}_
1
,
\vectorn
{
\emph
{
h
}}_
2
,...,
\vectorn
{
\emph
{
h
}}_
m
\}
$
,其中
$
\vectorn
{
\emph
{
h
}}_
i
$
表示
$
i
$
时刻循环神经网络的输出(通常为一个向量)。
\parinterval
{
\chapternine
}
已经对循环神经网络的基本知识进行过介绍。这里再回顾一下。简单来说,循环神经网络由循环单元组成。对于序列中的任意时刻,都有一个循环单元与之对应,它会融合当前时刻的输入和上一时刻循环单元的输出,生成当前时刻的输出。这样每个时刻的信息都会被传递到下一时刻,这也间接达到了记录历史信息的目的。比如,对于序列
$
\seq
{
x
}
=
\{
x
_
1
, x
_
2
,..., x
_
m
\}
$
,循环神经网络会按顺序输出一个序列
$
\seq
{
h
}
=
\{
\
mathbi
{
h
}_{
1
}
,
\mathbi
{
h
}_{
2
}
,...,
\mathbi
{
h
}_{
m
}
\}
$
,其中
$
\mathbi
{
h
}_{
i
}
$
表示
$
i
$
时刻循环神经网络的输出(通常为一个向量)。
\parinterval
图
\ref
{
fig:10-9
}
展示了一个循环神经网络处理序列问题的实例。当前时刻循环单元的输入由上一个时刻的输出和当前时刻的输入组成,因此也可以理解为,网络当前时刻计算得到的输出是由之前的序列共同决定的,即网络在不断地传递信息的过程中记忆了历史信息。以最后一个时刻的循环单元为例,它在对“开始”这个单词的信息进行处理时,参考了之前所有词(“<sos>
\
让
\
我们”)的信息。
...
...
@@ -461,19 +461,19 @@ NMT & 21.7 & 18.7 & -13.7 \\
\vspace
{
0.5em
}
\item
如何对
$
\seq
{{
x
}}$
和
$
\seq
{{
y
}}_{
<j
}$
进行分布式表示,即
{
\small\sffamily\bfseries
{
词嵌入
}}
(Word Embedding)。首先,将由one-hot向量表示的源语言单词,即由0和1构成的离散化向量表示,转化为实数向量。可以把这个过程记为
$
\textrm
{
e
}_
x
(
\cdot
)
$
。类似的,可以把目标语言序列
$
\seq
{{
y
}}_{
<j
}$
中的每个单词用同样的方式进行表示,记为
$
\textrm
{
e
}_
y
(
\cdot
)
$
。
\vspace
{
0.5em
}
\item
如何在词嵌入的基础上获取整个序列的表示,即句子的
{
\small\sffamily\bfseries
{
表示学习
}}
(Representation Learning)。可以把词嵌入的序列作为循环神经网络的输入,循环神经网络最后一个时刻的输出向量便是整个句子的表示结果。如图
\ref
{
fig:10-11
}
中,编码器最后一个循环单元的输出
$
\
vectorn
{
\emph
{
h
}}_
m
$
被看作是一种包含了源语言句子信息的表示结果,记为
$
\vectorn
{
\emph
{
C
}
}$
。
\item
如何在词嵌入的基础上获取整个序列的表示,即句子的
{
\small\sffamily\bfseries
{
表示学习
}}
(Representation Learning)。可以把词嵌入的序列作为循环神经网络的输入,循环神经网络最后一个时刻的输出向量便是整个句子的表示结果。如图
\ref
{
fig:10-11
}
中,编码器最后一个循环单元的输出
$
\
mathbi
{
h
}_
m
$
被看作是一种包含了源语言句子信息的表示结果,记为
$
\mathbi
{
C
}$
。
\vspace
{
0.5em
}
\item
如何得到每个目标语言单词的概率,即译文单词的
{
\small\sffamily\bfseries
{
生成
}}
\index
{
生成
}
(Generation)
\index
{
Generation
}
。与神经语言模型一样,可以用一个Softmax输出层来获取当前时刻所有单词的分布,即利用Softmax 函数计算目标语言词表中每个单词的概率。令目标语言序列
$
j
$
时刻的循环神经网络的输出向量(或状态)为
$
\
vectorn
{
\emph
{
s
}}_
j
$
。根据循环神经网络的性质,
$
y
_
j
$
的生成只依赖前一个状态
$
\vectorn
{
\emph
{
s
}}_{
j
-
1
}$
和当前时刻的输入(即词嵌入
$
\textrm
{
e
}_
y
(
y
_{
j
-
1
}
)
$
)。同时考虑源语言信息
$
\vectorn
{
\emph
{
C
}
}$
,
$
\funp
{
P
}
(
y
_
j |
\seq
{{
y
}}_{
<j
}
,
\seq
{{
x
}}
)
$
可以被重新定义为:
\item
如何得到每个目标语言单词的概率,即译文单词的
{
\small\sffamily\bfseries
{
生成
}}
\index
{
生成
}
(Generation)
\index
{
Generation
}
。与神经语言模型一样,可以用一个Softmax输出层来获取当前时刻所有单词的分布,即利用Softmax 函数计算目标语言词表中每个单词的概率。令目标语言序列
$
j
$
时刻的循环神经网络的输出向量(或状态)为
$
\
mathbi
{
s
}_
j
$
。根据循环神经网络的性质,
$
y
_
j
$
的生成只依赖前一个状态
$
\mathbi
{
s
}_{
j
-
1
}$
和当前时刻的输入(即词嵌入
$
\textrm
{
e
}_
y
(
y
_{
j
-
1
}
)
$
)。同时考虑源语言信息
$
\mathbi
{
C
}$
,
$
\funp
{
P
}
(
y
_
j |
\seq
{{
y
}}_{
<j
}
,
\seq
{{
x
}}
)
$
可以被重新定义为:
\begin{eqnarray}
\funp
{
P
}
(y
_
j |
\seq
{{
y
}}_{
<j
}
,
\seq
{{
x
}}
)
\equiv
\funp
{
P
}
(
{
y
_
j |
\
vectorn
{
\emph
{
s
}}_{
j-1
}
,y
_{
j-1
}
,
\vectorn
{
\emph
{
C
}
}}
)
\funp
{
P
}
(y
_
j |
\seq
{{
y
}}_{
<j
}
,
\seq
{{
x
}}
)
\equiv
\funp
{
P
}
(
{
y
_
j |
\
mathbi
{
s
}_{
j-1
}
,y
_{
j-1
}
,
\mathbi
{
C
}}
)
\label
{
eq:10-4
}
\end{eqnarray}
$
\funp
{
P
}
(
{
y
_
j |
\
vectorn
{
\emph
{
s
}}_{
j
-
1
}
,y
_{
j
-
1
}
,
\vectorn
{
\emph
{
C
}}}
)
$
由Softmax实现,Softmax的输入是循环神经网络
$
j
$
时刻的输出。在具体实现时,
$
\vectorn
{
\emph
{
C
}}$
可以被简单的作为第一个时刻循环单元的输入,即,当
$
j
=
1
$
时,解码器的循环神经网络会读入编码器最后一个隐层状态
$
\vectorn
{
\emph
{
h
}}_
m
$
(也就是
$
\vectorn
{
\emph
{
C
}}$
),而其他时刻的隐层状态不直接与
$
\vectorn
{
\emph
{
C
}
}$
相关。最终,
$
\funp
{
P
}
(
y
_
j |
\seq
{{
y
}}_{
<j
}
,
\seq
{{
x
}}
)
$
被表示为:
$
\funp
{
P
}
(
{
y
_
j |
\
mathbi
{
s
}_{
j
-
1
}
,y
_{
j
-
1
}
,
\mathbi
{
C
}}
)
$
由Softmax实现,Softmax的输入是循环神经网络
$
j
$
时刻的输出。在具体实现时,
$
\mathbi
{
C
}$
可以被简单的作为第一个时刻循环单元的输入,即,当
$
j
=
1
$
时,解码器的循环神经网络会读入编码器最后一个隐层状态
$
\mathbi
{
h
}_
m
$
(也就是
$
\mathbi
{
C
}$
),而其他时刻的隐层状态不直接与
$
\mathbi
{
C
}$
相关。最终,
$
\funp
{
P
}
(
y
_
j |
\seq
{{
y
}}_{
<j
}
,
\seq
{{
x
}}
)
$
被表示为:
\begin{eqnarray}
\funp
{
P
}
(y
_
j |
\seq
{{
y
}}_{
<j
}
,
\seq
{{
x
}}
)
\equiv
\left
\{
\begin{array}
{
ll
}
\funp
{
P
}
(y
_
j |
\
vectorn
{
\emph
{
C
}
}
,y
_{
j-1
}
)
&
j=1
\\
\funp
{
P
}
(y
_
j|
\
vectorn
{
\emph
{
s
}
}_{
j-1
}
,y
_{
j-1
}
)
\quad
&
j>1
\funp
{
P
}
(y
_
j |
\
mathbi
{
C
}
,y
_{
j-1
}
)
&
j=1
\\
\funp
{
P
}
(y
_
j|
\
mathbi
{
s
}_{
j-1
}
,y
_{
j-1
}
)
\quad
&
j>1
\end{array}
\right
.
\label
{
eq:10-5
}
\end{eqnarray}
...
...
@@ -490,14 +490,14 @@ $\funp{P}({y_j | \vectorn{\emph{s}}_{j-1} ,y_{j-1},\vectorn{\emph{C}}})$由Softm
%----------------------------------------------
\parinterval
输入层(词嵌入)和输出层(Softmax)的内容已在
{
\chapternine
}
进行了介绍,因此这里的核心内容是设计循环神经网络结构,即设计循环单元的结构。至今,研究人员已经提出了很多优秀的循环单元结构。其中循环神经网络(RNN)
是最原始的循环单元结构。在RNN中,对于序列
$
\seq
{{
x
}}
=
\{
\
vectorn
{
\emph
{
x
}}_
1
,
\vectorn
{
\emph
{
x
}}_
2
,...,
\vectorn
{
\emph
{
x
}}_
m
\}
$
,每个时刻
$
t
$
都对应一个循环单元,它的输出是一个向量
$
\vectorn
{
\emph
{
h
}
}_
t
$
,可以被描述为:
是最原始的循环单元结构。在RNN中,对于序列
$
\seq
{{
x
}}
=
\{
\
mathbi
{
x
}_
1
,
\mathbi
{
x
}_
2
,...,
\mathbi
{
x
}_
m
\}
$
,每个时刻
$
t
$
都对应一个循环单元,它的输出是一个向量
$
\mathbi
{
h
}_
t
$
,可以被描述为:
\begin{eqnarray}
\
vectorn
{
\emph
{
h
}}_
t=f(
\vectorn
{
\emph
{
x
}}_
t
\vectorn
{
\emph
{
U
}}
+
\vectorn
{
\emph
{
h
}}_{
t-1
}
\vectorn
{
\emph
{
W
}}
+
\vectorn
{
\emph
{
b
}
}
)
\
mathbi
{
h
}_
t=f(
\mathbi
{
x
}_
t
\mathbi
{
U
}
+
\mathbi
{
h
}_{
t-1
}
\mathbi
{
W
}
+
\mathbi
{
b
}
)
\label
{
eq:10-11
}
\end{eqnarray}
\noindent
其中
$
\
vectorn
{
\emph
{
x
}}_
t
$
是当前时刻的输入,
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
是上一时刻循环单元的输出,
$
f
(
\cdot
)
$
是激活函数,
$
\vectorn
{
\emph
{
U
}}$
和
$
\vectorn
{
\emph
{
W
}}$
是参数矩阵,
$
\vectorn
{
\emph
{
b
}
}$
是偏置。
\noindent
其中
$
\
mathbi
{
x
}_
t
$
是当前时刻的输入,
$
\mathbi
{
h
}_{
t
-
1
}$
是上一时刻循环单元的输出,
$
f
(
\cdot
)
$
是激活函数,
$
\mathbi
{
U
}$
和
$
\mathbi
{
W
}$
是参数矩阵,
$
\mathbi
{
b
}$
是偏置。
\parinterval
虽然RNN的结构很简单,但是已经具有了对序列信息进行记忆的能力。实际上,基于RNN结构的神经语言模型已经能够取得比传统
$
n
$
-gram语言模型更优异的性能。在机器翻译中,RNN也可以做为入门或者快速原型所使用的神经网络结构。后面会进一步介绍更加先进的循环单元结构,以及搭建循环神经网络中的常用技术。
...
...
@@ -510,7 +510,7 @@ $\funp{P}({y_j | \vectorn{\emph{s}}_{j-1} ,y_{j-1},\vectorn{\emph{C}}})$由Softm
\parinterval
RNN结构使得当前时刻循环单元的状态包含了之前时间步的状态信息。但是这种对历史信息的记忆并不是无损的,随着序列变长,RNN的记忆信息的损失越来越严重。在很多长序列处理任务中(如长文本生成)都观测到了类似现象。对于这个问题,研究者门提出了
{
\small\bfnew
{
长短时记忆
}}
\index
{
长短时记忆
}
(Long Short-term Memory)
\index
{
Long Short-term Memory,LSTM
}
模型,也就是常说的LSTM模型
\upcite
{
HochreiterLong
}
。
\parinterval
LSTM模型是RNN模型的一种改进。相比RNN仅传递前一时刻的状态
$
\
vectorn
{
\emph
{
h
}}_{
t
-
1
}$
,LSTM会同时传递两部分信息:状态信息
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
和记忆信息
$
\vectorn
{
\emph
{
c
}}_{
t
-
1
}$
。这里,
$
\vectorn
{
\emph
{
c
}}_{
t
-
1
}$
是新引入的变量,它也是循环单元的一部分,用于显性的记录需要记录的历史内容,
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
和
$
\vectorn
{
\emph
{
c
}
}_{
t
-
1
}$
在循环单元中会相互作用。LSTM通过“门”单元来动态地选择遗忘多少以前的信息和记忆多少当前的信息。LSTM中所使用的门单元结构如图
\ref
{
fig:10-15
}
所示,包括遗忘门,输入门和输出门。图中
$
\sigma
$
代表Sigmoid函数,它将函数输入映射为0-1范围内的实数,用来充当门控信号。
\parinterval
LSTM模型是RNN模型的一种改进。相比RNN仅传递前一时刻的状态
$
\
mathbi
{
h
}_{
t
-
1
}$
,LSTM会同时传递两部分信息:状态信息
$
\mathbi
{
h
}_{
t
-
1
}$
和记忆信息
$
\mathbi
{
c
}_{
t
-
1
}$
。这里,
$
\mathbi
{
c
}_{
t
-
1
}$
是新引入的变量,它也是循环单元的一部分,用于显性的记录需要记录的历史内容,
$
\mathbi
{
h
}_{
t
-
1
}$
和
$
\mathbi
{
c
}_{
t
-
1
}$
在循环单元中会相互作用。LSTM通过“门”单元来动态地选择遗忘多少以前的信息和记忆多少当前的信息。LSTM中所使用的门单元结构如图
\ref
{
fig:10-15
}
所示,包括遗忘门,输入门和输出门。图中
$
\sigma
$
代表Sigmoid函数,它将函数输入映射为0-1范围内的实数,用来充当门控信号。
%----------------------------------------------
\begin{figure}
[htp]
...
...
@@ -528,36 +528,36 @@ $\funp{P}({y_j | \vectorn{\emph{s}}_{j-1} ,y_{j-1},\vectorn{\emph{C}}})$由Softm
\begin{itemize}
\vspace
{
0.5em
}
\item
{
\small\sffamily\bfseries
{
遗忘
}}
\index
{
遗忘
}
。顾名思义,遗忘的目的是忘记一些历史,在LSTM中通过遗忘门实现,其结构如图
\ref
{
fig:10-15
}
(a)所示。
$
\
vectorn
{
\emph
{
x
}}_{
t
}$
表示时刻
$
t
$
的输入向量,
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
是时刻
$
t
-
1
$
的循环单元的输出,
$
\vectorn
{
\emph
{
x
}}_{
t
}$
和
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
都作为
$
t
$
时刻循环单元的输入。
$
\sigma
$
将对
$
\vectorn
{
\emph
{
x
}}_{
t
}$
和
$
\vectorn
{
\emph
{
h
}
}_{
t
-
1
}$
进行筛选,以决定遗忘的信息,其计算公式如下:
\item
{
\small\sffamily\bfseries
{
遗忘
}}
\index
{
遗忘
}
。顾名思义,遗忘的目的是忘记一些历史,在LSTM中通过遗忘门实现,其结构如图
\ref
{
fig:10-15
}
(a)所示。
$
\
mathbi
{
x
}_{
t
}$
表示时刻
$
t
$
的输入向量,
$
\mathbi
{
h
}_{
t
-
1
}$
是时刻
$
t
-
1
$
的循环单元的输出,
$
\mathbi
{
x
}_{
t
}$
和
$
\mathbi
{
h
}_{
t
-
1
}$
都作为
$
t
$
时刻循环单元的输入。
$
\sigma
$
将对
$
\mathbi
{
x
}_{
t
}$
和
$
\mathbi
{
h
}_{
t
-
1
}$
进行筛选,以决定遗忘的信息,其计算公式如下:
\begin{eqnarray}
\
vectorn
{
\emph
{
f
}}_
t=
\sigma
(
\vectorn
{
\emph
{
W
}}_
f [
\vectorn
{
\emph
{
h
}}_{
t-1
}
,
\vectorn
{
\emph
{
x
}}_{
t
}
] +
\vectorn
{
\emph
{
b
}
}_
f )
\
mathbi
{
f
}_
t=
\sigma
(
\mathbi
{
W
}_
f [
\mathbi
{
h
}_{
t-1
}
,
\mathbi
{
x
}_{
t
}
] +
\mathbi
{
b
}_
f )
\label
{
eq:10-12
}
\end{eqnarray}
这里,
$
\
vectorn
{
\emph
{
W
}}_
f
$
是权值,
$
\vectorn
{
\emph
{
b
}}_
f
$
是偏置,
$
[
\vectorn
{
\emph
{
h
}}_{
t
-
1
}
,
\vectorn
{
\emph
{
x
}}_{
t
}
]
$
表示两个向量的拼接。该公式可以解释为,对
$
[
\vectorn
{
\emph
{
h
}}_{
t
-
1
}
,
\vectorn
{
\emph
{
x
}}_{
t
}
]
$
进行变换,并得到一个实数向量
$
\vectorn
{
\emph
{
f
}}_
t
$
。
$
\vectorn
{
\emph
{
f
}
}_
t
$
的每一维都可以被理解为一个“门”,它决定可以有多少信息被留下(或遗忘)。
这里,
$
\
mathbi
{
W
}_
f
$
是权值,
$
\mathbi
{
b
}_
f
$
是偏置,
$
[
\mathbi
{
h
}_{
t
-
1
}
,
\mathbi
{
x
}_{
t
}
]
$
表示两个向量的拼接。该公式可以解释为,对
$
[
\mathbi
{
h
}_{
t
-
1
}
,
\mathbi
{
x
}_{
t
}
]
$
进行变换,并得到一个实数向量
$
\mathbi
{
f
}_
t
$
。
$
\mathbi
{
f
}_
t
$
的每一维都可以被理解为一个“门”,它决定可以有多少信息被留下(或遗忘)。
\vspace
{
0.5em
}
\item
{
\small\sffamily\bfseries
{
记忆更新
}}
\index
{
记忆更新
}
。首先,要生成当前时刻需要新增加的信息,该部分由输入门完成,其结构如图
\ref
{
fig:10-15
}
(b)红色线部分,图中“
$
\bigotimes
$
”表示进行点乘操作。输入门的计算分为两部分,首先利用
$
\sigma
$
决定门控参数
$
\
vectorn
{
\emph
{
i
}}_
t
$
,然后通过Tanh函数得到新的信息
$
\hat
{
\vectorn
{
\emph
{
c
}
}}_
t
$
,具体公式如下:
\item
{
\small\sffamily\bfseries
{
记忆更新
}}
\index
{
记忆更新
}
。首先,要生成当前时刻需要新增加的信息,该部分由输入门完成,其结构如图
\ref
{
fig:10-15
}
(b)红色线部分,图中“
$
\bigotimes
$
”表示进行点乘操作。输入门的计算分为两部分,首先利用
$
\sigma
$
决定门控参数
$
\
mathbi
{
i
}_
t
$
,然后通过Tanh函数得到新的信息
$
\hat
{
\mathbi
{
C
}}_
t
$
,具体公式如下:
\begin{eqnarray}
\
vectorn
{
\emph
{
i
}}_
t
&
=
&
\sigma
(
\vectorn
{
\emph
{
W
}}_
i [
\vectorn
{
\emph
{
h
}}_{
t-1
}
,
\vectorn
{
\emph
{
x
}}_{
t
}
] +
\vectorn
{
\emph
{
b
}
}_
i )
\label
{
eq:10-13
}
\\
\hat
{
\
vectorn
{
\emph
{
c
}}}_
t
&
=
&
\textrm
{
Tanh
}
(
\vectorn
{
\emph
{
W
}}_
c [
\vectorn
{
\emph
{
h
}}_{
t-1
}
,
\vectorn
{
\emph
{
x
}}_{
t
}
] +
\vectorn
{
\emph
{
b
}}_
c
)
\label
{
eq:10-14
}
\
mathbi
{
i
}_
t
&
=
&
\sigma
(
\mathbi
{
W
}_
i [
\mathbi
{
h
}_{
t-1
}
,
\mathbi
{
x
}_{
t
}
] +
\mathbi
{
b
}_
i )
\label
{
eq:10-13
}
\\
\hat
{
\
mathbi
{
C
}}_{
t
}
&
=
&
\textrm
{
Tanh
}
(
\mathbi
{
W
}_{
c
}
[
\mathbi
{
h
}_{
t-1
}
,
\mathbi
{
x
}_{
t
}
] +
\mathbi
{
b
}_{
c
}
)
\label
{
eq:10-14
}
\end{eqnarray}
之后,用
$
\
vectorn
{
\emph
{
i
}}_
t
$
点乘
$
\hat
{
\vectorn
{
\emph
{
c
}}}_
t
$
,得到当前需要记忆的信息,记为
$
\vectorn
{
\emph
{
i
}}_
t
\cdot
\hat
{
\vectorn
{
\emph
{
c
}}}_
t
$
。接下来需要更新旧的信息
$
\vectorn
{
\emph
{
c
}}_{
t
-
1
}$
,得到新的记忆信息
$
\vectorn
{
\emph
{
c
}}_
t
$
,更新的操作如图
\ref
{
fig:10-15
}
(c)红色线部分所示,“
$
\bigoplus
$
”表示相加。具体规则是通过遗忘门选择忘记一部分上文信息
$
\vectorn
{
\emph
{
f
}}_
t
$
,通过输入门计算新增的信息
$
\vectorn
{
\emph
{
i
}}_
t
\cdot
\hat
{
\vectorn
{
\emph
{
c
}
}}_
t
$
,然后根据“
$
\bigotimes
$
”门与“
$
\bigoplus
$
”门进行相应的乘法和加法计算:
之后,用
$
\
mathbi
{
i
}_
t
$
点乘
$
\hat
{
\mathbi
{
C
}}_{
t
}$
,得到当前需要记忆的信息,记为
$
\mathbi
{
i
}_
t
\cdot
\hat
{
\mathbi
{
C
}}_
t
$
。接下来需要更新旧的信息
$
\mathbi
{
c
}_{
t
-
1
}$
,得到新的记忆信息
$
\mathbi
{
c
}_
t
$
,更新的操作如图
\ref
{
fig:10-15
}
(c)红色线部分所示,“
$
\bigoplus
$
”表示相加。具体规则是通过遗忘门选择忘记一部分上文信息
$
\mathbi
{
f
}_
t
$
,通过输入门计算新增的信息
$
\mathbi
{
i
}_
t
\cdot
\hat
{
\mathbi
{
C
}}_
t
$
,然后根据“
$
\bigotimes
$
”门与“
$
\bigoplus
$
”门进行相应的乘法和加法计算:
\begin{eqnarray}
\
vectorn
{
\emph
{
c
}}_
t =
\vectorn
{
\emph
{
f
}}_
t
\cdot
\vectorn
{
\emph
{
c
}}_{
t-1
}
+
\vectorn
{
\emph
{
i
}}_
t
\cdot
\hat
{
\vectorn
{
\emph
{
c
}}_
t
}
\
mathbi
{
c
}_
t =
\mathbi
{
f
}_
t
\cdot
\mathbi
{
c
}_{
t-1
}
+
\mathbi
{
i
}_
t
\cdot
\hat
{
\mathbi
{
c
}}_{
t
}
\label
{
eq:10-15
}
\end{eqnarray}
\vspace
{
-1.0em
}
\item
{
\small\sffamily\bfseries
{
输出
}}
\index
{
输出
}
。该部分使用输出门计算最终的输出信息
$
\
vectorn
{
\emph
{
h
}}_
t
$
,其结构如图
\ref
{
fig:10-15
}
(d)红色线部分所示。在输出门中,首先将
$
\vectorn
{
\emph
{
x
}}_
t
$
和
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
通过
$
\sigma
$
函数变换得到
$
\vectorn
{
\emph
{
o
}}_
t
$
。其次,将上一步得到的新记忆信息
$
\vectorn
{
\emph
{
c
}
}_
t
$
通过Tanh函数进行变换,得到值在[-1,1]范围的向量。最后将这两部分进行点乘,具体公式如下:
\item
{
\small\sffamily\bfseries
{
输出
}}
\index
{
输出
}
。该部分使用输出门计算最终的输出信息
$
\
mathbi
{
h
}_
t
$
,其结构如图
\ref
{
fig:10-15
}
(d)红色线部分所示。在输出门中,首先将
$
\mathbi
{
x
}_
t
$
和
$
\mathbi
{
h
}_{
t
-
1
}$
通过
$
\sigma
$
函数变换得到
$
\mathbi
{
o
}_
t
$
。其次,将上一步得到的新记忆信息
$
\mathbi
{
c
}_
t
$
通过Tanh函数进行变换,得到值在[-1,1]范围的向量。最后将这两部分进行点乘,具体公式如下:
\begin{eqnarray}
\
vectorn
{
\emph
{
o
}}_
t
&
=
&
\sigma
(
\vectorn
{
\emph
{
W
}}_
o [
\vectorn
{
\emph
{
h
}}_{
t-1
}
,
\vectorn
{
\emph
{
x
}}_{
t
}
] +
\vectorn
{
\emph
{
b
}
}_
o )
\label
{
eq:10-16
}
\\
\
vectorn
{
\emph
{
h
}}_
t
&
=
&
\vectorn
{
\emph
{
o
}}_
t
\cdot
\textrm
{
Tanh
}
(
\vectorn
{
\emph
{
c
}
}_
t)
\label
{
eq:6-17
}
\
mathbi
{
o
}_
t
&
=
&
\sigma
(
\mathbi
{
W
}_
o [
\mathbi
{
h
}_{
t-1
}
,
\mathbi
{
x
}_{
t
}
] +
\mathbi
{
b
}_
o )
\label
{
eq:10-16
}
\\
\
mathbi
{
h
}_
t
&
=
&
\mathbi
{
o
}_
t
\cdot
\textrm
{
Tanh
}
(
\mathbi
{
c
}_
t)
\label
{
eq:6-17
}
\end{eqnarray}
\vspace
{
0.5em
}
\end{itemize}
\parinterval
LSTM的完整结构如图
\ref
{
fig:10-16
}
所示,模型的参数包括:参数矩阵
$
\
vectorn
{
\emph
{
W
}}_
f
$
、
$
\vectorn
{
\emph
{
W
}}_
i
$
、
$
\vectorn
{
\emph
{
W
}}_
c
$
、
\\
$
\vectorn
{
\emph
{
W
}}_
o
$
和偏置
$
\vectorn
{
\emph
{
b
}}_
f
$
、
$
\vectorn
{
\emph
{
b
}}_
i
$
、
$
\vectorn
{
\emph
{
b
}}_
c
$
、
$
\vectorn
{
\emph
{
b
}}_
o
$
。可以看出,
$
\vectorn
{
\emph
{
h
}}_
t
$
是由
$
\vectorn
{
\emph
{
c
}}_{
t
-
1
}$
、
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
与
$
\vectorn
{
\emph
{
x
}
}_
t
$
共同决定的。此外,上述公式中激活函数的选择是根据函数各自的特点决定的。
\parinterval
LSTM的完整结构如图
\ref
{
fig:10-16
}
所示,模型的参数包括:参数矩阵
$
\
mathbi
{
W
}_
f
$
、
$
\mathbi
{
W
}_
i
$
、
$
\mathbi
{
W
}_
c
$
、
\\
$
\mathbi
{
W
}_
o
$
和偏置
$
\mathbi
{
b
}_
f
$
、
$
\mathbi
{
b
}_
i
$
、
$
\mathbi
{
b
}_
c
$
、
$
\mathbi
{
b
}_
o
$
。可以看出,
$
\mathbi
{
h
}_
t
$
是由
$
\mathbi
{
c
}_{
t
-
1
}$
、
$
\mathbi
{
h
}_{
t
-
1
}$
与
$
\mathbi
{
x
}_
t
$
共同决定的。此外,上述公式中激活函数的选择是根据函数各自的特点决定的。
%----------------------------------------------
\begin{figure}
[htp]
...
...
@@ -574,7 +574,7 @@ $\funp{P}({y_j | \vectorn{\emph{s}}_{j-1} ,y_{j-1},\vectorn{\emph{C}}})$由Softm
\subsection
{
门控循环单元
}
\parinterval
LSTM 通过门控单元控制传递状态,忘记不重要的信息,记住必要的历史信息,在长序列上取得了很好的效果,但是其进行了许多门信号的计算,较为繁琐。
{
\small\bfnew
{
门循环单元
}}
\index
{
门循环单元
}
(Gated Recurrent Unit,GRU)
\index
{
Gated Recurrent Unit,GRU
}
作为一个LSTM的变种,它继承了LSTM中利用门控单元控制信息传递的思想,并对LSTM进行了简化
\upcite
{
Cho2014Learning
}
。它把循环单元状态
$
\
vectorn
{
\emph
{
h
}}_
t
$
和记忆
$
\vectorn
{
\emph
{
c
}}_
t
$
合并成一个状态
$
\vectorn
{
\emph
{
h
}
}_
t
$
,同时使用了更少的门控单元,大大提升了计算效率。
\parinterval
LSTM 通过门控单元控制传递状态,忘记不重要的信息,记住必要的历史信息,在长序列上取得了很好的效果,但是其进行了许多门信号的计算,较为繁琐。
{
\small\bfnew
{
门循环单元
}}
\index
{
门循环单元
}
(Gated Recurrent Unit,GRU)
\index
{
Gated Recurrent Unit,GRU
}
作为一个LSTM的变种,它继承了LSTM中利用门控单元控制信息传递的思想,并对LSTM进行了简化
\upcite
{
Cho2014Learning
}
。它把循环单元状态
$
\
mathbi
{
h
}_
t
$
和记忆
$
\mathbi
{
c
}_
t
$
合并成一个状态
$
\mathbi
{
h
}_
t
$
,同时使用了更少的门控单元,大大提升了计算效率。
%----------------------------------------------
\begin{figure}
[htp]
...
...
@@ -587,27 +587,27 @@ $\funp{P}({y_j | \vectorn{\emph{s}}_{j-1} ,y_{j-1},\vectorn{\emph{C}}})$由Softm
\end{figure}
%----------------------------------------------
\parinterval
GRU的输入和RNN是一样的,由输入
$
\
vectorn
{
\emph
{
x
}}_
t
$
和
$
t
-
1
$
时刻的状态
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
组成。GRU只有两个门信号,分别是重置门和更新门。重置门
$
\vectorn
{
\emph
{
r
}
}_
t
$
用来控制前一时刻隐藏状态的记忆程度,其结构如图
\ref
{
fig:10-17
}
(a)。更新门用来更新记忆,使用一个门同时完成遗忘和记忆两种操作,其结构如图
\ref
{
fig:10-17
}
(b)。重置门和更新门的计算公式如下:
\parinterval
GRU的输入和RNN是一样的,由输入
$
\
mathbi
{
x
}_
t
$
和
$
t
-
1
$
时刻的状态
$
\mathbi
{
h
}_{
t
-
1
}$
组成。GRU只有两个门信号,分别是重置门和更新门。重置门
$
\mathbi
{
r
}_
t
$
用来控制前一时刻隐藏状态的记忆程度,其结构如图
\ref
{
fig:10-17
}
(a)。更新门用来更新记忆,使用一个门同时完成遗忘和记忆两种操作,其结构如图
\ref
{
fig:10-17
}
(b)。重置门和更新门的计算公式如下:
\begin{eqnarray}
\
vectorn
{
\emph
{
r
}}_
t
&
=
&
\sigma
(
\vectorn
{
\emph
{
W
}}_
r [
\vectorn
{
\emph
{
h
}}_{
t-1
}
,
\vectorn
{
\emph
{
x
}
}_{
t
}
] )
\label
{
eq:10-18
}
\\
\
vectorn
{
\emph
{
u
}}_
t
&
=
&
\sigma
(
\vectorn
{
\emph
{
W
}}_
u [
\vectorn
{
\emph
{
h
}}_{
t-1
}
,
\vectorn
{
\emph
{
x
}
}_{
t
}
])
\label
{
eq:10-19
}
\
mathbi
{
r
}_
t
&
=
&
\sigma
(
\mathbi
{
W
}_
r [
\mathbi
{
h
}_{
t-1
}
,
\mathbi
{
x
}_{
t
}
] )
\label
{
eq:10-18
}
\\
\
mathbi
{
u
}_
t
&
=
&
\sigma
(
\mathbi
{
W
}_
u [
\mathbi
{
h
}_{
t-1
}
,
\mathbi
{
x
}_{
t
}
])
\label
{
eq:10-19
}
\end{eqnarray}
\parinterval
当完成了重置门和更新门计算后,就需要更新当前隐藏状态,如图
\ref
{
fig:10-17
}
(c)所示。在计算得到了重置门的权重
$
\
vectorn
{
\emph
{
r
}}_
t
$
后,使用其对前一时刻的状态
$
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
进行重置(
$
\vectorn
{
\emph
{
r
}}_
t
\cdot
\vectorn
{
\emph
{
h
}}_{
t
-
1
}$
),将重置后的结果与
$
\vectorn
{
\emph
{
x
}
}_
t
$
拼接,通过Tanh激活函数将数据变换到[-1,1]范围内:
\parinterval
当完成了重置门和更新门计算后,就需要更新当前隐藏状态,如图
\ref
{
fig:10-17
}
(c)所示。在计算得到了重置门的权重
$
\
mathbi
{
r
}_
t
$
后,使用其对前一时刻的状态
$
\mathbi
{
h
}_{
t
-
1
}$
进行重置(
$
\mathbi
{
r
}_
t
\cdot
\mathbi
{
h
}_{
t
-
1
}$
),将重置后的结果与
$
\mathbi
{
x
}_
t
$
拼接,通过Tanh激活函数将数据变换到[-1,1]范围内:
\begin{eqnarray}
\hat
{
\
vectorn
{
\emph
{
h
}}}_
t =
\textrm
{
Tanh
}
(
\vectorn
{
\emph
{
W
}}_
h [
\vectorn
{
\emph
{
r
}}_
t
\cdot
\vectorn
{
\emph
{
h
}}_{
t-1
}
,
\vectorn
{
\emph
{
x
}
}_{
t
}
])
\hat
{
\
mathbi
{
h
}}_
t =
\textrm
{
Tanh
}
(
\mathbi
{
W
}_
h [
\mathbi
{
r
}_
t
\cdot
\mathbi
{
h
}_{
t-1
}
,
\mathbi
{
x
}_{
t
}
])
\label
{
eq:10-20
}
\end{eqnarray}
\parinterval
$
\hat
{
\
vectorn
{
\emph
{
h
}}}_
t
$
在包含了输入信息
$
\vectorn
{
\emph
{
x
}}_
t
$
的同时,引入了
$
\vectorn
{
\emph
{
h
}
}_{
t
-
1
}$
的信息,可以理解为,记忆了当前时刻的状态。下一步是计算更新后的隐藏状态也就是更新记忆,如下所示:
\parinterval
$
\hat
{
\
mathbi
{
h
}}_
t
$
在包含了输入信息
$
\mathbi
{
x
}_
t
$
的同时,引入了
$
\mathbi
{
h
}_{
t
-
1
}$
的信息,可以理解为,记忆了当前时刻的状态。下一步是计算更新后的隐藏状态也就是更新记忆,如下所示:
\begin{eqnarray}
\
vectorn
{
\emph
{
h
}}_
t = (1-
\vectorn
{
\emph
{
u
}}_
t)
\cdot
\vectorn
{
\emph
{
h
}}_{
t-1
}
+
\vectorn
{
\emph
{
u
}}_
t
\cdot
\hat
{
\vectorn
{
\emph
{
h
}
}}_
t
\
mathbi
{
h
}_
t = (1-
\mathbi
{
u
}_
t)
\cdot
\mathbi
{
h
}_{
t-1
}
+
\mathbi
{
u
}_
t
\cdot
\hat
{
\mathbi
{
h
}}_
t
\label
{
eq:10-21
}
\end{eqnarray}
\noindent
这里,
$
\
vectorn
{
\emph
{
u
}}_
t
$
是更新门中得到的权重,将
$
\vectorn
{
\emph
{
u
}}_
t
$
作用于
$
\hat
{
\vectorn
{
\emph
{
h
}}}_
t
$
表示对当前时刻的状态进行“遗忘”,舍弃一些不重要的信息,将
$
(
1
-
\vectorn
{
\emph
{
u
}}_
t
)
$
作用于
$
\vectorn
{
\emph
{
h
}
}_{
t
-
1
}$
,用于对上一时刻隐藏状态进行选择性记忆。
\noindent
这里,
$
\
mathbi
{
u
}_
t
$
是更新门中得到的权重,将
$
\mathbi
{
u
}_
t
$
作用于
$
\hat
{
\mathbi
{
h
}}_
t
$
表示对当前时刻的状态进行“遗忘”,舍弃一些不重要的信息,将
$
(
1
-
\mathbi
{
u
}_
t
)
$
作用于
$
\mathbi
{
h
}_{
t
-
1
}$
,用于对上一时刻隐藏状态进行选择性记忆。
\parinterval
GRU的输入输出和RNN类似,其采用与LSTM类似的门控思想,达到捕获长距离依赖信息的目的。此外,GRU比LSTM少了一个门结构,而且参数只有
$
\
vectorn
{
\emph
{
W
}}_
r
$
、
$
\vectorn
{
\emph
{
W
}}_
u
$
和
$
\vectorn
{
\emph
{
W
}
}_
h
$
。因此,GRU具有比LSTM高的运算效率,在系统研发中也经常被使用。
\parinterval
GRU的输入输出和RNN类似,其采用与LSTM类似的门控思想,达到捕获长距离依赖信息的目的。此外,GRU比LSTM少了一个门结构,而且参数只有
$
\
mathbi
{
W
}_
r
$
、
$
\mathbi
{
W
}_
u
$
和
$
\mathbi
{
W
}_
h
$
。因此,GRU具有比LSTM高的运算效率,在系统研发中也经常被使用。
%----------------------------------------------------------------------------------------
% NEW SUB-SECTION
...
...
@@ -701,7 +701,7 @@ $\funp{P}({y_j | \vectorn{\emph{s}}_{j-1} ,y_{j-1},\vectorn{\emph{C}}})$由Softm
\parinterval
显然,以上问题的根本原因在于所使用的表示模型还比较“弱”。因此需要一个更强大的表示模型,在生成目标语言单词时能够有选择地获取源语言句子中更有用的部分。更准确的说,对于要生成的目标语单词,相关性更高的源语言片段应该在源语言句子的表示中体现出来,而不是将所有的源语言单词一视同仁。在神经机器翻译中引入注意力机制正是为了达到这个目的
\upcite
{
bahdanau2014neural,DBLP:journals/corr/LuongPM15
}
。实际上,除了机器翻译,注意力机制也被成功地应用于图像处理、语音识别、自然语言处理等其他任务。而正是注意力机制的引入,使得包括机器翻译在内很多自然语言处理系统得到了飞跃发展。
\parinterval
神经机器翻译中的注意力机制并不复杂。对于每个目标语言单词
$
y
_
j
$
,系统生成一个源语言表示向量
$
\
vectorn
{
\emph
{{
C
}}}_
j
$
与之对应,
$
\vectorn
{
\emph
{
C
}}_
j
$
会包含生成
$
y
_
j
$
所需的源语言的信息,或者说
$
\vectorn
{
\emph
{
C
}}_
j
$
是一种包含目标语言单词与源语言单词对应关系的源语言表示。相比用一个静态的表示
$
\vectorn
{
\emph
{
C
}}$
,注意机制使用的是动态的表示
$
\vectorn
{
\emph
{
C
}}_
j
$
。
$
\vectorn
{
\emph
{
C
}
}_
j
$
也被称作对于目标语言位置
$
j
$
的
{
\small\bfnew
{
上下文向量
}}
\index
{
上下文向量
}
(Context Vector
\index
{
Context Vector
}
)。图
\ref
{
fig:10-22
}
对比了未引入注意力机制和引入了注意力机制的编码器- 解码器结构。可以看出,在注意力模型中,对于每一个目标单词的生成,都会额外引入一个单独的上下文向量参与运算。
\parinterval
神经机器翻译中的注意力机制并不复杂。对于每个目标语言单词
$
y
_
j
$
,系统生成一个源语言表示向量
$
\
mathbi
{
C
}_
j
$
与之对应,
$
\mathbi
{
C
}_
j
$
会包含生成
$
y
_
j
$
所需的源语言的信息,或者说
$
\mathbi
{
C
}_
j
$
是一种包含目标语言单词与源语言单词对应关系的源语言表示。相比用一个静态的表示
$
\mathbi
{
C
}$
,注意机制使用的是动态的表示
$
\mathbi
{
C
}_
j
$
。
$
\mathbi
{
C
}_
j
$
也被称作对于目标语言位置
$
j
$
的
{
\small\bfnew
{
上下文向量
}}
\index
{
上下文向量
}
(Context Vector
\index
{
Context Vector
}
)。图
\ref
{
fig:10-22
}
对比了未引入注意力机制和引入了注意力机制的编码器- 解码器结构。可以看出,在注意力模型中,对于每一个目标单词的生成,都会额外引入一个单独的上下文向量参与运算。
%----------------------------------------------
\begin{figure}
[htp]
...
...
@@ -718,21 +718,21 @@ $\funp{P}({y_j | \vectorn{\emph{s}}_{j-1} ,y_{j-1},\vectorn{\emph{C}}})$由Softm
\subsection
{
上下文向量的计算
}
\label
{
sec:10.1.3
}
\parinterval
神经机器翻译中,注意力机制的核心是:针对不同目标语言单词生成不同的上下文向量。这里,可以将注意力机制看做是一种对接收到的信息的加权处理。对于更重要的信息赋予更高的权重即更高的关注度,对于贡献度较低的信息分配较低的权重,弱化其对结果的影响。这样,
$
\
vectorn
{
\emph
{
C
}
}_
j
$
可以包含更多对当前目标语言位置有贡献的源语言片段的信息。
\parinterval
神经机器翻译中,注意力机制的核心是:针对不同目标语言单词生成不同的上下文向量。这里,可以将注意力机制看做是一种对接收到的信息的加权处理。对于更重要的信息赋予更高的权重即更高的关注度,对于贡献度较低的信息分配较低的权重,弱化其对结果的影响。这样,
$
\
mathbi
{
C
}_
j
$
可以包含更多对当前目标语言位置有贡献的源语言片段的信息。
\parinterval
根据这种思想,上下文向量
$
\
vectorn
{
\emph
{
C
}}_
j
$
被定义为对不同时间步编码器输出的状态序列
$
\{
\vectorn
{
\emph
{
h
}}_
1
,
\vectorn
{
\emph
{
h
}}_
2
,...,
\vectorn
{
\emph
{
h
}
}_
m
\}
$
进行加权求和,如下:
\parinterval
根据这种思想,上下文向量
$
\
mathbi
{
C
}_
j
$
被定义为对不同时间步编码器输出的状态序列
$
\{
\mathbi
{
h
}_
1
,
\mathbi
{
h
}_
2
,...,
\mathbi
{
h
}_
m
\}
$
进行加权求和,如下:
\begin{eqnarray}
\
vectorn
{
\emph
{
C
}}_
j=
\sum
_{
i
}
\alpha
_{
i,j
}
\vectorn
{
\emph
{
h
}
}_
i
\
mathbi
{
C
}_
j=
\sum
_{
i
}
\alpha
_{
i,j
}
\mathbi
{
h
}_
i
\label
{
eq:10-22
}
\end{eqnarray}
\noindent
其中,
$
\alpha
_{
i,j
}$
是
{
\small\sffamily\bfseries
{
注意力权重
}}
\index
{
注意力权重
}
(Attention Weight)
\index
{
Attention Weight
}
,它表示目标语言第
$
j
$
个位置与源语言第
$
i
$
个位置之间的相关性大小。这里,将每个时间步编码器的输出
$
\
vectorn
{
\emph
{
h
}}_
i
$
看作源语言位置
$
i
$
的表示结果。进行翻译时,解码端可以根据当前的位置
$
j
$
,通过控制不同
$
\vectorn
{
\emph
{
h
}}_
i
$
的权重得到
$
\vectorn
{
\emph
{
C
}}_
j
$
,使得对目标语言位置
$
j
$
贡献大的
$
\vectorn
{
\emph
{
h
}}_
i
$
对
$
\vectorn
{
\emph
{
C
}}_
j
$
的影响增大。也就是说,
$
\vectorn
{
\emph
{
C
}}_
j
$
实际上就是
\{
${
\vectorn
{
\emph
{
h
}}_
1
,
\vectorn
{
\emph
{
h
}}_
2
,...,
\vectorn
{
\emph
{
h
}}_
m
}$
\}
的一种组合,只不过不同的
$
\vectorn
{
\emph
{
h
}}_
i
$
会根据对目标端的贡献给予不同的权重。图
\ref
{
fig:10-23
}
展示了上下文向量
$
\vectorn
{
\emph
{
C
}
}_
j
$
的计算过程。
\noindent
其中,
$
\alpha
_{
i,j
}$
是
{
\small\sffamily\bfseries
{
注意力权重
}}
\index
{
注意力权重
}
(Attention Weight)
\index
{
Attention Weight
}
,它表示目标语言第
$
j
$
个位置与源语言第
$
i
$
个位置之间的相关性大小。这里,将每个时间步编码器的输出
$
\
mathbi
{
h
}_
i
$
看作源语言位置
$
i
$
的表示结果。进行翻译时,解码端可以根据当前的位置
$
j
$
,通过控制不同
$
\mathbi
{
h
}_
i
$
的权重得到
$
\mathbi
{
C
}_
j
$
,使得对目标语言位置
$
j
$
贡献大的
$
\mathbi
{
h
}_
i
$
对
$
\mathbi
{
C
}_
j
$
的影响增大。也就是说,
$
\mathbi
{
C
}_
j
$
实际上就是
\{
${
\mathbi
{
h
}_
1
,
\mathbi
{
h
}_
2
,...,
\mathbi
{
h
}_
m
}$
\}
的一种组合,只不过不同的
$
\mathbi
{
h
}_
i
$
会根据对目标端的贡献给予不同的权重。图
\ref
{
fig:10-23
}
展示了上下文向量
$
\mathbi
{
C
}_
j
$
的计算过程。
%----------------------------------------------
\begin{figure}
[htp]
\centering
\input
{
./Chapter10/Figures/figure-calculation-process-of-context-vector-c
}
\caption
{
上下文向量
$
\
vectorn
{
\emph
{
C
}
}_
j
$
的计算过程
}
\caption
{
上下文向量
$
\
mathbi
{
C
}_
j
$
的计算过程
}
\label
{
fig:10-23
}
\end{figure}
%----------------------------------------------
...
...
@@ -741,25 +741,25 @@ $\funp{P}({y_j | \vectorn{\emph{s}}_{j-1} ,y_{j-1},\vectorn{\emph{C}}})$由Softm
\begin{itemize}
\vspace
{
0.5em
}
\item
使用目标语言上一时刻循环单元的输出
$
\
vectorn
{
\emph
{
s
}}_{
j
-
1
}$
与源语言第
$
i
$
个位置的表示
$
\vectorn
{
\emph
{
h
}
}_
i
$
之间的相关性,其用来表示目标语言位置
$
j
$
对源语言位置
$
i
$
的关注程度,记为
$
\beta
_{
i,j
}$
,由函数
$
a
(
\cdot
)
$
实现:
\item
使用目标语言上一时刻循环单元的输出
$
\
mathbi
{
s
}_{
j
-
1
}$
与源语言第
$
i
$
个位置的表示
$
\mathbi
{
h
}_
i
$
之间的相关性,其用来表示目标语言位置
$
j
$
对源语言位置
$
i
$
的关注程度,记为
$
\beta
_{
i,j
}$
,由函数
$
a
(
\cdot
)
$
实现:
\begin{eqnarray}
\beta
_{
i,j
}
= a(
\
vectorn
{
\emph
{
s
}}_{
j-1
}
,
\vectorn
{
\emph
{
h
}
}_
i)
\beta
_{
i,j
}
= a(
\
mathbi
{
s
}_{
j-1
}
,
\mathbi
{
h
}_
i)
\label
{
eq:10-23
}
\end{eqnarray}
$
a
(
\cdot
)
$
可以被看作是目标语言表示和源语言表示的一种“统一化”,即把源语言和目标语言表示映射在同一个语义空间,进而语义相近的内容有更大的相似性。该函数有多种计算方式,比如,向量乘、向量夹角、单层神经网络等,数学表达如下:
\begin{eqnarray}
a (
\
vectorn
{
\emph
{
s
}}
,
\vectorn
{
\emph
{
h
}
}
) =
\left\{
\begin{array}
{
ll
}
\
vectorn
{
\emph
{
s
}}
\vectorn
{
\emph
{
h
}
}^{
\textrm
{
T
}}
&
\textrm
{
向量乘
}
\\
\textrm
{
cos
}
(
\
vectorn
{
\emph
{
s
}}
,
\vectorn
{
\emph
{
h
}
}
)
&
\textrm
{
向量夹角
}
\\
\
vectorn
{
\emph
{
s
}}
\vectorn
{
\emph
{
W
}}
\vectorn
{
\emph
{
h
}
}^{
\textrm
{
T
}}
&
\textrm
{
线性模型
}
\\
\textrm
{
TanH
}
(
\
vectorn
{
\emph
{
W
}}
[
\vectorn
{
\emph
{
s
}}
,
\vectorn
{
\emph
{
h
}}
])
\vectorn
{
\emph
{
v
}}^{
\textrm
{
T
}}
&
\textrm
{
拼接
}
[
\vectorn
{
\emph
{
s
}}
,
\vectorn
{
\emph
{
h
}
}
]+
\textrm
{
单层网络
}
a (
\
mathbi
{
s
}
,
\mathbi
{
h
}
) =
\left\{
\begin{array}
{
ll
}
\
mathbi
{
s
}
\mathbi
{
h
}^{
\textrm
{
T
}}
&
\textrm
{
向量乘
}
\\
\textrm
{
cos
}
(
\
mathbi
{
s
}
,
\mathbi
{
h
}
)
&
\textrm
{
向量夹角
}
\\
\
mathbi
{
s
}
\mathbi
{
W
}
\mathbi
{
h
}^{
\textrm
{
T
}}
&
\textrm
{
线性模型
}
\\
\textrm
{
TanH
}
(
\
mathbi
{
W
}
[
\mathbi
{
s
}
,
\mathbi
{
h
}
])
\mathbi
{
v
}^{
\textrm
{
T
}}
&
\textrm
{
拼接
}
[
\mathbi
{
s
}
,
\mathbi
{
h
}
]+
\textrm
{
单层网络
}
\end{array}
\right
.
\label
{
eq:10-24
}
\end{eqnarray}
其中
$
\
vectorn
{
\emph
{
W
}}$
和
$
\vectorn
{
\emph
{
v
}
}$
是可学习的参数。
其中
$
\
mathbi
{
W
}$
和
$
\mathbi
{
v
}$
是可学习的参数。
\vspace
{
0.5em
}
\item
进一步,利用Softmax函数,将相关性系数
$
\beta
_{
i,j
}$
进行指数归一化处理,得到注意力权重
$
\alpha
_{
i,j
}$
:
\vspace
{
0.5em
}
...
...
@@ -783,7 +783,7 @@ a (\vectorn{\emph{s}},\vectorn{\emph{h}}) = \left\{ \begin{array}{ll}
\vspace
{
0.5em
}
\end{itemize}
\parinterval
图
\ref
{
fig:10-25
}
展示了一个上下文向量的计算过程实例。首先,计算目标语言第一个单词“Have”与源语言中的所有单词的相关性,即注意力权重,对应图中第一列
$
\alpha
_{
i,
1
}$
,则当前时刻所使用的上下文向量
$
\
vectorn
{
\emph
{
C
}}_
1
=
\sum
_{
i
=
1
}^
8
\alpha
_{
i,
1
}
\vectorn
{
\emph
{
h
}}_
i
$
;然后,计算第二个单词“you”的注意力权重对应第二列
$
\alpha
_{
i,
2
}$
,其上下文向量
$
\vectorn
{
\emph
{
C
}}_
2
=
\sum
_{
i
=
1
}^
8
\alpha
_{
i,
2
}
\vectorn
{
\emph
{
h
}}_
i
$
,以此类推,可以得到任意目标语言位置
$
j
$
的上下文向量
$
\vectorn
{
\emph
{
C
}
}_
j
$
。很容易看出,不同目标语言单词的上下文向量对应的源语言词的权重
$
\alpha
_{
i,j
}$
是不同的,不同的注意力权重为不同位置赋予了不同的重要性。
\parinterval
图
\ref
{
fig:10-25
}
展示了一个上下文向量的计算过程实例。首先,计算目标语言第一个单词“Have”与源语言中的所有单词的相关性,即注意力权重,对应图中第一列
$
\alpha
_{
i,
1
}$
,则当前时刻所使用的上下文向量
$
\
mathbi
{
C
}_
1
=
\sum
_{
i
=
1
}^
8
\alpha
_{
i,
1
}
\mathbi
{
h
}_
i
$
;然后,计算第二个单词“you”的注意力权重对应第二列
$
\alpha
_{
i,
2
}$
,其上下文向量
$
\mathbi
{
C
}_
2
=
\sum
_{
i
=
1
}^
8
\alpha
_{
i,
2
}
\mathbi
{
h
}_
i
$
,以此类推,可以得到任意目标语言位置
$
j
$
的上下文向量
$
\mathbi
{
C
}_
j
$
。很容易看出,不同目标语言单词的上下文向量对应的源语言词的权重
$
\alpha
_{
i,j
}$
是不同的,不同的注意力权重为不同位置赋予了不同的重要性。
%----------------------------------------------
\begin{figure}
[htp]
...
...
@@ -794,13 +794,13 @@ a (\vectorn{\emph{s}},\vectorn{\emph{h}}) = \left\{ \begin{array}{ll}
\end{figure}
%----------------------------------------------
\parinterval
在
\ref
{
sec:10.3.1
}
节中,公式
\eqref
{
eq:10-5
}
描述了目标语言单词生成概率
$
\funp
{
P
}
(
y
_
j |
\
vectorn
{
\emph
{
y
}}_{
<j
}
,
\vectorn
{
\emph
{
x
}}
)
$
。在引入注意力机制后,不同时刻的上下文向量
$
\vectorn
{
\emph
{
C
}}_
j
$
替换了传统模型中固定的句子表示
$
\vectorn
{
\emph
{
C
}
}$
。描述如下:
\parinterval
在
\ref
{
sec:10.3.1
}
节中,公式
\eqref
{
eq:10-5
}
描述了目标语言单词生成概率
$
\funp
{
P
}
(
y
_
j |
\
mathbi
{
y
}_{
<j
}
,
\mathbi
{
x
}
)
$
。在引入注意力机制后,不同时刻的上下文向量
$
\mathbi
{
C
}_
j
$
替换了传统模型中固定的句子表示
$
\mathbi
{
C
}$
。描述如下:
\begin{eqnarray}
\funp
{
P
}
(y
_
j |
\
vectorn
{
\emph
{
y
}}_{
<j
}
,
\vectorn
{
\emph
{
x
}}
)
\equiv
\funp
{
P
}
(y
_
j |
\vectorn
{
\emph
{
s
}}_{
j-1
}
,y
_{
j-1
}
,
\vectorn
{
\emph
{
C
}
}_
j )
\funp
{
P
}
(y
_
j |
\
mathbi
{
y
}_{
<j
}
,
\mathbi
{
x
}
)
\equiv
\funp
{
P
}
(y
_
j |
\mathbi
{
s
}_{
j-1
}
,y
_{
j-1
}
,
\mathbi
{
C
}_
j )
\label
{
eq:10-26
}
\end{eqnarray}
\parinterval
这样,可以在生成每个
$
y
_
j
$
时动态的使用不同的源语言表示
$
\
vectorn
{
\emph
{
C
}
}_
j
$
,并更准确地捕捉源语言和目标语言不同位置之间的相关性。表
\ref
{
tab:10-7
}
展示了引入注意力机制前后译文单词生成公式的对比。
\parinterval
这样,可以在生成每个
$
y
_
j
$
时动态的使用不同的源语言表示
$
\
mathbi
{
C
}_
j
$
,并更准确地捕捉源语言和目标语言不同位置之间的相关性。表
\ref
{
tab:10-7
}
展示了引入注意力机制前后译文单词生成公式的对比。
\vspace
{
0.5em
}
%----------------------------------------------
...
...
@@ -810,8 +810,8 @@ a (\vectorn{\emph{s}},\vectorn{\emph{h}}) = \left\{ \begin{array}{ll}
\label
{
tab:10-7
}
\begin{tabular}
{
l | l
}
\rule
{
0pt
}{
13pt
}
引入注意力之前
&
引入注意力之后
\\
\hline
\rule
{
0pt
}{
16pt
}
$
\textrm
{
have
}
=
\argmax
_{
y
_
1
}
\funp
{
P
}
(
y
_
1
|
\
vectorn
{
\emph
{
C
}}
, y
_
0
)
$
&$
\textrm
{
have
}
=
\argmax
_{
y
_
1
}
\funp
{
P
}
(
y
_
1
|
\vectorn
{
\emph
{
C
}
}_
1
, y
_
0
)
$
\\
\rule
{
0pt
}{
16pt
}
$
\textrm
{
you
}
=
\argmax
_{
y
_
2
}
\funp
{
P
}
(
y
_
2
|
\
vectorn
{
\emph
{
s
}}_
1
, y
_
1
)
$
&$
\textrm
{
you
}
=
\argmax
_{
y
_
2
}
\funp
{
P
}
(
y
_
2
|
\vectorn
{
\emph
{
s
}}_
1
,
\vectorn
{
\emph
{
C
}
}_
2
, y
_
1
)
$
\\
\rule
{
0pt
}{
16pt
}
$
\textrm
{
have
}
=
\argmax
_{
y
_
1
}
\funp
{
P
}
(
y
_
1
|
\
mathbi
{
C
}
, y
_
0
)
$
&$
\textrm
{
have
}
=
\argmax
_{
y
_
1
}
\funp
{
P
}
(
y
_
1
|
\mathbi
{
C
}_
1
, y
_
0
)
$
\\
\rule
{
0pt
}{
16pt
}
$
\textrm
{
you
}
=
\argmax
_{
y
_
2
}
\funp
{
P
}
(
y
_
2
|
\
mathbi
{
s
}_
1
, y
_
1
)
$
&$
\textrm
{
you
}
=
\argmax
_{
y
_
2
}
\funp
{
P
}
(
y
_
2
|
\mathbi
{
s
}_
1
,
\mathbi
{
C
}_
2
, y
_
1
)
$
\\
\end{tabular}
\end{table}
%----------------------------------------------
...
...
@@ -823,7 +823,7 @@ a (\vectorn{\emph{s}},\vectorn{\emph{h}}) = \left\{ \begin{array}{ll}
\label
{
sec:10.1.4
}
\vspace
{
0.5em
}
\parinterval
从前面的描述可以看出,注意力机制在机器翻译中就是要回答一个问题:给定一个目标语言位置
$
j
$
和一系列源语言的不同位置上的表示
\{
${
\
vectorn
{
\emph
{
h
}}_
i
}$
\}
,如何得到一个新的表示
$
\hat
{
\vectorn
{
\emph
{
h
}
}}$
,使得它与目标语言位置
$
j
$
对应得最好?
\parinterval
从前面的描述可以看出,注意力机制在机器翻译中就是要回答一个问题:给定一个目标语言位置
$
j
$
和一系列源语言的不同位置上的表示
\{
${
\
mathbi
{
h
}_
i
}$
\}
,如何得到一个新的表示
$
\hat
{
\mathbi
{
h
}}$
,使得它与目标语言位置
$
j
$
对应得最好?
\parinterval
那么,如何理解这个过程?注意力机制的本质又是什么呢?换一个角度来看,实际上,目标语言位置
$
j
$
可以被看作是一个查询,我们希望从源语言端找到与之最匹配的源语言位置,并返回相应的表示结果。为了描述这个问题,可以建立一个查询系统。假设有一个库,里面包含若干个
$
\mathrm
{
key
}$
-
$
\mathrm
{
value
}$
单元,其中
$
\mathrm
{
key
}$
代表这个单元的索引关键字,
$
\mathrm
{
value
}$
代表这个单元的值。比如,对于学生信息系统,
$
\mathrm
{
key
}$
可以是学号,
$
\mathrm
{
value
}$
可以是学生的身高。当输入一个查询
$
\mathrm
{
query
}$
,我们希望这个系统返回与之最匹配的结果。也就是,希望找到匹配的
$
\mathrm
{
key
}$
,并输出其对应的
$
\mathrm
{
value
}$
。比如,当查询某个学生的身高信息时,可以输入学生的学号,之后在库中查询与这个学号相匹配的记录,并把这个记录中的
$
\mathrm
{
value
}$
(即身高)作为结果返回。
...
...
@@ -838,7 +838,7 @@ a (\vectorn{\emph{s}},\vectorn{\emph{h}}) = \left\{ \begin{array}{ll}
\end{figure}
%----------------------------------------------
\parinterval
也可以用这个系统描述翻译中的注意力问题,其中,
$
\mathrm
{
query
}$
即目标语言位置
$
j
$
的某种表示,
$
\mathrm
{
key
}$
和
$
\mathrm
{
value
}$
即源语言每个位置
$
i
$
上的
${
\
vectorn
{
\emph
{
h
}
}_
i
}$
(这里
$
\mathrm
{
key
}$
和
$
\mathrm
{
value
}$
是相同的)。但是,这样的系统在机器翻译问题上并不好用,因为目标语言的表示和源语言的表示都在多维实数空间上,所以无法要求两个实数向量像字符串一样进行严格匹配,或者说这种严格匹配的模型可能会导致
$
\mathrm
{
query
}$
几乎不会命中任何的
$
\mathrm
{
key
}$
。既然无法严格精确匹配,注意力机制就采用了一个“模糊”匹配的方法。这里定义每个
$
\mathrm
{
key
}_
i
$
和
$
\mathrm
{
query
}$
都有一个0~1之间的匹配度,这个匹配度描述了
$
\mathrm
{
key
}_
i
$
和
$
\mathrm
{
query
}$
之间的相关程度,记为
$
\alpha
_
i
$
。而查询的结果(记为
$
\overline
{
\mathrm
{
value
}}$
)也不再是某一个单元的
$
\mathrm
{
value
}$
,而是所有单元
$
\mathrm
{
value
}$
用
$
\alpha
_
i
$
的加权和:
\parinterval
也可以用这个系统描述翻译中的注意力问题,其中,
$
\mathrm
{
query
}$
即目标语言位置
$
j
$
的某种表示,
$
\mathrm
{
key
}$
和
$
\mathrm
{
value
}$
即源语言每个位置
$
i
$
上的
${
\
mathbi
{
h
}_
i
}$
(这里
$
\mathrm
{
key
}$
和
$
\mathrm
{
value
}$
是相同的)。但是,这样的系统在机器翻译问题上并不好用,因为目标语言的表示和源语言的表示都在多维实数空间上,所以无法要求两个实数向量像字符串一样进行严格匹配,或者说这种严格匹配的模型可能会导致
$
\mathrm
{
query
}$
几乎不会命中任何的
$
\mathrm
{
key
}$
。既然无法严格精确匹配,注意力机制就采用了一个“模糊”匹配的方法。这里定义每个
$
\mathrm
{
key
}_
i
$
和
$
\mathrm
{
query
}$
都有一个0~1之间的匹配度,这个匹配度描述了
$
\mathrm
{
key
}_
i
$
和
$
\mathrm
{
query
}$
之间的相关程度,记为
$
\alpha
_
i
$
。而查询的结果(记为
$
\overline
{
\mathrm
{
value
}}$
)也不再是某一个单元的
$
\mathrm
{
value
}$
,而是所有单元
$
\mathrm
{
value
}$
用
$
\alpha
_
i
$
的加权和:
\begin{eqnarray}
\overline
{
\mathrm
{
value
}}
=
\sum
_
i
\alpha
_
i
\cdot
{
\mathrm
{
value
}}_
i
\label
{
eq:10-27
}
...
...
@@ -846,7 +846,7 @@ a (\vectorn{\emph{s}},\vectorn{\emph{h}}) = \left\{ \begin{array}{ll}
\noindent
也就是说所有的
$
\mathrm
{
value
}_
i
$
都会对查询结果有贡献,只是贡献度不同罢了。可以通过设计
$
\alpha
_
i
$
来捕捉
$
\mathrm
{
key
}$
和
$
\mathrm
{
query
}$
之间的相关性,以达到相关度越大的
$
\mathrm
{
key
}$
所对应的
$
\mathrm
{
value
}$
对结果的贡献越大。
\parinterval
重新回到神经机器翻译问题上来。这种基于模糊匹配的查询模型可以很好的满足对注意力建模的要求。实际上,公式
\eqref
{
eq:10-27
}
中的
$
\alpha
_
i
$
就是前面提到的注意力权重,它可以由注意力函数
$
a
(
\cdot
)
$
计算得到。这样,
$
\overline
{
\mathrm
{
value
}}$
就是得到的上下文向量,它包含了所有
\{
$
\
vectorn
{
\emph
{
h
}}_
i
$
\}
的信息,只是不同
$
\vectorn
{
\emph
{
h
}
}_
i
$
的贡献度不同罢了。图
\ref
{
fig:10-27
}
展示了将基于模糊匹配的查询模型应用于注意力机制的实例。
\parinterval
重新回到神经机器翻译问题上来。这种基于模糊匹配的查询模型可以很好的满足对注意力建模的要求。实际上,公式
\eqref
{
eq:10-27
}
中的
$
\alpha
_
i
$
就是前面提到的注意力权重,它可以由注意力函数
$
a
(
\cdot
)
$
计算得到。这样,
$
\overline
{
\mathrm
{
value
}}$
就是得到的上下文向量,它包含了所有
\{
$
\
mathbi
{
h
}_
i
$
\}
的信息,只是不同
$
\mathbi
{
h
}_
i
$
的贡献度不同罢了。图
\ref
{
fig:10-27
}
展示了将基于模糊匹配的查询模型应用于注意力机制的实例。
%----------------------------------------------
\begin{figure}
[htp]
...
...
@@ -928,13 +928,13 @@ a (\vectorn{\emph{s}},\vectorn{\emph{h}}) = \left\{ \begin{array}{ll}
\parinterval
在基于梯度的方法中,模型参数可以通过损失函数
$
L
$
对于参数的梯度进行不断更新。对于第
$
step
$
步参数更新,首先进行神经网络的前向计算,之后进行反向计算,并得到所有参数的梯度信息,再使用下面的规则进行参数更新:
\begin{eqnarray}
\
vectorn
{
\emph
{
w
}}_{
step+1
}
=
\vectorn
{
\emph
{
w
}}_{
step
}
-
\alpha
\cdot
\frac
{
\partial
L(
\vectorn
{
\emph
{
w
}}_{
step
}
)
}
{
\partial
\vectorn
{
\emph
{
w
}
}_{
step
}
}
\
mathbi
{
w
}_{
step+1
}
=
\mathbi
{
w
}_{
step
}
-
\alpha
\cdot
\frac
{
\partial
L(
\mathbi
{
w
}_{
step
}
)
}
{
\partial
\mathbi
{
w
}_{
step
}
}
\label
{
eq:10-30
}
\end{eqnarray}
\noindent
其中,
$
\
vectorn
{
\emph
{
w
}}_{
step
}$
表示更新前的模型参数,
$
\vectorn
{
\emph
{
w
}}_{
step
+
1
}$
表示更新后的模型参数,
$
L
(
\vectorn
{
\emph
{
w
}}_{
step
}
)
$
表示模型相对于
$
\vectorn
{
\emph
{
w
}}_{
step
}$
的损失,
$
\frac
{
\partial
L
(
\vectorn
{
\emph
{
w
}}_{
step
}
)
}
{
\partial
\vectorn
{
\emph
{
w
}
}_{
step
}
}$
表示损失函数的梯度,
$
\alpha
$
是更新的步进值。也就是说,给定一定量的训练数据,不断执行公式
\eqref
{
eq:10-30
}
的过程。反复使用训练数据,直至模型参数达到收敛或者损失函数不再变化。通常,把公式的一次执行称为“一步”更新/训练,把访问完所有样本的训练称为“一轮”训练。
\noindent
其中,
$
\
mathbi
{
w
}_{
step
}$
表示更新前的模型参数,
$
\mathbi
{
w
}_{
step
+
1
}$
表示更新后的模型参数,
$
L
(
\mathbi
{
w
}_{
step
}
)
$
表示模型相对于
$
\mathbi
{
w
}_{
step
}$
的损失,
$
\frac
{
\partial
L
(
\mathbi
{
w
}_{
step
}
)
}
{
\partial
\mathbi
{
w
}_{
step
}
}$
表示损失函数的梯度,
$
\alpha
$
是更新的步进值。也就是说,给定一定量的训练数据,不断执行公式
\eqref
{
eq:10-30
}
的过程。反复使用训练数据,直至模型参数达到收敛或者损失函数不再变化。通常,把公式的一次执行称为“一步”更新/训练,把访问完所有样本的训练称为“一轮”训练。
\parinterval
将公式
\eqref
{
eq:10-30
}
应用于神经机器翻译有几个基本问题需要考虑:1)损失函数的选择;2)参数初始化的策略,也就是如何设置
$
\
vectorn
{
\emph
{
w
}
}_
0
$
;3)优化策略和学习率调整策略;4)训练加速。下面对这些问题进行讨论。
\parinterval
将公式
\eqref
{
eq:10-30
}
应用于神经机器翻译有几个基本问题需要考虑:1)损失函数的选择;2)参数初始化的策略,也就是如何设置
$
\
mathbi
{
w
}_
0
$
;3)优化策略和学习率调整策略;4)训练加速。下面对这些问题进行讨论。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
...
...
@@ -942,15 +942,15 @@ a (\vectorn{\emph{s}},\vectorn{\emph{h}}) = \left\{ \begin{array}{ll}
\subsubsection
{
1. 损失函数
}
\parinterval
神经机器翻译在目标端的每个位置都会输出一个概率分布,表示这个位置上不同单词出现的可能性。设计损失函数时,需要知道当前位置输出的分布相比于标准答案的“差异”。对于这个问题,常用的是交叉熵损失函数。令
$
\
vectorn
{
\emph
{
y
}}$
表示机器翻译模型输出的分布,
$
\hat
{
\vectorn
{
\emph
{
y
}
}}$
表示标准答案,则交叉熵损失可以被定义为:
\parinterval
神经机器翻译在目标端的每个位置都会输出一个概率分布,表示这个位置上不同单词出现的可能性。设计损失函数时,需要知道当前位置输出的分布相比于标准答案的“差异”。对于这个问题,常用的是交叉熵损失函数。令
$
\
mathbi
{
y
}$
表示机器翻译模型输出的分布,
$
\hat
{
\mathbi
{
y
}}$
表示标准答案,则交叉熵损失可以被定义为:
\begin{eqnarray}
L
_{
\textrm
{
ce
}}
(
\
vectorn
{
\emph
{
y
}}
,
\hat
{
\vectorn
{
\emph
{
y
}}}
) = -
\sum
_{
k=1
}^{
|V|
}
\vectorn
{
\emph
{
y
}}
[k]
\textrm
{
log
}
(
\hat
{
\vectorn
{
\emph
{
y
}
}}
[k])
L
_{
\textrm
{
ce
}}
(
\
mathbi
{
y
}
,
\hat
{
\mathbi
{
y
}}
) = -
\sum
_{
k=1
}^{
|V|
}
\mathbi
{
y
}
[k]
\textrm
{
log
}
(
\hat
{
\mathbi
{
y
}}
[k])
\label
{
eq:10-3222
}
\end{eqnarray}
\noindent
其中
$
\
vectorn
{
\emph
{
y
}}
[
k
]
$
和
$
\hat
{
\vectorn
{
\emph
{
y
}}}
[
k
]
$
分别表示向量
$
\vectorn
{
\emph
{
y
}}$
和
$
\hat
{
\vectorn
{
\emph
{
y
}}}$
的第
$
k
$
维,
$
|V|
$
表示输出向量的维度(等于词表大小)。假设有
$
n
$
个训练样本,模型输出的概率分布为
$
\vectorn
{
\emph
{
Y
}}
=
\{
\vectorn
{
\emph
{
y
}}_
1
,
\vectorn
{
\emph
{
y
}}_
2
,...,
\vectorn
{
\emph
{
y
}}_
n
\}
$
,标准答案的分布
$
\widehat
{
\vectorn
{
\emph
{
Y
}}}
=
\{
\hat
{
\vectorn
{
\emph
{
y
}}}_
1
,
\hat
{
\vectorn
{
\emph
{
y
}}}_
2
,...,
\hat
{
\vectorn
{
\emph
{
y
}
}}_
n
\}
$
。这个训练样本集合上的损失函数可以被定义为:
\noindent
其中
$
\
mathbi
{
y
}
[
k
]
$
和
$
\hat
{
\mathbi
{
y
}}
[
k
]
$
分别表示向量
$
\mathbi
{
y
}$
和
$
\hat
{
\mathbi
{
y
}}$
的第
$
k
$
维,
$
|V|
$
表示输出向量的维度(等于词表大小)。假设有
$
n
$
个训练样本,模型输出的概率分布为
$
\mathbi
{
Y
}
=
\{
\mathbi
{
y
}_
1
,
\mathbi
{
y
}_
2
,...,
\mathbi
{
y
}_
n
\}
$
,标准答案的分布
$
\widehat
{
\mathbi
{
Y
}}
=
\{
\hat
{
\mathbi
{
y
}}_
1
,
\hat
{
\mathbi
{
y
}}_
2
,...,
\hat
{
\mathbi
{
y
}}_
n
\}
$
。这个训练样本集合上的损失函数可以被定义为:
\begin{eqnarray}
L(
\
vectorn
{
\emph
{
Y
}}
,
\widehat
{
\vectorn
{
\emph
{
Y
}}}
) =
\sum
_{
j=1
}^
n L
_{
\textrm
{
ce
}}
(
\vectorn
{
\emph
{
y
}}_
j,
\hat
{
\vectorn
{
\emph
{
y
}
}}_
j)
L(
\
mathbi
{
Y
}
,
\widehat
{
\mathbi
{
Y
}}
) =
\sum
_{
j=1
}^
n L
_{
\textrm
{
ce
}}
(
\mathbi
{
y
}_
j,
\hat
{
\mathbi
{
y
}}_
j)
\label
{
eq:10-31
}
\end{eqnarray}
...
...
@@ -970,13 +970,13 @@ L(\vectorn{\emph{Y}},\widehat{\vectorn{\emph{Y}}}) = \sum_{j=1}^n L_{\textrm{ce}
\begin{itemize}
\vspace
{
0.5em
}
\item
LSTM遗忘门偏置初始化为1,也就是始终选择遗忘记忆
$
\
vectorn
{
\emph
{
c
}}$
,这样可以有效防止初始化时
$
\vectorn
{
\emph
{
c
}
}$
里包含的错误信号传播到后面的时刻。
\item
LSTM遗忘门偏置初始化为1,也就是始终选择遗忘记忆
$
\
mathbi
{
c
}$
,这样可以有效防止初始化时
$
\mathbi
{
c
}$
里包含的错误信号传播到后面的时刻。
\vspace
{
0.5em
}
\item
网络中的其他偏置一般都初始化为0,可以有效防止加入过大或过小的偏置后使得激活函数的输出跑到“饱和区”,也就是梯度接近0的区域,防止训练一开始就无法跳出局部极小的区域。
\vspace
{
0.5em
}
\item
网络的权重矩阵
$
\
vectorn
{
\emph
{
w
}}$
一般使用Xavier参数初始化方法
\upcite
{
pmlr-v9-glorot10a
}
,可以有效稳定训练过程,特别是对于比较“深”的网络。令
$
d
_{
in
}$
和
$
d
_{
out
}$
分别表示
$
\vectorn
{
\emph
{
w
}}$
的输入和输出的维度大小
\footnote
{
对于变换
$
\vectorn
{
\emph
{
y
}}
=
\vectorn
{
\emph
{
x
}}
\vectorn
{
\emph
{
w
}}$
,
$
\vectorn
{
\emph
{
w
}
}$
的列数为
$
d
_{
in
}$
,行数为
$
d
_{
out
}$
。
}
,则该方法的具体实现如下:
\item
网络的权重矩阵
$
\
mathbi
{
w
}$
一般使用Xavier参数初始化方法
\upcite
{
pmlr-v9-glorot10a
}
,可以有效稳定训练过程,特别是对于比较“深”的网络。令
$
d
_{
in
}$
和
$
d
_{
out
}$
分别表示
$
\mathbi
{
w
}$
的输入和输出的维度大小
\footnote
{
对于变换
$
\mathbi
{
y
}
=
\mathbi
{
x
}
\mathbi
{
w
}$
,
$
\mathbi
{
w
}$
的列数为
$
d
_{
in
}$
,行数为
$
d
_{
out
}$
。
}
,则该方法的具体实现如下:
\begin{eqnarray}
\
vectorn
{
\emph
{
w
}
}
\sim
U(-
\sqrt
{
\frac
{
6
}
{
d
_{
in
}
+ d
_{
out
}
}
}
,
\sqrt
{
\frac
{
6
}
{
d
_{
in
}
+ d
_{
out
}
}
}
)
\
mathbi
{
w
}
\sim
U(-
\sqrt
{
\frac
{
6
}
{
d
_{
in
}
+ d
_{
out
}
}
}
,
\sqrt
{
\frac
{
6
}
{
d
_{
in
}
+ d
_{
out
}
}
}
)
\label
{
eq:10-32
}
\vspace
{
0.5em
}
\end{eqnarray}
...
...
@@ -1005,12 +1005,12 @@ L(\vectorn{\emph{Y}},\widehat{\vectorn{\emph{Y}}}) = \sum_{j=1}^n L_{\textrm{ce}
\parinterval
需要注意的是,训练循环神经网络时,反向传播使得网络层之间的梯度相乘。在网络层数过深时,如果连乘因子小于1可能造成梯度指数级的减少,甚至趋近于0,导致网络无法优化,也就是梯度消失问题。当连乘因子大于1时,可能会导致梯度的乘积变得异常大,造成梯度爆炸的问题。在这种情况下需要使用“梯度裁剪”来防止梯度超过阈值。梯度裁剪在
{
\chapternine
}
已经介绍过,这里简单回顾一下。梯度裁剪的具体公式如下:
\vspace
{
-0.5em
}
\begin{eqnarray}
\
vectorn
{
\emph
{
w
}}
' =
\vectorn
{
\emph
{
w
}}
\cdot
\frac
{
\gamma
}
{
\textrm
{
max
}
(
\gamma
,
\|
\vectorn
{
\emph
{
w
}
}
\|
_
2)
}
\
mathbi
{
w
}
' =
\mathbi
{
w
}
\cdot
\frac
{
\gamma
}
{
\textrm
{
max
}
(
\gamma
,
\|
\mathbi
{
w
}
\|
_
2)
}
\label
{
eq:10-33
}
\end{eqnarray}
%\vspace{0.5em}
\noindent
其中,
$
\gamma
$
是手工设定的梯度大小阈值,
$
\|
\cdot
\|
_
2
$
是L2范数,
$
\
vectorn
{
\emph
{
w
}
}
'
$
表示梯度裁剪后的参数。这个公式的含义在于只要梯度大小超过阈值,就按照阈值与当前梯度大小的比例进行放缩。
\noindent
其中,
$
\gamma
$
是手工设定的梯度大小阈值,
$
\|
\cdot
\|
_
2
$
是L2范数,
$
\
mathbi
{
w
}
'
$
表示梯度裁剪后的参数。这个公式的含义在于只要梯度大小超过阈值,就按照阈值与当前梯度大小的比例进行放缩。
%----------------------------------------------------------------------------------------
% NEW SUBSUB-SECTION
...
...
Chapter12/chapter12.tex
查看文件 @
ef167b14
...
...
@@ -58,7 +58,7 @@
\parinterval
自注意力机制也可以被看做是一个序列表示模型。比如,对于每个目标位置
$
j
$
,都生成一个与之对应的源语句子表示,它的形式为:
\begin{eqnarray}
\
vectorn
{
\emph
{
C
}}_
j =
\sum
_
i
\alpha
_{
i,j
}
\vectorn
{
\emph
{
h
}}_
i
\
mathbi
{
C
}}_
j =
\sum
_
i
\alpha
_{
i,j
}
\vectorn
{
\emph
{
h
}}_
i
\label
{
eq:12-4201
}
\end{eqnarray}
...
...
@@ -561,7 +561,7 @@ Transformer Deep(48层) & 30.2 & 43.1 & 194$\times 10^
\section
{
推断
}
\parinterval
Transformer解码器生成译文词序列的过程和其它神经机器翻译系统类似,都是从左往右生成,且下一个单词的预测依赖已经生成的单词。其具体推断过程如图
\ref
{
fig:12-56
}
所示,其中
$
\
vectorn
{
\emph
{
C
}}_
i
$
是编码-解码注意力的结果,解码器首先根据“<eos>”和
$
\vectorn
{
\emph
{
C
}}_
1
$
生成第一个单词“how”,然后根据“how”和
$
\vectorn
{
\emph
{
C
}}_
2
$
生成第二个单词“are”,以此类推,当解码器生成“<eos>”时结束推断。
\parinterval
Transformer解码器生成译文词序列的过程和其它神经机器翻译系统类似,都是从左往右生成,且下一个单词的预测依赖已经生成的单词。其具体推断过程如图
\ref
{
fig:12-56
}
所示,其中
$
\
mathbi
{
C
}}_
i
$
是编码-解码注意力的结果,解码器首先根据“<eos>”和
$
\mathbi
{
C
}}_
1
$
生成第一个单词“how”,然后根据“how”和
$
\mathbi
{
C
}}_
2
$
生成第二个单词“are”,以此类推,当解码器生成“<eos>”时结束推断。
\parinterval
但是,Transformer在推断阶段无法对所有位置进行并行化操作,因为对于每一个目标语单词都需要对前面所有单词进行注意力操作,因此它推断速度非常慢。可以采用的加速手段有:低精度
\upcite
{
DBLP:journals/corr/CourbariauxB16
}
、Cache(缓存需要重复计算的变量)
\upcite
{
DBLP:journals/corr/abs-1805-00631
}
、共享注意力网络等
\upcite
{
Xiao2019SharingAW
}
。关于Transformer模型的推断加速方法将会在
{
\chapterfourteen
}
进一步深入讨论。
...
...
Chapter9/chapter9.tex
查看文件 @
ef167b14
This source diff could not be displayed because it is too large. You can
view the blob
instead.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论