图解transformer中的自注意力机制

这篇具有很好参考价值的文章主要介绍了图解transformer中的自注意力机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文将将介绍注意力的概念从何而来,它是如何工作的以及它的简单的实现。

注意力机制

在整个注意力过程中,模型会学习了三个权重:查询、键和值。查询、键和值的思想来源于信息检索系统。所以我们先理解数据库查询的思想。

假设有一个数据库,里面有所有一些作家和他们的书籍信息。现在我想读一些Rabindranath写的书:

图解transformer中的自注意力机制

在数据库中,作者名字类似于键,图书类似于值。查询的关键词Rabindranath是这个问题的键。所以需要计算查询和数据库的键(数据库中的所有作者)之间的相似度,然后返回最相似作者的值(书籍)。

同样,注意力有三个矩阵,分别是查询矩阵(Q)、键矩阵(K)和值矩阵(V)。它们中的每一个都具有与输入嵌入相同的维数。模型在训练中学习这些度量的值。

我们可以假设我们从每个单词中创建一个向量,这样我们就可以处理信息。对于每个单词,生成一个512维的向量。所有3个矩阵都是512x512(因为单词嵌入的维度是512)。对于每个标记嵌入,我们将其与所有三个矩阵(Q, K, V)相乘,每个标记将有3个长度为512的中间向量。

图解transformer中的自注意力机制

接下来计算分数,它是查询和键向量之间的点积。分数决定了当我们在某个位置编码单词时,对输入句子的其他部分的关注程度。

然后将点积除以关键向量维数的平方根。这种缩放是为了防止点积变得太大或太小(取决于正值或负值),因为这可能导致训练期间的数值不稳定。选择比例因子是为了确保点积的方差近似等于1。

然后通过softmax操作传递结果。这将分数标准化:它们都是正的,并且加起来等于1。softmax输出决定了我们应该从不同的单词中获取多少信息或特征(值),也就是在计算权重。

这里需要注意的一点是,为什么需要其他单词的信息/特征?因为我们的语言是有上下文含义的,一个相同的单词出现在不同的语境,含义也不一样。

最后一步就是计算softmax与这些值的乘积,并将它们相加。

可视化图解

上面逻辑都是文字内容,看起来有一些枯燥,下面我们可视化它的矢量化实现。这样可以更加深入的理解。

查询键和矩阵的计算方法如下

图解transformer中的自注意力机制

同样的方法可以计算键向量和值向量。

图解transformer中的自注意力机制

图解transformer中的自注意力机制

最后计算得分和注意力输出。

图解transformer中的自注意力机制

简单代码实现

 importtorch
 importtorch.nnasnn
 fromtypingimportList
 
 defget_input_embeddings(words: List[str], embeddings_dim: int):
     # we are creating random vector of embeddings_dim size for each words
     # normally we train a tokenizer to get the embeddings.
     # check the blog on tokenizer to learn about this part
     embeddings= [torch.randn(embeddings_dim) forwordinwords]
     returnembeddings
 
 
 text="I should sleep now"
 words=text.split(" ")
 len(words) # 4
 
 
 embeddings_dim=512# 512 dim because the original paper uses it. we can use other dim also
 embeddings=get_input_embeddings(words, embeddings_dim=embeddings_dim)
 embeddings[0].shape# torch.Size([512])
 
 
 # initialize the query, key and value metrices 
 query_matrix=nn.Linear(embeddings_dim, embeddings_dim)
 key_matrix=nn.Linear(embeddings_dim, embeddings_dim)
 value_matrix=nn.Linear(embeddings_dim, embeddings_dim)
 query_matrix.weight.shape, key_matrix.weight.shape, value_matrix.weight.shape# torch.Size([512, 512]), torch.Size([512, 512]), torch.Size([512, 512])
 
 
 # query, key and value vectors computation for each words embeddings
 query_vectors=torch.stack([query_matrix(embedding) forembeddinginembeddings])
 key_vectors=torch.stack([key_matrix(embedding) forembeddinginembeddings])
 value_vectors=torch.stack([value_matrix(embedding) forembeddinginembeddings])
 query_vectors.shape, key_vectors.shape, value_vectors.shape# torch.Size([4, 512]), torch.Size([4, 512]), torch.Size([4, 512])
 
 
 # compute the score
 scores=torch.matmul(query_vectors, key_vectors.transpose(-2, -1)) /torch.sqrt(torch.tensor(embeddings_dim, dtype=torch.float32))
 scores.shape# torch.Size([4, 4])
 
 
 # compute the attention weights for each of the words with the other words
 softmax=nn.Softmax(dim=-1)
 attention_weights=softmax(scores)
 attention_weights.shape# torch.Size([4, 4])
 
 
 # attention output
 output=torch.matmul(attention_weights, value_vectors)
 output.shape# torch.Size([4, 512])

以上代码只是为了展示注意力机制的实现,并未优化。

多头注意力

上面提到的注意力是单头注意力,在原论文中有8个头。对于多头和单多头注意力计算相同,只是查询(q0-q3),键(k0-k3),值(v0-v3)中间向量会有一些区别。

图解transformer中的自注意力机制

之后将查询向量分成相等的部分(有多少头就分成多少)。在上图中有8个头,查询,键和值向量的维度为512。所以就变为了8个64维的向量。

把前64个向量放到第一个头,第二组向量放到第二个头,以此类推。在上面的图片中,我只展示了第一个头的计算。

这里需要注意的是:不同的框架有不同的实现方法,pytorch官方的实现是上面这种,但是tf和一些第三方的代码中是将每个头分开计算了,比如8个头会使用8个linear(tf的dense)而不是一个大linear再拆解。还记得Pytorch的transformer里面要求emb_dim能被num_heads整除吗,就是因为这个

使用哪种方式都可以,因为最终的结果都类似影响不大。

当我们在一个head中有了小查询、键和值(64 dim的)之后,计算剩下的逻辑与单个head注意相同。最后得到的64维的向量来自每个头。

我们将每个头的64个输出组合起来,得到最后的512个dim输出向量。

图解transformer中的自注意力机制

多头注意力可以表示数据中的复杂关系。每个头都能学习不同的模式。多个头还提供了同时处理输入表示的不同子空间(本例:64个向量表示512个原始向量)的能力。

多头注意代码实现

 num_heads=8
 # batch dim is 1 since we are processing one text.
 batch_size=1
 
 text="I should sleep now"
 words=text.split(" ")
 len(words) # 4
 
 
 embeddings_dim=512
 embeddings=get_input_embeddings(words, embeddings_dim=embeddings_dim)
 embeddings[0].shape# torch.Size([512])
 
 
 # initialize the query, key and value metrices 
 query_matrix=nn.Linear(embeddings_dim, embeddings_dim)
 key_matrix=nn.Linear(embeddings_dim, embeddings_dim)
 value_matrix=nn.Linear(embeddings_dim, embeddings_dim)
 query_matrix.weight.shape, key_matrix.weight.shape, value_matrix.weight.shape# torch.Size([512, 512]), torch.Size([512, 512]), torch.Size([512, 512])
 
 
 # query, key and value vectors computation for each words embeddings
 query_vectors=torch.stack([query_matrix(embedding) forembeddinginembeddings])
 key_vectors=torch.stack([key_matrix(embedding) forembeddinginembeddings])
 value_vectors=torch.stack([value_matrix(embedding) forembeddinginembeddings])
 query_vectors.shape, key_vectors.shape, value_vectors.shape# torch.Size([4, 512]), torch.Size([4, 512]), torch.Size([4, 512])
 
 
 # (batch_size, num_heads, seq_len, embeddings_dim)
 query_vectors_view=query_vectors.view(batch_size, -1, num_heads, embeddings_dim//num_heads).transpose(1, 2) 
 key_vectors_view=key_vectors.view(batch_size, -1, num_heads, embeddings_dim//num_heads).transpose(1, 2) 
 value_vectors_view=value_vectors.view(batch_size, -1, num_heads, embeddings_dim//num_heads).transpose(1, 2) 
 query_vectors_view.shape, key_vectors_view.shape, value_vectors_view.shape
 # torch.Size([1, 8, 4, 64]),
 #  torch.Size([1, 8, 4, 64]),
 #  torch.Size([1, 8, 4, 64])
 
 
 # We are splitting the each vectors into 8 heads. 
 # Assuming we have one text (batch size of 1), So we split 
 # the embedding vectors also into 8 parts. Each head will 
 # take these parts. If we do this one head at a time.
 head1_query_vector=query_vectors_view[0, 0, ...]
 head1_key_vector=key_vectors_view[0, 0, ...]
 head1_value_vector=value_vectors_view[0, 0, ...]
 head1_query_vector.shape, head1_key_vector.shape, head1_value_vector.shape
 
 
 # The above vectors are of same size as before only the feature dim is changed from 512 to 64
 # compute the score
 scores_head1=torch.matmul(head1_query_vector, head1_key_vector.permute(1, 0)) /torch.sqrt(torch.tensor(embeddings_dim//num_heads, dtype=torch.float32))
 scores_head1.shape# torch.Size([4, 4])
 
 
 # compute the attention weights for each of the words with the other words
 softmax=nn.Softmax(dim=-1)
 attention_weights_head1=softmax(scores_head1)
 attention_weights_head1.shape# torch.Size([4, 4])
 
 output_head1=torch.matmul(attention_weights_head1, head1_value_vector)
 output_head1.shape# torch.Size([4, 512])
 
 
 # we can compute the output for all the heads
 outputs= []
 forhead_idxinrange(num_heads):
     head_idx_query_vector=query_vectors_view[0, head_idx, ...]
     head_idx_key_vector=key_vectors_view[0, head_idx, ...]
     head_idx_value_vector=value_vectors_view[0, head_idx, ...]
     scores_head_idx=torch.matmul(head_idx_query_vector, head_idx_key_vector.permute(1, 0)) /torch.sqrt(torch.tensor(embeddings_dim//num_heads, dtype=torch.float32))
 
     softmax=nn.Softmax(dim=-1)
     attention_weights_idx=softmax(scores_head_idx)
     output=torch.matmul(attention_weights_idx, head_idx_value_vector)
     outputs.append(output)
 
 [out.shapeforoutinoutputs]
 # [torch.Size([4, 64]),
 #  torch.Size([4, 64]),
 #  torch.Size([4, 64]),
 #  torch.Size([4, 64]),
 #  torch.Size([4, 64]),
 #  torch.Size([4, 64]),
 #  torch.Size([4, 64]),
 #  torch.Size([4, 64])]
 
 # stack the result from each heads for the corresponding words
 word0_outputs=torch.cat([out[0] foroutinoutputs])
 word0_outputs.shape
 
 # lets do it for all the words
 attn_outputs= []
 foriinrange(len(words)):
     attn_output=torch.cat([out[i] foroutinoutputs])
     attn_outputs.append(attn_output)
 [attn_output.shapeforattn_outputinattn_outputs] # [torch.Size([512]), torch.Size([512]), torch.Size([512]), torch.Size([512])]
 
 
 # Now lets do it in vectorize way. 
 # We can not permute the last two dimension of the key vector.
 key_vectors_view.permute(0, 1, 3, 2).shape# torch.Size([1, 8, 64, 4])
 
 
 # Transpose the key vector on the last dim
 score=torch.matmul(query_vectors_view, key_vectors_view.permute(0, 1, 3, 2)) # Q*k
 score=torch.softmax(score, dim=-1)
 
 
 # reshape the results 
 attention_results=torch.matmul(score, value_vectors_view)
 attention_results.shape# [1, 8, 4, 64]
 
 # merge the results
 attention_results=attention_results.permute(0, 2, 1, 3).contiguous().view(batch_size, -1, embeddings_dim)
 attention_results.shape# torch.Size([1, 4, 512])

总结

注意力机制(attention mechanism)是Transformer模型中的重要组成部分。Transformer是一种基于自注意力机制(self-attention)的神经网络模型,广泛应用于自然语言处理任务,如机器翻译、文本生成和语言模型等。本文介绍的自注意力机制是Transformer模型的基础,在此基础之上衍生发展出了各种不同的更加高效的注意力机制,所以深入了解自注意力机制,将能够更好地理解Transformer模型的设计原理和工作机制,以及如何在具体的各种任务中应用和调整模型。这将有助于你更有效地使用Transformer模型并进行相关研究和开发。

最后有兴趣的可以看看这个,它里面包含了pytorch的transformer的完整实现:

https://avoid.overfit.cn/post/c3f0da0fd4bd4151a8f79741ebc09937

作者:Souvik Mandal文章来源地址https://www.toymoban.com/news/detail-491914.html

到了这里,关于图解transformer中的自注意力机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Transformer系列(2)】注意力机制、自注意力机制、多头注意力机制、通道注意力机制、空间注意力机制超详细讲解

    注意力机制一直是一个比较热的话题,其实在很早之前就提出了,我们在学习图像分类时在SENet就见到过(直通车:经典神经网络论文超详细解读(七)——SENet(注意力机制)学习笔记(翻译+精读+代码复现))自从谷歌发表了《Attention Is All You Need》这篇论文后,注意力

    2024年02月06日
    浏览(63)
  • 注意力机制和Transformer

    机器翻译是NLP领域中最重要的问题之一,也是Google翻译等工具的基础。传统的RNN方法使用两个循环网络实现序列到序列的转换,其中一个网络(编码器)将输入序列转换为隐藏状态,而另一个网络(解码器)则将该隐藏状态解码为翻译结果。但是,这种方法存在两个问题:

    2024年02月09日
    浏览(46)
  • 简单理解Transformer注意力机制

    这篇文章是对《动手深度学习》注意力机制部分的简单理解。 生物学中的注意力 生物学上的注意力有两种,一种是无意识的,零一种是有意识的。如下图1,由于红色的杯子比较突出,因此注意力不由自主指向了它。如下图2,由于有意识的线索是想要读书,即使红色杯子比较

    2024年02月03日
    浏览(35)
  • 大模型基础之注意力机制和Transformer

    核心思想:在decoder的每一步,把encoder端所有的向量提供给decoder,这样decoder根据当前自身状态,来自动选择需要使用的向量和信息. decoder在每次生成时可以关注到encoder端所有位置的信息。 通过注意力地图可以发现decoder所关注的点。 注意力使网络可以对齐语义相关的词汇。

    2024年02月11日
    浏览(39)
  • 注意力机制——Spatial Transformer Networks(STN)

    Spatial Transformer Networks(STN)是一种空间注意力模型,可以通过学习对输入数据进行空间变换,从而增强网络的对图像变形、旋转等几何变换的鲁棒性。STN 可以在端到端的训练过程中自适应地学习变换参数,无需人为设置变换方式和参数。 STN 的基本结构包括三个部分:定位网

    2024年02月07日
    浏览(43)
  • 【】理解ChatGPT之注意力机制和Transformer入门

    作者:黑夜路人 时间:2023年4月27日 想要连贯学习本内容请阅读之前文章: 【原创】理解ChatGPT之GPT工作原理 【原创】理解ChatGPT之机器学习入门 【原创】AIGC之 ChatGPT 高级使用技巧 GPT是什么意思 GPT 的全称是 Generative Pre-trained Transformer(生成型预训练变换模型),它是基于大

    2024年02月16日
    浏览(44)
  • 【计算机视觉 | 注意力机制】13种即插即用涨点模块分享!含注意力机制、卷积变体、Transformer变体等

    用即插即用的模块“缝合”,加入自己的想法快速搭积木炼丹。 这种方法可以简化模型设计,减少冗余工作,帮助我们快速搭建模型结构,不需要从零开始实现所有组件。除此以外,这些即插即用的模块都具有标准接口,意味着我们可以很方便地替换不同的模块进行比较,加

    2024年02月04日
    浏览(46)
  • 【Transformer】自注意力机制Self-Attention

    \\\"Transformer\\\"是一种深度学习模型,首次在\\\"Attention is All You Need\\\"这篇论文中被提出,已经成为自然语言处理(NLP)领域的重要基石。这是因为Transformer模型有几个显著的优点: 自注意力机制(Self-Attention) :这是Transformer最核心的概念,也是其最大的特点。 通过自注意力机制,模

    2024年02月13日
    浏览(35)
  • Transformer(一)简述(注意力机制,NLP,CV通用模型)

    目录 1.Encoder 1.1简单理解Attention 1.2.什么是self-attention 1.3.怎么计算self-attention 1.4.multi-headed(q,k,v不区分大小写) 1.5.位置信息表达  2.Decoder(待补充)  3.BERT 参考文献 比方说,下图中的热度图中我们希望专注于小鸟,而不关注背景信息。那么如何关注文本和图像中的重点呢

    2024年02月13日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包