seq2seq attention详解
1️⃣ seq2seq介绍
传统的RNN、LSTM和GRU无法处理输入序列和输出序列长度不同的任务。因此提出了seq2seq。
seq2seq是一种基于编码器-解码器架构的深度学习模型,用于将一个变长序列转换为另一个变长序列,常用于机器翻译、文本摘要和语音识别等任务。在2014年
被提出
2️⃣ 原理分析
2.1 整体结构
seq2seq也被称为encoder-decoder模型。模型包含两个部分:encoder用于将任意长度的序列编码到一个固定长度的上下文向量 c c c中;decoder将 c c c解码,得到序列。
seq2seq结构很多,这里主要介绍三种:
第一种:上下文向量 c c c作为decoder的输入数据,需要初始化decoder隐层状态
注意:图中的粉色圈I和绿色圈O忽略即可
第二种:上下文向量
c
c
c作为decoder的隐层状态
第三种:上下文向量
c
c
c作为decoder的输入数据,需要初始化decoder隐层状态。Decoder每一个时间步的输出作为下一个时间步的输入
2.2 encoder
上面介绍的三种结构,它们的encoder都是一样的。encoder接受输入
x
x
x,最终输出一个编码所有信息的上下文向量
c
c
c,中间的时间步没有输出
上下文向量
c
c
c的计算方法包括以下几种:
c
=
h
N
c
=
g
(
h
N
)
c
=
g
(
h
1
:
:
h
N
)
\begin{aligned} &\mathbf{c}=h_{N} \\ &\mathbf{c}=g(h_N) \\ &\mathbf{c}=g(h_1::h_N) \end{aligned}
c=hNc=g(hN)c=g(h1::hN)
第一种计算方法:上下文向量
c
c
c就是Encoder最后一个时间步的隐藏状态
h
N
h_N
hN
第二种计算方法:增加一个非线性变换函数
第三种计算方法:使用整个序列的隐藏状态
h
1
,
h
2
,
…
,
h
N
h_1,h_2,\ldots,h_N
h1,h2,…,hN来计算上下文向量
c
c
c。这种是seq2seq常用的方式
2.3 decoder
看第一种decoder,上下文向量
c
c
c作为decoder的输入数据,需要初始化decoder隐层状态
h
0
′
h_0^\prime
h0′
h
i
′
=
f
(
U
⋅
c
+
W
⋅
h
i
−
1
′
)
y
i
=
g
(
V
⋅
h
i
′
)
h_{i}^ \prime=f(U\cdot c+W\cdot h_{i-1}^\prime)\\y_{i}=g(V\cdot h_{i}^\prime)
hi′=f(U⋅c+W⋅hi−1′)yi=g(V⋅hi′)
第二种decoder,上下文向量
c
c
c作为decoder的隐层状态,各个时间步只接受上一时间步的隐层状态,而没有其他输入。
h
1
′
=
f
(
W
⋅
c
)
h
i
′
=
f
(
W
⋅
h
i
−
1
′
)
y
i
=
g
(
V
⋅
h
i
′
)
h_{1}^ \prime=f(W\cdot c)\\h_{i}^ \prime=f(W\cdot h_{i-1}^ \prime)\\y_{i}=g(V\cdot h_{i}^ \prime)
h1′=f(W⋅c)hi′=f(W⋅hi−1′)yi=g(V⋅hi′)
第三种:上下文向量
c
c
c作为decoder的输入数据,Decoder每一个时间步的输出作为下一个时间步的输入。注意这里需要初始化
h
0
′
h_0^\prime
h0′和
y
0
′
y_0^\prime
y0′
h i ′ = f ( U ⋅ c + V ⋅ y i − 1 ′ + W ⋅ h i − 1 ) y i ′ = g ( V ⋅ h i ′ ) h_{i}^ \prime=f(U\cdot c+V\cdot y_{i-1}^\prime+W\cdot h_{i-1})\\y_{i}^\prime=g(V\cdot h_{i}^\prime) hi′=f(U⋅c+V⋅yi−1′+W⋅hi−1)yi′=g(V⋅hi′)
3️⃣ 使用技巧
3.1 Teacher Forcing
针对上面的第三种模型,每一个时间步的输入包含上一个时间步的输出 y i − 1 ′ y_{i-1}^\prime yi−1′。如果前一个时间步出错了,那必然会影响后面所有的结果。
因此提出了Teacher Forcing,我们在训练过程中使用ground truth作为时间步的输入,即输入 y i − 1 t r u t h ′ y_{i-1}^{ truth^ {\prime}} yi−1truth′
那么Teacher Forcing有什么优点呢?
- 可以减少错误的传播
缺点:
- 因为依赖标签数据,在训练过程中,模型会有较好的效果。但是在测试的时候因为不能得到ground truth的支持,所以如果目前生成的序列在训练过程中有很大不同,模型就会变得脆弱。解决办法:集束搜索(Beam Search),后续如果有机会,会对集束搜索进行学习
3.2 Attention机制
回想一下seq2seq模型中,encoder是不是总是将任意长度的序列编码到一个固定长度的上下文向量 c c c中。然后在decoder解码过程中,上下文向量 c c c的长度是不变的,这存在以下弊端:
- 固定长度的上下文向量 c c c会丢失许多细节,无法有效表达长序列中的全部信息
假设输入序列为 X N = { x 1 , x 2 , … , x N } X_N=\{x_1,x_2,\ldots,x_N\} XN={x1,x2,…,xN},输出序列为 Y M = { y 1 ′ , y 2 ′ , … , y M ′ } Y_M=\{y_1^{\prime},y_2^{\prime},\ldots,y_M^{\prime}\} YM={y1′,y2′,…,yM′},Attention机制的工作流程为:
1.Encoder生成隐藏状态
Encoder对输入序列
X
N
=
{
x
1
,
x
2
,
…
,
x
N
}
X_N=\{x_1,x_2,\ldots,x_N\}
XN={x1,x2,…,xN}逐步处理,生成每个时间步的隐藏状态序列
H
=
H=
H=
{
h
1
,
h
2
,
…
,
h
N
}
\{h_1,h_2,\ldots,h_N\}
{h1,h2,…,hN},其中
h
i
h_i
hi表示输入
x
i
x_i
xi的隐向量表示。
2.Decoder的初始状态
Decoder的初始隐藏状态记为 h 0 ′ h_0^{\prime} h0′。
3.计算注意力权重 (Attention Scores)
在解码的第 t t t步,Decoder 的隐藏状态 h t ′ h_t^{\prime} ht′与 Encoder 的每个隐藏状态 h i h_i hi进行对比,计算注意力分数 e t i e_{ti} eti ,常见方法如下:
-
加性注意力:
e t i = v T tanh ( W 1 h i + W 2 s t ) e_{ti}=v^T\tanh(W_1h_i+W_2s_t) eti=vTtanh(W1hi+W2st)
其中, W 1 W_1 W1和 W 2 W_2 W2是可学习的权重参数 -
点积注意力(Dot-Product Attention):
e t i = h t ′ T h i e_{ti}=h_t^{\prime T}h_i eti=ht′Thi
- 缩放点积注意力 (Scaled Dot-Product Attention) :
e t i = h t ′ T h i d e_{ti}=\frac{h_t^{\prime T}h_i}{\sqrt{d}} eti=dht′Thi
其中 d d d是隐藏向量的维度。
4.计算权重分布 (Attention Weights)
使用 Softmax 函数将分数 e t i e_{ti} eti转换为归一化的权重 α t i \alpha_{ti} αti:
α t i = exp ( e t i ) ∑ j = 1 N exp ( e t j ) \alpha_{ti}=\frac{\exp(e_{ti})}{\sum_{j=1}^N\exp(e_{tj})} αti=∑j=1Nexp(etj)exp(eti)
5.生成上下文向量
根据权重 α t i \alpha_{ti} αti对 Encoder 的隐藏状态加权求和,得到上下文向量 c t : c_t: ct:
c t = ∑ i = 1 N α t i h i c_t=\sum_{i=1}^N\alpha_{ti}h_i ct=i=1∑Nαtihi
6.计算输出
h
t
′
=
f
(
U
⋅
c
t
+
V
⋅
y
t
−
1
′
+
W
⋅
h
t
−
1
′
)
y
t
′
=
g
(
V
⋅
h
t
′
)
h_{t}^ \prime=f(U\cdot c_t+V\cdot y_{t-1}^\prime+W\cdot h_{t-1}^\prime)\\y_{t}^\prime=g(V\cdot h_{t}^\prime)
ht′=f(U⋅ct+V⋅yt−1′+W⋅ht−1′)yt′=g(V⋅ht′)
g() 通常是 Softmax,用于生成输出词分布
4️⃣ 总结
- seq2seq中,encoder的隐层状态维度一致;decoder的隐层状态一致;维度就是隐层神经元个数