最近在做李宏毅深度学习2020作业8:Seq2Seq时,非常纠结一点,注意力值算出来用在哪儿?
在作业的BASE版本上加上注意力后,机器翻译的效果并没有提升,因此决定梳理一番。
本文主要关注attention用谁计算,以及计算出来如何使用,而不再赘述计算过程。
1. 原论文中
attention应该是做一个语义信息的补充功能。
简要说明一下公式定义,
c
i
c_i
ci代表
i
i
i时刻计算出的注意力向量,
s
i
s_i
si为
i
i
i时刻输出的hidden,
y
i
y_i
yi为
i
i
i时刻输出的word
根据原论文中的公式,当前RNN的hidden要通过当前注意力值和前一时刻传过来的hidden,以及前一时刻的输出一起算得。
再来看注意力值
c
i
c_i
ci的计算公式
这里也是很明确地指出了,注意力中做相似度的运算,是用上一时刻传过来的
s
i
−
1
s_{i-1}
si−1计算的
但是使用PyTorch编写代码时,我们总需要决定,Decoder中的RNN,给它输入的hidden和input到底是什么?
只靠示意图几条线一连,或者给个抽象函数f是不够的!
2. 斯坦福的CS224N
CS224N是这么描述的
(1) 把attention值
a
t
a_t
at和当前的RNNhidden
s
t
s_t
st 拼在一起,然后通过一个线性分类器得到词的分布概率。
这个
s
t
s_t
st应该是由输入词向量和
s
t
−
1
s_{t-1}
st−1计算出来的,那和原论文就不一致了。
网上找到的一张CS224n的笔记图,进一步阐述了这个过程。
(2) 把上一时刻算出来的attention向量和现在的输入拼在一起。
下面根据cs224n的作业指导,进一步详细描述计算过程:
源句长度为m,词嵌入维度为e
采用了双向LSTM结构的Encoder
初始化Decoder,W矩阵起到维度变换的作用
在t时刻:
- 找到第t个subword的embedding, y t ∈ R e × 1 y_t \in R^{e \times 1} yt∈Re×1
- 把 y t y_t yt 和前一步的combined-output vector o t − 1 ∈ R h × 1 o_{t-1} \in R^{h\times1} ot−1∈Rh×1 拼在一起产生 y t ˉ ∈ R ( e + h ) × 1 \bar{y_t} \in R^{(e+h)\times1} ytˉ∈R(e+h)×1
- 要注意第一个target subword (i.e. the start token) o 0 o_0 o0 is a zero-vector.
- 把
y
t
ˉ
\bar{y_t}
ytˉ作为输入送入解码器。
(这里也明确了是先输入RNN,再进行注意力的计算)
下面是注意力的计算,注意维度即可。
这个combined-output vector: o t o_t ot,是用 a t a_t at和当前time step的RNN输出的 h t d e c {h_t}^{dec} htdec拼在一起,经过下列运算得到的。
t时刻输出词的概率分布 P T P_T PT为:
V t 是 目 标 词 表 大 小 V_t是目标词表大小 Vt是目标词表大小
损失函数的计算:
g t g_t gt为t时刻正确的目标词汇的one-hot向量,长度为 V t V_t Vt