赞
踩
这里介绍的self-attention使用的方法是:Scaled Dot-Product Attention。采用点积计算相似度。
Scaled
指的是 Q和K计算得到的相似度 再经过了一定的量化,具体就是 除以
d
k
\sqrt{d_k}
dk
;Dot-Product
指的是 Q和K之间 通过计算点积作为相似度;Mask
可选择性 目的是将 padding的部分 填充负无穷,这样算softmax的时候这里就attention为0,从而避免padding带来的影响.Mask attention 的思想是 掩盖掉部分内容,不参与 attention 的计算,或许是因为不需要,或许因为不存在,根据实际场景来;A t t e n t i o n ( X , X , X ) = s o f t m a x ( X X T ) X Attention(X,X,X)=softmax(XX^T)X Attention(X,X,X)=softmax(XXT)X
自注意力机制指的是输入都是同一个矩阵 X X X,并不代表 Q , K , V Q,K,V Q,K,V是相同的。
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dk QKT)V
缩放的必要性
使用 d k \sqrt{d_k} dk 的效果
在注意力机制中,尤其是在自注意力和Transformer模型中,输入通常是一个统一的输入矩阵 X X X,而这个矩阵后续会通过乘以不同的权重矩阵来转换成三个不同的向量集合:查询向量 Q Q Q、键向量 K K K和值向量 V V V。这三组向量是通过如下方式生成的:
这里的 W Q W^Q WQ, W K W^K WK, 和 W V W^V WV 是可学习的权重矩阵,分别对应于查询、键和值。这些矩阵的维度取决于模型的设计,通常它们的输出维度(列数)是预先定义的,以满足特定的模型架构要求。
在Transformer模型中,使用不同的权重矩阵 W Q W^Q WQ, W K W^K WK, 和 W V W^V WV来分别生成查询向量 Q Q Q、键向量 K K K 和值向量 V V V 的目的是为了允许模型在不同的表示空间中学习和抽取特征。这样做增加了模型的灵活性和表达能力,允许模型分别优化用于匹配(Q 和 K)和用于输出信息合成(V)的表示。
理论上,可以使用同一个权重矩阵来生成
Q
Q
Q、
K
K
K 和
V
V
V,但这样做会限制模型的能力。如果使用相同的矩阵,那么
Q
、
K
、
V
Q、K、V
Q、K、V三者将无法在不同的表示空间中进行优化,从而可能导致模型无法充分捕捉到输入数据中的复杂关系。实际上,这种设计减少了模型的灵活性,可能导致性能下降。
并且使用相同的Q,K,V会导致,同一个注意力机制会为上下文中的相同向量分配非常大的分数,而实际上注意力机制更关注相关词之间的关系。
注意力机制并不全是自注意力机制,因此输入并不全是相同的。
注意力机制多种多样,各有特点,适用于不同的应用和任务。下面列举几种常见的注意力机制,并说明它们的输入及相应的权重矩阵情况:
理解了上述
X
X
X到
Q
,
K
,
V
Q,K,V
Q,K,V的转换,实际上就很容易实现自注意力机制了,转换实际上是一个线性变换,因此只需要使用三个Linear
层分别表示三个权重矩阵即可。Linear层使用解释。
根据原理,我们可以得出以下结论:
理论上,由于 Q Q Q和 K K K求的是不同向量的相关度(点积),因此 W Q , W K W^Q,W^K WQ,WK的形状必须相同。而 W V W^V WV是用来定义输出的形状的,可以不同。但是我们这里将输出的形状定义为与输入 X X X形状相同,因此线性层输入输出相同。
以下代码是Self-Attention
示例,可以发现它和公式高度匹配。
import torch
import torch.nn as nn
import torch.nn.functional as F
class SelfAttention(nn.Module):
def __init__(self,seq_length):
super(SelfAttention,self).__init__()
self.input_size = seq_length
# 定义三个权重矩阵
self.Wq=nn.Linear(seq_length,seq_length)#不改变形状的线性变换
self.Wk=nn.Linear(seq_length,seq_length)
self.Wv=nn.Linear(seq_length,seq_length)
def forward(self,input):
# 计算Q,K,V 三个矩阵
q = self.Wq(input)
k = self.Wk(input)
v = self.Wv(input)
# 计算QK^T,即向量之间的相关度 ; 这里可以理解dk了:torch.tensor(float(self.input_size)),是Wk的维度。
attention_scores = torch.matmul(q, k.transpose(-1,-2))/torch.sqrt(torch.tensor(float(self.input_size)))
# 计算向量权重,softmax归一化
attention_weight = F.softmax(attention_scores, dim=-1)
# 计算输出
output = torch.matmul(attention_weight, v)
return output
x = torch.randn(2,2,3)
Self_Attention = SelfAttention(3) # 这里的3表示输入向量的维度。
output = Self_Attention(x)
print(output.shape) #[2,2,3]
通过以上代码可以发现,自注意力机制在这里体现为,输入一个x
,得到一个output
,这里输入和输出是相同形状的。换句话说,自注意力机制通过将 输入向量与整个输入向量加权求和,得到的每个输出向量是包含所有加权后输入向量信息的向量。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。