多头注意⼒机制的概念、具体流程以及相关代码
1、多头注意⼒的概念
⾃注意⼒模型可以看作为在⼀个线性投影空间中建⽴输⼊向量中不同形式之间的交互关系。多头注意⼒就是在多个不同的投影空间中建⽴不同的投影信息。将输⼊矩阵,进⾏不同的投影,得到许多输出矩阵后,将其拼接在⼀起。
从下图中可以看出V K Q 是固定的单个值,⽽Linear层有3个,Scaled Dot-Product Attention 有3个,即3个多头;最后cancat在⼀起,然后Linear层转换变成⼀个和单头⼀样的输出值;类似于集成;多头和单头的区别在于复制多个单头,但权重系数肯定是不⼀样的;类⽐于⼀个神经⽹络模型与多个⼀样的神经⽹络模型,但由于初始化不⼀样,会导致权重不⼀样,然后结果集成。
幽默的故事
attention层本质就是特征提取器,是基于整个序列提取了潜在的特征,因为每个embedding向量都融
⼊了其他的embedding的信息,能⽣成有意义的特征,去除了⽆关的噪⾳。
上⾯是我查到的关于多头注意⼒机制的模型描述,这⾥谈谈我对其的理解:在求hi的公式中,给定的查询、键、值应该是指输⼊矩阵X,⽽
开始这些是相同的,通过相应的权重分别计算出对应的查询、键、值,⽽每⼀个头的权重是不同的,所以有Wi。接下来就分别在每⼀个头上各⾃计算对应的⾃注意输出,最后有⼏个头就得到⼏个结果,然后将其拼接,乘以相应的权重,从⽽得到最终的结果。(以上是⾃⼰的理解,有不对的地⽅请批评指正,谢谢!)
具体流程如下图所⽰
2、pytorch实现多头注意机制
3 代码
as nn
class Attention(nn.Module):
def__init__(lf,dim,num_heads=8,qkv_bias=Fal,qk_scale=None,attn_drop=0.,proj_drop=0.):
super(Attention, lf).__init__()
lf.num_heads = num_heads
head_dim = dim // num_heads
#这⾥的dim指的是c,即input输⼊N个数据的维度。
# 另外,为避免繁琐,将8个头的权重拼在⼀起,⽽三个不同的权重由后⾯的Linear⽣成。
# ⽽lf.qkv的作⽤是是将input X (N,C)与权重W(C,8*C1*3)相乘得到Q_K_V拼接在⼀起的矩阵。
微信如何群收款
# 所以,dim*3表⽰的就是所有头所有权重拼接的维度,即8*C1*3。即dim=C=C1*3。
lf.scale = qk_scale or head_dim **-0.5
lf.qkv = nn.Linear(dim,dim *3,bias = qkv_bias)
#bias默认为True,为了使该层学习额外的偏置。
lf.attn_drop = nn.Dropout(attn_drop)
#dropout忽略⼀半节点
lf.proj = nn.Linear(dim,dim)
lf.proj_drop = nn.Dropout(proj_drop)
def forward(lf, x):
B,N,C = x.shape
#B为batch_size
qkv = lf.qkv(x).reshape(B,N,3,lf.num_heads,C // lf.num_heads).permute(2,0,3,1,4)
同开头的成语#将x构造成⼀个(B,N,3,8,c1)的⼀个矩阵,然后将其变成(3,B,8,N,c1)。
雷锋的故事读后感
#是为了使得后⾯能将其分为三部分,分别作为不同的权重,维度为(B,8,N,c1)骨传导耳机优缺点
q,k,v = qkv[0],qkv[1],qkv[2]
attn =(q @ k.transpo(-2,-1))* lf.scale
教育程度
#将k的维度从(B,8,N,c1)转变为(B,8,c1,N),其实就是对单头key矩阵转置,使Query*key^T,得到scores结果,然后×lf.scale,即×C1的-0.5。
#就是做⼀个归⼀化。乘⼀个参数,不⼀定是这个值。
#维度为(B,8,N,N)
attn = attn.softmax(dim =-1)
#对归⼀化的scores做softmax
去动物园英语
# 维度为(B,8,N,N)
x =(attn @ v).transpo(1,2).reshape(B,N,C)
#将scores与values矩阵相乘,得到数据维度为(B,8,N,C1),使⽤transpo将其维度转换为(B,N,8,C1)
x = lf.proj(x)
#做⼀个全连接
英语作文我的老师x=lf.proj_drop(x)
#做Dropout
return x
#得到多头注意⼒所有头拼接的结果。