RNN编码器-解码器
读 Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation
论文的主要贡献
提出了一个新的神经网络模型叫做 RNN编码-解码器 ,该模型包含两个RNN,分别位于编码器和解码器中,编码器中的RNN负责将变长的输入序列映射到一个固定长度的向量中,解码器中的RNN则负责将向量映射到一个变长的输出序列中。定性的来讲,这个模型可以学习语言短语的有意义的的语义和句法表示。
提出了一个新的LSTM变体GRU。GRU到现在都非常受欢迎。
RNN Encoder-Decoder
图1就是本篇论文所提出的一个新的深度学习模型,叫做 RNN编码器解码器 ,编码器和解码器分别包含一个RNN,图1展示的是RNN展开之后的情况。
编码器
图2 编码器部分标注出了隐藏层状态,用
h
t
\mathbf{h}_t
ht 表示,其更新公式为:
h
t
=
f
(
h
t
−
1
,
x
t
)
(1)
\mathbf{h}_t = f(\mathbf{h}_{t-1},x_t) \tag{1}
ht=f(ht−1,xt)(1)
公式(1)说明当前时刻的隐藏层状态
h
t
h_t
ht 是由上一时刻的状态
h
t
−
1
h_{t-1}
ht−1 和当前时刻的输入
x
t
x_t
xt 共同决定的。
f
f
f 是一个函数,可以是一个简单的逻辑函数,比如sigmoid函数,也可以是一个复杂的函数,比如LSTM。这篇论文中
f
f
f 用的是作者提出的一个新的结构,叫做GRU,后面会讲。
图2 中 C 是中间语义表示。
可以是各个时刻隐层输出的汇总:
C
=
g
(
h
1
,
h
2
,
.
.
.
,
h
T
)
(2)
C = g(\mathbf{h}_1,\mathbf{h}_2,...,\mathbf{h}_T) \tag{2}
C=g(h1,h2,...,hT)(2)
也可以是最后一层隐层的输出:
C
=
h
T
(3)
C = \mathbf{h}_T \tag{3}
C=hT(3)
在本篇论文中作者是将隐层的最后输出作为语义表示 C 。由于编码器用的是RNN的结构,每一个循环中的信息都会流到下一个循环中,因此中间语义表示 C 理论上包含了输入序列的所有信息。
解码器
图3 标注出了解码器的隐藏层状态,为了防止跟编码器部分混淆,我们用
s
t
\mathbf{s}_t
st 表示。从图中可以看出,隐藏层的状态更新,不仅跟上一时刻的输出
s
t
−
1
\mathbf{s}_{t-1}
st−1 和当前时刻的输入
c
\mathbf{c}
c 有关系,还跟上一时刻的输出
y
t
−
1
y_{t-1}
yt−1 有关:
s
t
=
f
(
s
t
−
1
,
y
t
−
1
,
c
)
(4)
\mathbf{s}_t = f(\mathbf{s}_{t-1},y_{t-1},\mathbf{c}) \tag{4}
st=f(st−1,yt−1,c)(4)
之后我们就可以计算模型的输出预测了:
P
(
y
t
∣
y
t
−
1
,
y
t
−
2
,
.
.
.
,
y
1
,
c
)
=
g
(
s
t
,
y
t
−
1
,
c
)
(5)
P(y_t|y_{t-1},y_{t-2},...,y_1, \mathbf{c})=g(\mathbf{s}_t,y_{t-1}, \mathbf{c}) \tag{5}
P(yt∣yt−1,yt−2,...,y1,c)=g(st,yt−1,c)(5)
其中
g
g
g 函数一般为softmax函数。
训练
m a x θ 1 N ∑ n = 1 N l o g p θ ( y n ∣ x n ) (6) \underset{\theta}{\mathrm{max}} \frac{1}{N}\sum_{n=1}^Nlogp_{{\theta}}(\mathbf{y}_n|\mathbf{x}_n) \tag{6} θmaxN1n=1∑Nlogpθ(yn∣xn)(6)
这个公式就是我们训练的目标函数,目的是最大化这个条件对数似然函数。其中 θ {\theta} θ 是模型的参数, ( x n , y n ) (\mathbf{x}_n, \mathbf{y}_n) (xn,yn) 代表输入输出句子对
GRU
图4 就是本篇论文中作者提出的隐藏层**函数,后来被称为GRU(Gate Recurrent Unit)。
先来看一下GRU各个状态是如何更新的:
h
j
t
=
z
j
h
j
t
−
1
+
(
1
−
z
j
)
h
~
j
t
(7)
h_j^t = z_jh_j^{t-1}+(1-z_j)\widetilde{h}_j^t \tag{7}
hjt=zjhjt−1+(1−zj)h
jt(7)
h
~
j
t
=
ϕ
(
[
W
x
]
j
+
[
U
(
r
⊙
h
t
−
1
)
]
j
)
(8)
\widetilde{h}_j^t=\phi \Big([W\mathbf{x}]_j + [U \big(\mathbf{r} \odot \mathbf{h}_{t-1} \big)]_j \Big) \tag{8}
h
jt=ϕ([Wx]j+[U(r⊙ht−1)]j)(8)
z
j
=
σ
(
[
W
z
x
]
j
+
[
U
z
h
t
−
1
]
j
)
(9)
z_j=\sigma \Big( [W_z\mathbf{x}]_j + [U_z\mathbf{h}_{t-1}]_j \Big) \tag{9}
zj=σ([Wzx]j+[Uzht−1]j)(9)
r
j
=
σ
(
[
W
r
x
]
j
+
[
U
r
h
t
−
1
]
j
)
(10)
r_j = \sigma \Big( [W_r\mathbf{x}]_j + [U_r\mathbf{h}_{t-1}]_j \Big) \tag{10}
rj=σ([Wrx]j+[Urht−1]j)(10)
其中,
[
.
]
j
[.]_j
[.]j 代表向量的第 j 个元素。也就是说公式(7)-(10)是以单个元素为例进行计算的。
⊙
\odot
⊙ 表示将两个形状相同的矩阵对应元素相乘。
[
.
]
+
[
.
]
[.]+[.]
[.]+[.] 代表将两个向量进行拼接,不是对应元素相加。
x
\mathbf{x}
x 和
h
t
−
1
\mathbf{h}_{t-1}
ht−1 分别代表输入和上一层的隐藏状态。
W
∗
W_*
W∗ 和
U
∗
U_*
U∗ 代表 权重矩阵,
∗
*
∗ 代表r、z或空。
σ
\sigma
σ 代表sigmoid函数。图中的 z 和 r 分别代表更新门和重置门。
如果重置门被设置为0,那么先前的隐藏层状态就会被强制遗忘,然后用当前的输入进行重置。这使得隐藏层状态可以有效的丢 弃跟未来没有任何关系的信息,从而使信息表达更为紧凑。
而更新门则是用来控制先前的隐藏层状态会携带多少信息到当前状态。
上面这两条可以结合公式(7)来理解,公式(7)左侧表示更新门携带的信息,右侧表示遗忘门携带的信息。
上面的图都是作者原始论文中的图,我稍微加了些辅助线帮助理解,但是整个模型可能还不是特别容易理解。所以又从网上找了后人改进的图:
图源: 动手学深度学习
可以自己结合公式跟上面这个图进行对应理解。
完!