7-2 自注意力机制 原理
上一章已经讲过什么是注意力,注意力有哪几种???
接下来,讲一下什么叫做自注意力机制??
李宏毅视频讲解:https://www.bilibili.com/video/BV1v3411r78R
PPT:https://speech.ee.ntu.edu.tw/~hylee/ml/ml2021-course-data/self_v7.pdf
自注意力机制
实际上是注意力机制
中的一种,
自注意力机制实际上也是一种网络的构型,它想要解决的问题是网络接收的输入是很多向量,并且向量的大小也是不确定的情况,比如机器翻译(序列到序列的问题,机器自己决定多少个标签),词性标注(Pos tagging一个向量对应一个标签),语义分析(多个向量对应一个标签)等文字处理问题。
1. 简介
Query,Key,Value的概念取自于信息检索系统
,举个简单的搜索的例子来说。
当你在某电商平台搜索某件商品(年轻女士冬季穿的红色薄款羽绒服)时,
- 你在搜索引擎上
输入的内容
便是Query
, - 然后搜索引擎根据Query为你匹配
Key
(例如商品的种类,颜色,描述
等), - 然后根据Query和Key的
相似度
得到匹配的内容(Value)
。
self-attention中的Q,K,V也是起着类似的作用,在矩阵计算中,点积是计算两个矩阵相似度的方法之一
,因此式1中使用了QKT进行相似度的计算。接着便是根据相似度进行输出的匹配,这里使用了加权匹配的方式,而权值就是query与key的相似度。
2. NLP中自注意力
自注意力计算公式
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
=
S
o
f
t
M
a
x
(
Q
K
T
d
)
V
Attention(Q,K,V)=SoftMax(\frac{QK^T}{\sqrt{d}})V
Attention(Q,K,V)=SoftMax(dQKT)V
现在我们有一组一维的向量,那么向量b是如何产生的呢?
步骤1: 对于每个向量 a a a,分别乘上三个系数 w q , w k , w v w^q,w^k,w^v wq,wk,wv,得到 q , k , v q,k,v q,k,v三个值
q i = w q ⋅ a i q^i=w^q\cdot a^i qi=wq⋅ai写成向量形式 Q = W q ⋅ I Q=W^q\cdot I Q=Wq⋅I
k i = w q ⋅ a i k^i=w^q\cdot a^i ki=wq⋅ai写成向量形式 K = W k ⋅ I K=W^k\cdot I K=Wk⋅I
v i = w q ⋅ a i v^i=w^q\cdot a^i vi=wq⋅ai写成向量形式 V = V q ⋅ I V=V^q\cdot I V=Vq⋅I
得到的Q,K,V分别表示query,key和value。这3个w的参数就是我们需要学习的参数
步骤2:
利用得到的
Q
Q
Q和
K
K
K计算每两个输入向量之间的相关性,也就是计算attention的值
α
\alpha
α,
α
\alpha
α的计算方法有多种,通常采用点乘
的方式。
α i , j = q i ⋅ k j \alpha_{i,j}=q^i\cdot k^j αi,j=qi⋅kj写成向量形式: A = K T ⋅ Q A=K^T\cdot Q A=KT⋅Q
矩阵A中的每一个值记录了对应的两个输入向量的Attention的大小 α \alpha α
Q K T QK^T QKT代表 n n n个查询向量(样本特征)与 n n n个键向量(信息特征)之间的相似度。
如果 A A A的第一行为 [ 2 , 5 , 3 ] [2,5,3] [2,5,3],则代表第一个样本与第一、二、三条信息之间的相似度2,5,3
步骤3:
对A矩阵进行softmax操作或者relu操作得到A’。通常为 S o f t m a x ( ⋅ / d k ) Softmax(\cdot/\sqrt{d_k}) Softmax(⋅/dk)
A ′ A^\prime A′就是各个样本与各条信息间相关或相似程度的分布
对于上一段提到的例子,我们简单地令 w ( x ) = x i ∑ x i w(x)=\frac{x_i}{\sum x_i} w(x)=∑xixi,得到 [ 0.2 , 0.5 , 0.3 ] [0.2,0.5,0.3] [0.2,0.5,0.3]。这代表第一个样本与第一、二、三条信息的相关或相似度分别为20%、50%和30%。
步骤4:利用得到的 A ′ A^\prime A′和 V V V计算每个输入向量a对应的self-attention层的输出向量b:
b i = ∑ j = 1 n v i ⋅ α i , j ′ b_i=\sum_{j=1}^nv_i\cdot \alpha_{i,j}^\prime bi=∑j=1nvi⋅αi,j′,写成向量形式 O = V ⋅ A ′ O=V\cdot A^\prime O=V⋅A′
A t t ( Q , K , V ) Att(Q,K,V) Att(Q,K,V)即值向量(信息)的加权和,权值为各个样本与各条信息间相关或相似程度的分布,这就是自注意力的最终结果。
拿第一个向量a1对应的self-attention输出向量b1举例,它的产生过程如下:
3. 图像中的自注意力+代码
代码来自SAGAN这篇论文:
论文代码: https://arxiv.org/abs/1805.08318
代码链接: https://github.com/heykeetae/Self-Attention-GAN
自注意力代码如下
import numpy as np
import torch
from einops import rearrange
from torch import nn
class Self_Attn(nn.Module):
""" Self attention Layer"""
def __init__(self, in_dim, activation=None):
super(Self_Attn, self).__init__()
# self.chanel_in = in_dim
# self.activation = activation
self.query_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1)
self.key_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1)
self.value_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim, kernel_size=1)
self.gamma = nn.Parameter(torch.zeros(1))
self.softmax = nn.Softmax(dim=-1) #
def forward(self, x):
"""
inputs :
x : input feature maps( B X C X W X H)
returns :
out : self attention value + input feature
attention: B X N X N (N is Width*Height)
"""
# batch,通道数,宽,高
m_batchsize, C, width, height = x.size() # [1, 16, 32, 32]
# 步骤1, 通过conv 得出q,k
q = self.query_conv(x).view(m_batchsize, -1, width * height).permute(0, 2,
1) # B X CX(N) torch.Size([1, 1024, 2])
k = self.key_conv(x).view(m_batchsize, -1, width * height) # B X C x (*W*H) torch.Size([1, 2, 1024])
# 步骤1, 计算得出v
v = self.value_conv(x).view(m_batchsize, -1, width * height) # B X C X N torch.Size([1, 16, 1024])
# 步骤2, 矩阵的乘法 ,q,k进行相乘,得出特征图
# [batch_size,1024,2]*[batch_size,2,1024]
energy = torch.bmm(q, k) # transpose check [1, 1024, 1024]
# 特征图attention map,通过softmax
attention = self.softmax(energy) # BX (N) X (N) torch.Size([1, 1024, 1024])
# 步骤3,v * 特征图= 注意力
# [1,16,1024] * [1,1024,1024]= torch.Size([1, 16, 1024])
out = torch.bmm(v, attention.permute(0, 2, 1)) # torch.Size([1, 16, 1024])
# 重新resize
out = out.view(m_batchsize, C, width, height) # torch.Size([1, 16, 32, 32])
# 加上残差
out = self.gamma * out + x
return out, attention
if __name__ == '__main__':
# 这个通道数需要 是8的倍数。因为 q,k,v 是使用conv算出的。 输出通道需要大于 8
x = torch.randn(size=(1, 16, 32, 32))
model = Self_Attn(16)
out, attention = model(x)
print(out.shape)
print(attention.shape)
4. 问题
自注意力机制虽然考虑了所有的输入向量,但没有考虑到向量的位置信息。在实际的文字处理问题中,可能在不同位置词语具有不同的性质,比如动词往往较低频率出现在句首。
有学者提出可以通过位置编码(Positional Encoding)来解决这个问题:对每一个输入向量加上一个位置向量e,位置向量的生成方式有多种,通过e来表示位置信息带入self-attention层进行计算。
[2003.09229] Learning to Encode Position for Transformer with Continuous Dynamical Model (arxiv.org)
参考资料
注意力机制 & 自注意力模型 - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/48508221文章来源:https://www.toymoban.com/news/detail-432447.html
(1条消息) 机器学习中的自注意力(Self Attention)机制详解_I am zzxn的博客-CSDN博客_自注意力机制公式文章来源地址https://www.toymoban.com/news/detail-432447.html
到了这里,关于7-2 自注意力机制 原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!