Attention机制
2017年,Google机器翻译团队发表的《Attention is All You Need》中,完全抛弃了RNN和CNN等网络结构,而仅仅采用Attention机制来进行机器翻译任务,并且取得了很好的效果。
主流框架
图中所示的框架用于得到注意力值(Attention Value)。对于指定的Target中的某个元素Query,通过计算Query和各个元素相似性或者相关性,得到每个Key对应Value的权重系数,将权重进行归一化后对Value进行加权求和,得到最终的Attention值
可以将这一过程看作软寻址,序列中每一个元素都由key(地址)和value(元素)数据对存储在存储器里,当有query=key的查询时,需要取出元素的value值(也即query查询的attention值),与传统的寻址不一样,它不是按照地址取出值的,它是通过计算key与query的相似度来完成寻址。这就是所谓的软寻址,它可能会把所有地址(key)的值(value)取出来,上步计算出的相似度决定了取出来值的重要程度,然后按重要程度合并value值得到attention值,此处的合并指的是加权求和。
Self-Attention
Self Attention能够更容易的捕获序列中长距离的相互依赖的特征,对于RNN及其变体来说需要经过较长时间步的信息积累才可能活得,而Self Attention能够直接通过一个计算步骤得到联系。
除此外,Self Attention对于增加计算的并行性也有直接帮助作用。
计算过程
一、将输入的Input向量经过变换(可以使用简单的神经网络)得到对应的Embedding向量。
二、对于每一个Input,我们创建三个向量:Query向量(Q)、Key向量(K)和Value向量(V)。这三个向量通过将Embedding向量乘以三个权重矩阵得到:
权重矩阵在模型训练过程中训练得到。
三、通常,计算得到的Q、K、V的维度低于Embedding向量(如:10×100 维的 Embedding 映射为 10×20 维的 Q,其中Wq 的维度为 100×20)
四、计算当前输入Input(i)的Self-Attention Socre,第一个score将是Qi和K1的点积。第二个score是Qi和K2的点积,一直进行点积到末尾结束。
五、对Self-Attention Socre进行缩放和归一化,得到更平稳的结果。
六、将Softmax之后的Self-Attention Socre乘以Value向量,求和得到Attention Value。
Multi-Head Attention
Multi-Head Attention 就是在self-attention的基础上,对于输入的embedding矩阵使用多组权重矩阵与Embedding进行点击,得到多组Q、K、V。最后将得到的结果进行拼接。
Transformer
Transformer整体结构如下:
使用Self-attention模块以及其他相关层即可组合得到Transformer模型的Encoder以及Decoder。
使用N个Encoder以及N个Decoder进行分析
Token&Positional Embedding
1、将输入进行Embedding操作,映射到更高维度的特征空间。将Embedding后的Input与位置编码(Positional Encoding)进行相加,得到带位置编码的输入
class TokenAndPositionEmbedding(layers.Layer):
def __init__(self, maxlen, vocab_size, embed_dim):
super().__init__()
self.token_emb = layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)
self.pos_emb = layers.Embedding(input_dim=maxlen, output_dim=embed_dim)
def call(self, x):
maxlen = tf.shape(x)[-1]
positions = tf.range(start=0, limit=maxlen, delta=1)
positions = self.pos_emb(positions)
x = self.token_emb(x)
return x
def get_config(self):
# 返回层的配置参数
config = super(TokenAndPositionEmbedding, self).get_config()
config.update({
# 'maxlen': self.maxlen,
'vocab_size': self.vocab_size,
'embed_dim': self.embed_dim,
# 'rate': self.rate,
})
return config
2.1、Encoder以及Decoder包含多头注意力机制
self.att = keras.layers.MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim)
attn_output = self.att(inputs, inputs)
2.2、Add & Norm
self.layernorm1 = keras.layers.LayerNormalization(epsilon=1e-6)
out1 = self.layernorm1(inputs + attn_output)
2.3、Feed Forward
两层全连接,第一层激活函数为Relu,第二层无激活函数,其输出维度和输入一样
self.ffn = keras.Sequential(
[keras.layers.Dense(ff_dim, activation="relu"), keras.layers.Dense(embed_dim),]
)
参考:
详解Self-Attention和Multi-Head Attention - 张浩在路上 (imzhanghao.com)