qkv就是Query,Key和Value,这个概念很早就有,随着transformer的爆火,在注意力领域该结构可以说是最典型的、最重要的。我接触深度学习是从视觉领域入手的,调研了很多注意力结构,比如SENet等等。注意力领域也有诸多细分,比如通道注意力、空间注意力等。我总结为注意力结构就是生成一个权重,附加到内容上,效果就是只关注某部分内容,忽略其他内容。如果权重由内容本身生成,就是自注意力机制。

transformer论文地址:https://arxiv.org/abs/1706.03762

qk就是我理解的权重,v就是内容。但我总也理解不了Query和Key的区别,尤其是从代码的角度来看这个问题,特征x过一个全联接层得到Query,过另一个全连接层得到Key,让q和k的概念互换一下似乎也没啥问题吧。代码地址:https://github.com/LiamMaclean216/Pytorch-Transfomer/blob/master/utils.py

class Key(torch.nn.Module):
    def __init__(self, dim_input, dim_attn):
        super(Key, self).__init__()
        self.dim_attn = dim_attn
        
        self.fc1 = nn.Linear(dim_input, dim_attn, bias = False)
        #self.fc2 = nn.Linear(5, dim_attn)
    
    def forward(self, x):
        x = self.fc1(x)
        #x = self.fc2(x)
        
        return x

class Query(torch.nn.Module):
    def __init__(self, dim_input, dim_attn):
        super(Query, self).__init__()
        self.dim_attn = dim_attn
        
        self.fc1 = nn.Linear(dim_input, dim_attn, bias = False)
        #self.fc2 = nn.Linear(5, dim_attn)
    
    def forward(self, x):
        
        x = self.fc1(x)
        #print(x.shape)
        #x = self.fc2(x)
        
        return x

然后我们来看看论文,Q和K有怎么计算呢,仅仅就是Q乘以K的转置,然后再softmax,然后除以维度开根,做个简单的归一化。这种级别的计算是一种简单的结构,但是我认为还是很弯弯绕绕的,没有SENet那么简单好理解,我尤其不能理解Q和K,在我看来就算只有一项也能行吧。

transformer最早应用于NLP领域,很多博客解释这个问题从NLP角度出发,我总结理解不了。图像领域也有很多qkv的结构,ViT、Twins等在CV上把QKV用的得心应手。我仍不能理解对于一个图,QKV对应着什么级别的概念。经过最近的调研,我把自己的理解写下来,欢迎大家讨论、纠错。我把某些具体的含义带入到了推理过程,方便描述QKV的抽象概念。

我的理解

我们通过人类区分猫狗时候的QKV,联想模型区分猫狗时候的QKV。

从人类角度区分猫狗的话,我们可以从以下角度做对比:耳朵的弯曲程度、胡子长度与脸长度的比例、嘴巴长度与脸长度的比例、花纹、眼睛、爪子、尾巴。经过我这几年的观察,我发现了以下规律。耳朵上,弯耳大概率是狗(小部分狗是直耳),直耳大概率是猫;胡子上,胡子长度接近脸长的是大概率猫,胡子短的是大概率狗;嘴长上,嘴长接近脸长的大概率是狗,嘴长明显小于脸长的大概率是猫。

上述是我通过观察总结的经验,现在有一张我没见过的图片,它的特点如下:

我通过查找图片中的对比项,我可以轻松地得出这个动物大概率是猫,即使胡子的长度不是很清晰,不绝对符合猫的特征,能看到的胡子长度是我们之前总结胡子长度的中间值。但是其他两项还是足够支撑我们作出预测。

总结一下上述过程,“经过我这几年的观察”就是模型的训练过程,新图片预测大概率是猫是一次推理过程。QKV隐藏在推理过程中,我们接下来再细致地区分一下加了注意力的推理过程。

推理时,我先看到这个图片,然后我看到直耳、短嘴、胡子长度好像是脸长的四分之三、黄色花纹。那么对于这个图,胡子没啥区分度就不关注了,花纹也不管了。这个图我们只需要关注耳朵和嘴巴位置就行了,得到下面的注意图,黑色部分不关注,只关注白色部分:

Query就是直耳、短嘴、胡子长度这些特征,Key就是耳朵、嘴长、胡子长度这些项。Query与Key运算得到的就是这些特征对于区分猫狗重不重要,重要的就关注,不重要的就不关注。

Key很难理解,我们具体到向量,key向量可以理解为:此图中不同项的不同值的重要性;此时Query向量就是此图中某些项的特征值。Query向量作为索引,key向量就是字典,查到的值就是重要性。

为什么key向量一定是通过全图特征计算得到?我们本来就知道耳朵、嘴巴和胡子是重要的,而花纹是不重要的,只需要一个常量就行了?因为并不是所有的图都有清晰的胡子,这个图的胡子并没有拍清楚,只能看到隐约的长度,那么胡子长度就不是关键的特征,就不需要关注了。

在transformer中,这一部分输出为:

对应到transformer结构图就是红色箭头的位置:

Value是整个图片的特征图,这里我们借用原图展示。整个注意力结构的输入输出如下:

ViT的推理过程实际上要复杂些,首先将图片做patch embedding,还做了位置编码,使用的是multi-head attention,并堆叠多个block。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐