论文:https://arxiv.org/pdf/1706.03762.pdf
目录
论文:https://arxiv.org/pdf/1706.03762.pdf
Attention注意力机制:
Attention起源于NLP中的seq2seq模型,通常是RNN结构,对于这种结构,每一层传给下一层的向量长度是固定的,所以,当句子很长时,很难表达全部的信息,一开始的信息在后面就会容易丢掉。例如一个句子,“我喜欢吃苹果因为。。。(省略N个字)”,作为RNN的输入,希望输出回答“谁喜欢吃苹果”,当输入全部处理后,这时模型就可能已经丢掉了“我”这个信息了。
这时,Attention机制的出现就很及时了,它会让我们选择性的关注一些区域,这样有限的向量常度,能让我们传递更值得注意的特征。在图像上的部分表现可以用下图展示
QKV计算:query key value
要理解这三个概念的含义,首先要明白 self-attention 最终想要的是什么?
给定当前输入样本 ( 为了更好地理解,我们把输入进行拆解),产生一个输出,而这个输出是序列中所有样本的加权和。因为假设这个输出能看到所有输入的样本信息,然后根据不同权重选择自己的注意力点。
注意力的计算方法,给定一个query,当前的输入样本 x_i,通过空间变换变成了一个 query_i,计算query_i和所有输入样本的key的相关性,会进行如下操作 r_i = query_i * key^T,这样 r_i 每一个元素就可以看做是当前样本 x_i 与序列中其他样本之间的关系向量,然后根据query与key的相关性得到value的加权和即为注意力,你可以认为value中的每一行是序列的一个样本经过网络后,网络认为有用的信息。举个例子:在电影推荐中。query 是某个人对电影的喜好信息(比如兴趣点、年龄、性别等)、key 是电影的类型(喜剧、年代等)、value 就是待推荐的电影。在这个例子中,query, key 和 value 的每个属性虽然在不同的空间,其实他们是有一定的潜在关系的,也就是说通过某种变换,可以使得三者的属性在一个相近的空间中, 但注意self-attention 不是为了 query 去找 value,而是根据当前 query 获取 value 的加权和来获取对输入样本的注意力。
下面举例说明,第一步是从每个编码器的输入向量创建三个向量分别是query,key和value。因此对于每个单词创建一个查询向量、一个键向量和一个值向量,这些向量是通过将嵌入乘以我们在训练过程中训练的三个矩阵WQ、WK、WV来创建的。
将X1乘以WQ得到q1,其他类似操作得到q2, k1, k2, v1, v2。
第二步我们计算一个相关性分数score,分数是通过query和所有的key的点积来得到的
第三步是将分数除以key向量维度的平方根,一般为关键向量维度为64,所以要除以8.
第四步是通过softmax对score进行归一化操作。
第五步是将归一化后的分数分别乘以对应的value向量。
第六步是将加权后的value向量相加,得到自注意力z1, z2。
最后,因为都是矩阵计算,所以将第二步到第六步合并成一个公式计算
transformer特点:
1、encoder+attention+decoder结构。
2、无局部假设,于是可并行计算,且对相对位置不敏感。
3、无有序假设,于是需要位置编码来反映位置变化对于特征的影响。
异同:
1、CNN:权重共享所以有平移不变性,所以也可以并行计算,但滑动窗口形成了局部关联性,所以对相对位置敏感,对绝对位置不敏感。
2、RNN:通常是串行计算,耗时但对顺序敏感,计算复杂度也与输入序列长度呈线性关系,对相对位置和绝对位置都敏感。
整体框架:
左边为encoder部分,右边为decoder部分。
Encoder:
对输入做embedding 和位置编码后,放入N个layer组成的encoder。embedding是为了防止输入没有预定的维数或超出,进行降维或升维。
每个layer由两部分组成,第一部分是多头自注意力层Multi-Head Attention,第二部分是一个前馈神经网络Feed Forward。
Multi-Head Attention:
多头自注意力为什么要多头?这是一种提高自注意力层性能的方法。例如,当猫抓老鼠时,它是怎么跑的,这里的它是指猫还是老鼠?使用多头注意力机制能够联合来自不同 head 部分学习到的信息,每个head有一个结果,然后我们会对所有头的结果进行“投票”来得到最终的结果。如上面的例子,单个头得到一个Z,假设我们有8个头则得到8个Z:
当然,Feed Forward层不需要这么多Z,所以我们用了一个额外的权重矩阵 WO来将8个Z矩阵合并成一个,也就是前面说的“投票”了。
Decoder:
对于decoder部分,也有N个layer组成,每个layer有3个部分,第一个部分带掩码的多头自注意力层Masked Multi-Head Attention 的输入是上一次的输出,而为什么有mask喃?是因为为了防止把当前字符之前的字符传进去。第二个是一个交叉的Multi-Head Attention,把encoder的输出作为key 和 value, Masked Multi-Head Attention的输出作为query,来算出encoder输入序列和decoder输入序列的关联性,第三部分是一个前馈神经网络Feed Forward。最后进入一个线性层和softmax。
位置编码:
可以看DETR源码笔记(一)_在努力的松鼠的博客-优快云博客_detr源码里有该部分代码详解。
因为transformer对位置信息不敏感,所以需要加一个position encoding信息加到input里,一般使用正余弦编码,这样每个位置的编码都是被确定的,不管重新编码多少次,相同的位置,编码也不会变,也不会被输入大小长短限制。
feed forward network 只考虑单独的特征,不会关心周围的其他特征。也可以说每一个feed forward network 的输入都会经过一个相同的网络。