文章目录
公式输入请参考: 在线Latex公式
概述
Seq2Seq模型的概念大概回顾一下,然后把里面两个点弄一下,一个是Seq2Seq做interfere/decode的优化方法:Beam search,一个是attention。
这里要注意,数据预处理的时候,由于输入的序列长度是不一样的,但是模型是预先定好的,所以要以数据中最长的序列为标准来制定encoder的长度,然后对于短的序列,把后面补齐特殊的符号。对于decoder端也是一样。
Encoder后得到的C(content vector),然后用C来预测输出序列,我们先来看看需要做什么优化。
interfere/decode的过程
假设我们的Seq2Seq模型已经训练好了,模型参数是已知的。
然后在Encoder部分,最后一个词的时候,就相当于得到了C
然后开始进行decoder
Greedy Search
每一次都取概率最大的单词作为当前时刻的输出和下一时刻的输入。
由于一句话的翻译或者说输出结果可能会有很多种,对于这样的生成的模型怎么知道或者说如何评估模型的效果呢?
按上面的输入,我们把输入记为
y
^
\hat y
y^,标签记为
y
y
y
如果从单词重复度上面看基本上是没问题的,单单从这个角度来看,是不能够说明翻译的效果的。
上图中红色的
y
^
\hat y
y^与第一个
y
^
\hat y
y^重复度与真实标签一样样的,但是明显红色的
y
^
\hat y
y^是不符合语法逻辑的。因此我们要加入n-gram的思想来进行评估模型的好坏,例如:
绿色是Unigram,红色是bigram,黑色是trigram,可以看到第一
y
^
\hat y
y^无论是哪种gram都要比红色
y
^
\hat y
y^要强。实作上可以取三者的平均值来进行判断。
目前生成
y
^
\hat y
y^的时候,每次都是选取概率值最大的那个作为当前时刻的输出,这样是属于贪心的算法,这样并不能保证全局最优解。时间复杂度为:
O
(
T
)
O(T)
O(T)
为了得到全局最优解,我们有两种方法:
Exhaustic Search:穷举法
Beam Search:集束搜索法
Exhaustic Search
从上图可以看出来,每个输出向量长度和词表长度相当,为:
∣
V
∣
|V|
∣V∣,输出序列的长度为T(红色部分,这个长度可以定下来的,前面说过,按最长的输出来定)整个算法的时间复杂度为:
O
(
∣
V
∣
T
)
O(|V|^T)
O(∣V∣T),因为每次输入都要考虑
∣
V
∣
|V|
∣V∣种可能性。
Beam Search
Exhaustic Search虽然可以找到全局最优解,但是其时间复杂度太高,因此要折中一下。Beam Search可能找出来的不是全局最优解,但是比Greedy Search要强,而且时间复杂度可以接受。
直接看例子,假设k为3(Beam size),也就是每次考虑前3个可能,输出第一个词的时候(输入是start,计算概率为:
log
p
(
t
h
e
∣
s
t
a
r
t
)
\log p(the|start)
logp(the∣start)):
输出第二词的时候,可以看到,概率是用加的,因为在计算概率的时候采用了log,所以乘就变成了加。
再在计算的结果里面选择结果最大的三个(绿色框),注意这里是带负号的。
依次类推:
注意,由于Beam Search算法每步的结果都是负数,所以值越小那么加上负号就越大,如果在第一个单词的时候就取到一个<end>符号,那么按算法的思想,肯定直接选择<stack>到<end>作为整个序列的输出,也就是说Beam Search算法会倾向于比较短的序列。为了解决这个问题,在每次计算序列的是概率的时候,要除以当前输出序列的个数。例如上图中的最后那个<end>是-2.3,要除以4才行。
Beam Search算法时间复杂度为:
O
(
k
2
T
)
=
O
(
T
)
O(k^2T)=O(T)
O(k2T)=O(T)
小结
Greedy Search,时间复杂度为:
O
(
T
)
O(T)
O(T),每次只考虑最好的那个
Exhaustic Search,时间复杂度为:
O
(
∣
V
∣
T
)
O(|V|^T)
O(∣V∣T),每次考虑所有可能
Beam Search,时间复杂度为:
O
(
T
)
O(T)
O(T),每次考虑前k个可能
Attention
有三个方面的应用,我们分别来看,最后一个自注意力机制是重点。
Attention for Image Captioning
原始的图片分类(看例子貌似是alexnet):
把上面的模型中学习到的图片的特征用来做看图说话,按理说离softmax越近,表达越好,这里为什么不把FC-1000作为最后的图片表达呢?因为原来的模型为了做分类(cifar是1000类),对向量做了限制,限制为1000长度,而我们现在要做看图说话,是一个多模态的模型,因此把LSTM接到FC-4096更好。
最后模型就变成下面的样子:
图片的向量V会贯穿所有的单词向量的生成计算,上图中
W
i
h
Wih
Wih是一个转移矩阵,将图片向量V线性映射到LSTM模型的输入空间。
第一个单词w0就是y0
依次类推,直到生成end符号
这个多模态的模型解决的是看图说话的问题:
这个构架有几个问题:
1、很容易生成和图片无关的文字
2、当模型没有达到我们的预期的时候,我们如何去DEBUG,优化模型
3、整个序列的生成依赖于最后的向量V(这个向量包含了图片中的所有信息),难道我要生成一个关于狗狗的单词需要这样一个代表图片所有信息的向量吗?不用,只用注意到某一个部分就好
实例解析
中间的L×D的特征每一个都是
R
D
R^D
RD维的向量,然后根据这个L×D的特征来生成序列。下面来看注意力机制如何起作用。
在生成第一个单词的时候得到一个和个L×D一样大小的矩阵,这个矩阵可以看做权重,里面是概率,从例子上面看出,在生成第一个单词的时候,大概率要集中在第一列第二行的特征向量上。
对于第一个单词的权重
z
1
z_1
z1可以用下面方式计算:
然后生成第一个单词:
实际上就是加权平均:
z
=
∑
i
=
1
L
p
i
v
i
z=\sum_{i=1}^Lp_iv_i
z=i=1∑Lpivi
p
i
p_i
pi是权重,
v
i
v_i
vi是图的特征表示。
这用
a
2
a_2
a2和特征生成
z
2
z_2
z2,然后生成第二个单词
Attention for Machine Translation
下面来看看Seq2Seq中的Attention
上图中的输入可以用每个单词预训练好的词向量(pretrain embedding)直接进行输入,经过LSTM的Encoder部分得到
g
1
,
g
2
,
g
3
.
.
.
g_1,g_2,g_3...
g1,g2,g3...(Encoder部分和之前没有加attention机制是一样的,没有变化),然后一步生成得到
h
1
h_1
h1后,直接和每个
g
1
,
g
2
,
g
3
.
.
.
g_1,g_2,g_3...
g1,g2,g3...进行点乘,得到的结果(绿色)进行归一化(normalization),得到每个单词的权重,然后计算
C
′
C'
C′,
C
′
C'
C′就是新的content vector,和C不一样,上图中就是encoder结果乘以计算出来的每个单词的权重:
C
′
=
g
1
×
0.6
+
g
2
×
0.2
+
g
3
×
0.1
+
g
4
×
0.1
C'=g_1\times0.6+g_2\times0.2+g_3\times0.1+g_4\times0.1
C′=g1×0.6+g2×0.2+g3×0.1+g4×0.1
再用
C
′
C'
C′和
h
1
h_1
h1(直接concat)计算第一个词
y
^
1
\hat y_1
y^1,它的数学表达大概是:
y
^
1
=
s
o
f
t
m
a
x
(
w
h
y
⋅
(
c
o
n
c
a
t
(
C
1
′
&
h
1
)
)
+
b
)
\hat y_1=softmax(w_{hy}\cdot (concat(C_1'\&h_1))+b)
y^1=softmax(why⋅(concat(C1′&h1))+b)
这里经过softmax后会得到词库大小的概率分布,可以从这个分布里面找出最有可能的单词
y
^
1
\hat y_1
y^1。同样的还有
y
^
1
\hat y_1
y^1对应的
h
2
h_2
h2,然后用
y
^
1
\hat y_1
y^1和和每个
g
1
,
g
2
,
g
3
.
.
.
g_1,g_2,g_3...
g1,g2,g3...进行点乘,归一化后计算
C
1
′
C_1'
C1′,重复下去,直达结束。
小结
模型中计算注意力的时候用的
g
1
,
g
2
,
g
3
.
.
.
g_1,g_2,g_3...
g1,g2,g3...分别与
h
1
h_1
h1相乘来计算权重,但是我们可以看到,这个是LSTM生成的
g
1
,
g
2
,
g
3
.
.
.
g_1,g_2,g_3...
g1,g2,g3...,
g
1
g_1
g1是第一个单词的信息,
g
2
g_2
g2除了有第二个单词的信息之外,还包含有第一个单词的信息的。
注意力模型还为解决模型的调试给出了解决方案。
例如:
在翻译的时候翻译错了,有个yestoday,那么可以用注意力机制看是关注了哪个词翻译错的。
Self-Attention
这个是transformer的一个组成部分,这里先讲个大概,后面写BERT再讲。
中心思想就是句子本身的注意力,也就是考虑上下文对自己这个向量的影响。例如
本来《今天》这个单词就是有一个预训练好的向量,如果考虑Self-Attention操作,就会把上下文的影响考虑进来,得到一个新的向量,这个向量是包含了对《今天》这个单词不同影响的上下文关系在里面。这个过程具体以原文例子来看:
就是输入
x
1
,
x
2
x_1,x_2
x1,x2如何得到
z
1
,
z
2
z_1,z_2
z1,z2
论文原图先贴上:
x
1
,
x
2
x_1,x_2
x1,x2是预训练得到的向量
Queries、Keys、Values分别对应attention机制中的Q\K\V,它们是通过输入词向量分别和
W
Q
、
W
K
、
W
V
W^Q、W^K、W^V
WQ、WK、WV做乘积(例如:
x
1
⋅
w
q
x_1\cdot w^q
x1⋅wq)得到的。其目的主要是计算权值。(大写是原文中的矩阵表示。)
W
Q
、
W
K
、
W
V
W^Q、W^K、W^V
WQ、WK、WV是参数,是训练学习到的。
接下来要计算第二个单词对第一个单词的影响:
先计算score(别的单词对当前单词的重要性),注意计算当前
z
1
z_1
z1的时候,要用
q
1
q_1
q1来计算score这个代表当前单词在当前句子中的重要性。得到的分数分别是112和96,下面我们要计算权重,用归一化,普通归一化这样算:112/(112+96)和96/(112+96),这样计算的权重大家都差不多有没有?根本没法很好体现重要性。如果用softmax:
e
112
e
112
+
e
96
,
e
96
e
112
+
e
96
\frac{e^{112}}{e^{112}+e^{96}},\frac{e^{96}}{e^{112}+e^{96}}
e112+e96e112,e112+e96e96
这样就放大了score的差距,前者为1,后者为0。这样也太夸张了。要再小一点,所以把score除以了一个
d
k
\sqrt{d_k}
dk(这个是经验值,就是k的维度的开方),分别得到14和12,再softmax
e
14
e
14
+
e
12
,
e
12
e
14
+
e
12
\frac{e^{14}}{e^{14}+e^{12}},\frac{e^{12}}{e^{14}+e^{12}}
e14+e12e14,e14+e12e12
这样就得到上面的结果:0.88和0.12
然后把权重分别与v点乘,最后得到z。
原论文中用score做了词与词之间的相关性分析:
再贴一个例子的图:
每个单词对应的词向量是已知的,维度是64×1(假设)。那么下面的
q
1
=
w
Q
⋅
x
1
q_1=w^Q\cdot x_1
q1=wQ⋅x1是(32×64)×(64×1)=32×1大小的向量, k也是这个维度。下面计算score要得到一个一个标量,应该要对qk做转置:
q
T
⋅
k
T
q^T\cdot k^T
qT⋅kT相当于(1×32)×(1×32)=1维的标量,然后除以
d
k
\sqrt{d_k}
dk得到的结果,然后经过softmax得到概率,然后softmax的结果去点乘v,得到z,然后作为下一层的输入再进行计算。
小结
之前LSTM或者说RNN有三个问题:
1.long-term dependency(长句的时候,很难捕获远距离的依赖)
2.linear computation无法并行
3.shallow model(deep from time perspective,纵向的角度(浅层))
解决方案:
需要设计一个模型不依赖于沿着时间的梯度计算
需要设计一个非时序的模型
设计适合从纵向的方向叠加的模型
而注意力机制解决了:
问题1:由于在计算单词的score的时候,模型考虑所有单词两两之间的关系,所以不会存在后面的单词没有考虑到前面的单词的情况。
问题2:从计算的过程来看,Queries、Keys、Values还有score的计算过程都是可以按单词并行计算的(就是上图中垂直方向,而且都是矩阵计算),适合GPU并行。