transformer的核心是self-attention,self-attention可参考:
一、机器翻译
对于机器翻译而言,分为源语言与目的语言(如英文与中文)
对源语言建立词典,大小为src_vocab_size (包括padding)
对目标语言建立词典,大小为tgt_vocab_size (包括padding)
在词典中对词进行排序(放好位置就行),按照下标给词一个数字表示(0一定表示padding,得规定好)
训练集为源语言与目标语言的一一对应关系,但是
- 源语言与目标语言对应的句子的长度很可能不一致
- 源语言与目标语言中所有句子可能有长有短
二、数据处理
1、batch
模型中要通过矩阵加速运算,如果是一对句子一对句子的输入模型进行训练就行,但是训练是需要分批输入到模型中的。
所以一个bacth中的句子需要是等长度的所以需要padding,即填充0。
以下为一个batch的处理过程:
最终一个batch的输入格式为(B,L)
B为batch_size, L为本次batch的输入的句子的单词个数
2、embedding
源语言与目标语言词典中的每一个词都可以转换为一个
d
m
o
d
e
l
d_{model}
dmodel长度的向量,词向量可以预训练得来,也可以加入到此网络中进行训练。词向量类似与一个矩阵:
源语言的词向量矩阵如上所示,每一行为一个词向量,可以用每一个词的代表数字表示当成行标直接去取对应的词向量
最终将一个batch的输入转换为(B,L,d_model)
B为batch_size, L为本次batch的输入的句子的单词个数,d_model为词向量长度
3、pad Mask
加入了padding,但是padding是不能加入到self-attention的计算中的, 这意味着什么呢?
思考一下self-attention中会产生一个单词与单词之间的关系矩阵,每个单词的query向量与所有单词的key向量点乘再除以向量长度取根号,之后经过softmax层归一化将其变为都是正数并且加起来等于 1。 (Scaled Dot-Product attention)
最终形成的矩阵格式为(L,L),表示一个句子的各个词之间的关系分数。
第一行就表示第一个单词与其他所有单词的关系分数,每一行的和为1
但是我们说单词与padding之间是没有关系的,即单词与padding之间的关系分为为0,那把softmax之后分数直接置为0
不行,因为行的和不再为1,这样就不合理了,所以我们在softmax之前做操作。
回忆一下softmax的公式:
要让某个值为0,只需要让
z
i
z_i
zi为负无穷即可,所以只需要让softmax之前的矩阵的padding列全为无穷即可,softmax之前的矩阵如下所示:
注:
为什么不考虑padding的行呢?
我的理解是padding行最终也会输出一个向量,但是这个向量不会参数到self-attention的计算中,所以不用管它
三、encoder
采用论文中的描述
“编码器由N = 6个相同的层组成。每层有两个子层。
第一个是一个多头自注意机制
第二个是一个简单的,位置上完全连接的前馈网络。
我们在两个子层周围使用一个残差连接,然后是层规范化。
也就是说,每个子层的输出是LayerNorm(x +子层(x)),其中子层(x)是由子层本身实现的函数。
为了方便这些残差连接,模型中的所有子层以及嵌入层产生的输出维数dmodel = 512。”
如下所示:
一层encoder(图中标识为N层)
1、 输入
(1)输入矩阵:(B,L)
(2)单词embedding:(B,L,d_model)
(3)加上position_embedding:(B,L,d_model)
2、multi-Head attention
注:论文中 d q = d k = d v = d m o d e l / n h e a d s d_q = d_k = d_v = d_{model} / n_{heads} dq=dk=dv=dmodel/nheads
(1)转换为Q,K,V矩阵
(
B
,
L
,
d
m
o
d
e
l
)
−
>
(
B
,
L
,
d
q
∗
n
h
e
a
d
s
)
(B,L,d_{model}) -> (B,L,d_q * n_{heads})
(B,L,dmodel)−>(B,L,dq∗nheads) Q矩阵
(
B
,
L
,
d
m
o
d
e
l
)
−
>
(
B
,
L
,
d
k
∗
n
h
e
a
d
s
)
(B,L,d_{model}) -> (B,L,d_k * n_{heads})
(B,L,dmodel)−>(B,L,dk∗nheads) K矩阵
(
B
,
L
,
d
m
o
d
e
l
)
−
>
(
B
,
L
,
d
v
∗
n
h
e
a
d
s
)
(B,L,d_{model}) -> (B,L,d_v * n_{heads})
(B,L,dmodel)−>(B,L,dv∗nheads) V矩阵
一个线性层nn.Linear
就可以完成
(2)对每个注意力头进行soft-atttention计算
(1)把头提出来
(
B
,
L
,
d
q
∗
n
h
e
a
d
s
)
−
>
(
B
,
n
h
e
a
d
s
,
L
,
d
q
)
(B,L,d_q * n_{heads}) -> (B,n_{heads},L,d_q)
(B,L,dq∗nheads)−>(B,nheads,L,dq) Q矩阵
(
B
,
L
,
d
k
∗
n
h
e
a
d
s
)
−
>
(
B
,
n
h
e
a
d
s
,
L
,
d
k
)
(B,L,d_k * n_{heads}) -> (B,n_{heads},L,d_k)
(B,L,dk∗nheads)−>(B,nheads,L,dk) K矩阵
(
B
,
L
,
d
q
∗
n
h
e
a
d
s
)
−
>
(
B
,
n
h
e
a
d
s
,
L
,
d
v
)
(B,L,d_q * n_{heads}) -> (B,n_{heads},L,d_v )
(B,L,dq∗nheads)−>(B,nheads,L,dv) V矩阵
(2)Scaled Dot-Product Attention
<1>
(
Q
∗
K
T
)
/
d
k
(Q * K^T)/ \sqrt{d_k}
(Q∗KT)/dk ->
(
B
,
n
h
e
a
d
s
,
L
,
L
)
)
(B,n_{heads},L,L))
(B,nheads,L,L))
(
K
T
K^T
KT 对最后两位进行转置,变为
(
B
,
n
h
e
a
d
s
,
d
k
,
L
)
)
(B,n_{heads},d_k,L))
(B,nheads,dk,L))
<2> mask结果,将padding列变为-inf
<3>对每一行进行softmax
<4>乘以V矩阵 ->
(
B
,
n
h
e
a
d
s
,
L
,
d
v
)
)
(B,n_{heads},L,d_v))
(B,nheads,L,dv))
(3)多头融合
<1>
(
B
,
n
h
e
a
d
s
,
L
,
d
v
)
)
(B,n_{heads},L,d_v))
(B,nheads,L,dv)) ->
(
B
,
L
,
n
h
e
a
d
s
∗
d
v
)
)
(B,L,n_{heads} * d_v))
(B,L,nheads∗dv))
<2>
(
B
,
L
,
n
h
e
a
d
s
∗
d
v
)
)
(B,L,n_{heads} * d_v))
(B,L,nheads∗dv)) ->
(
B
,
L
,
d
m
o
d
e
l
)
)
(B,L,d_{model}))
(B,L,dmodel)) (线性层)
3、残差连接+layerNorm
(1)模型输入与多头注意力层的输出格式相同: ( B , L , d m o d e l ) ) (B,L,d_{model})) (B,L,dmodel)) 直接相加
(2)layerNorm
4、Position-wise Feed-Forward
(1)全连接层 + relu
( B , L , d m o d e l ) ) (B,L,d_{model})) (B,L,dmodel)) -> ( B , L , d f f ) ) (B,L,d_{ff})) (B,L,dff))
(2)全连接层
( B , L , d f f ) ) (B,L,d_{ff})) (B,L,dff)) -> ( B , L , d m o d e l ) ) (B,L,d_{model})) (B,L,dmodel))
5、残差连接+layerNorm
(1)模型输入与多头注意力层的输出格式相同: ( B , L , d m o d e l ) ) (B,L,d_{model})) (B,L,dmodel)) 直接相加
(2)layerNorm
最终encoder输出格式为 ( B , L , d m o d e l ) (B,L,d_{model}) (B,L,dmodel)
四、decoder
decoder与encoder主要有两个部分不同
1、subsequence_mask
之前描述了pad_mask,是由于真正的单词与padding之间不能有关系,关系系数为0。
subsequence_mask是针对目标语言的输入embedding而言的,在self-attention时我们要算各个词之间的关系分数。考虑一下利用RNN的翻译模型,目标语言是按顺序一个一个输入进网络中,即前面的词不知道后面的词,即前面的词不能算跟后面的词之间的关系,但是后面的词可以跟前面算关系。mask矩阵如下,
而且padding的mask也要考虑,最终变为
2、encoder-decoder attention
这一部分输入与之前不同,之前是这样的
(
B
,
L
,
d
m
o
d
e
l
)
−
>
(
B
,
L
,
d
q
∗
n
h
e
a
d
s
)
(B,L,d_{model}) -> (B,L,d_q * n_{heads})
(B,L,dmodel)−>(B,L,dq∗nheads) Q矩阵
(
B
,
L
,
d
m
o
d
e
l
)
−
>
(
B
,
L
,
d
k
∗
n
h
e
a
d
s
)
(B,L,d_{model}) -> (B,L,d_k * n_{heads})
(B,L,dmodel)−>(B,L,dk∗nheads) K矩阵
(
B
,
L
,
d
m
o
d
e
l
)
−
>
(
B
,
L
,
d
v
∗
n
h
e
a
d
s
)
(B,L,d_{model}) -> (B,L,d_v * n_{heads})
(B,L,dmodel)−>(B,L,dv∗nheads) V矩阵
同一个输入,转换为Q,K,V矩阵
现在变为这样
(
B
,
L
o
u
t
p
u
t
s
,
d
m
o
d
e
l
)
(
来
自
o
u
t
p
u
t
s
)
−
>
(
B
,
L
o
u
t
p
u
t
s
,
d
q
∗
n
h
e
a
d
s
)
(B,L_{outputs},d_{model}) (来自outputs) -> (B,L_{outputs},d_q * n_{heads})
(B,Loutputs,dmodel)(来自outputs)−>(B,Loutputs,dq∗nheads) Q矩阵
(
B
,
L
i
n
p
u
t
s
,
d
m
o
d
e
l
)
(
来
自
i
n
t
p
u
t
s
)
−
>
(
B
,
L
i
n
p
u
t
s
,
d
k
∗
n
h
e
a
d
s
)
(B,L_{inputs},d_{model}) (来自intputs) -> (B,L_{inputs},d_k * n_{heads})
(B,Linputs,dmodel)(来自intputs)−>(B,Linputs,dk∗nheads) K矩阵
(
B
,
L
i
n
p
u
t
s
,
d
m
o
d
e
l
)
(
来
自
i
n
t
p
u
t
s
)
−
>
(
B
,
L
i
n
p
u
t
s
,
d
v
∗
n
h
e
a
d
s
)
(B,L_{inputs},d_{model}) (来自intputs) -> (B,L_{inputs},d_v * n_{heads})
(B,Linputs,dmodel)(来自intputs)−>(B,Linputs,dv∗nheads) V矩阵
query矩阵来自outputs,key矩阵、value矩阵来自inputs,相当于decoder从encoder的输出中选取数据来完成自己的输出,与sequence to sequence模型有异曲同工之妙。
最终Linear层之前的输出为 ( B , L o u t p u t s , d m o d e l ) (B,L_{outputs},d_{model}) (B,Loutputs,dmodel)
3、翻译输出
linear之后softmax
(
B
,
L
o
u
t
p
u
t
s
,
d
m
o
d
e
l
)
(B,L_{outputs},d_{model})
(B,Loutputs,dmodel) ->
(
B
,
L
o
u
t
p
u
t
s
,
t
g
t
_
v
o
c
a
b
_
s
i
z
e
)
(B,L_{outputs},tgt\_vocab\_size)
(B,Loutputs,tgt_vocab_size)
选取每个位置概率最大的单词输出,即为翻译