自然语言处理: 第五章Attention注意力机制

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

自然语言处理: 第五章Attention注意力机制

理论基础

Attention(来自2017年google发表的[1706.03762] Attention Is All You Need (arxiv.org) ),顾名思义是注意力机制,字面意思就是你所关注的东西,比如我们看到一个非常非常的故事的时候,但是其实我们一般能用5W2H就能很好的归纳这个故事,所以我们在复述或者归纳一段文字的时候,我们肯定有我们所关注的点,这些关注的点就是我们的注意力,而类似How 或者when 这种不同的形式就成为了Attention里的多头的机制。 下图是引自GPT3.5对注意力的一种直观的解释,简而言之其实就是各种不同(多头)我们关注的点(注意力)构成了注意力机制,这个奠定现代人工智能基石的基础。
自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能



那么注意力机制的优点是什么呢? (下面的对比是相对于上一节的Seq2Seq模型)

  1. 解决了长距离依赖问题,由于Seq2Seq模型一般是以时序模型eg RNN / Lstm / GRU 作为基础, 所以就会必然导致模型更倾向新的输入 – 多头注意力机制允许模型在解码阶段关注输入序列中的不同部分
  2. 信息损失:很难将所有信息压缩到一个固定长度的向量中(encorder 输出是一个定长的向量) – 注意力机制动态地选择输入序列的关键部分
  3. 复杂度和计算成本:顺序处理序列的每个时间步 – 全部网络都是以全连接层或者点积操作,没有时序模型
  4. 对齐问题:源序列和目标序列可能存在不对齐的情况 – 注意力机制能够为模型提供更精细的词汇级别对齐信


注意力可以拆解成下面6个部分,下面会在代码实现部分逐个解释

自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能


  1. 缩放点积注意力

两个向量相乘可以得到其相似度, 一般常用的是直接点积也比较简单,原论文里还提出里还提出了下面两种计算相似度分数的方式, 也可以参考下图。

自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能



其实相似度分数,直观理解就是两个向量点积可以得到相似度的分数,加权求和得到输出。自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能
自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能



然后就是对点积注意力的拆解首先我们要明确目标我们要求解的是X1关于X2的注意力输出,所以首先需要确定的是X1 和 X2 的特征维度以及batch_size肯定要相同,然后是seq长度可以不同。 然后我们计算原始注意力权重即X1(N , seq1 , embedding) · X2(N , seq2 , embedding) -> attention( N , seq1 , seq2) , 可以看到我们得到了X1中每个单词对X2中每个单词的注意力权重矩阵所以维度是(seq1 , seq2)。

当特征维度尺寸比较大时,注意力的值会变得非常大,从而导致后期计算softmax的时候梯度消失,所以这里会对注意力的值做一个缩小,也就是将点积的结果/scaler_factor, 这个scaler_factor一般是embedding_size 的开根号。

然后我们对X2的维度做一个softmax 得到归一化的注意力权重,至于为什么是X2,是因为我们计算的是X1关于X2的注意力,所以在下一步我会会让整个attention 权重与X2做点积也就是加权求和,这里需要把X2对应的权重做归一化所以要对X2的权重做归一化。

也就是X1 与 X2 之间相互每个单词的相似度(score) 因为我们求的是X1 关于X2的注意力,所以最后我们将归一化后的权重与X2做一个加权求和(点积)即Attention_scaled(N , seq1 , seq2) · X2(N , seq2 , embedding) -> X1_attention_X2( N , seq1 , embedding) 这个时候我们可以看到最后的输出与X1的维度相同,但是里面的信息已经是整合了X2的信息的的X1’。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2cDP4HFU-1689687821802)(image/06_attention/1689604378729.png)]



  1. 编解码注意力
    这个仅存在Seq2Seq的架构中,也就是将编码器的最后输出与解码器的隐藏状态相互结合,下图进行了解释可以看到encoder将输入的上下文进行编码后整合成一个context 向量,由于我们最后的输出是decoder 所以这里X1 是解码器的隐层状态,X2 是编码器的隐层状态。

    自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能



4. QKV

下面介绍的就是注意力中一个经常被弄混的概念,QKV, 根据前面的只是其实query 就是X1也就是我们需要查询的目标, Key 和 Value 也就是X2,只是X2不同的表现形式,K 可以等于 V 也可以不等,上面的做法都是相等的。

自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能

  1. 自注意力

    最后就是注意力机制最核心的内容,也就是自注意力机制,那么为什么多了一个自呢?其实就是X1 = X2 ,换句话说就是自己对自己做了一个升华,文本对自己的内容做了一个类似summary的机制,得到了精华。就如同下图一样,自注意力的QKV 都来自同一个输入X向量,最后得到的X’, 它是自己整合了自己全部信息向量,它读完了自己全部的内容,并不只是单独的一个字或者一段话,而是去其糟粕后的X。

自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能

而多头自注意力也就是同样的X切分好几个QKV, 可以捕捉不同的重点(类似一个qkv捕捉when , 一个qkv捕捉how),所以多头是有助于网络的表达,然后这里需要注意的是多头是将embedding - > (n_head , embedding // n_head ) , 不是(n_head , embedding)。

所以多头中得到的注意力权重的shape也会变成(N , n_head , seq , seq ) 这里由于是自注意力 所以seq1 = seq2 = seq 。

自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能



代码实现

这里只介绍了核心代码实现, 下面是多头注意力的实现:

import torch.nn as nn # 导入torch.nn库
# 创建一个Attention类,用于计算注意力权重
class Mult_attention(nn.Module):
    def __init__(self, n_head):
        super(Mult_attention, self).__init__()
        self.n_head = n_head

    def forward(self, decoder_context, encoder_context , dec_enc_attn_mask): # decoder_context : x1(q) , encoder_context : x2(k , v)
        # print(decoder_context.shape, encoder_context.shape) # X1(N , seq_1 , embedding) , X2(N , seq_2 , embedding)
        # 进行切分 , (N , seq_len_X , emb_dim) -> (N , num_head , seq_len_X , head_dim) / head_dim * num_head  = emb_dim
        Q = self.split_heads(decoder_context)  # X1
        K = self.split_heads(encoder_context)  # X2
        V = self.split_heads(encoder_context)  # X2
        # print(Q.shape , 0)

        # 将注意力掩码复制到多头 attn_mask: [batch_size, n_heads, len_q, len_k]
        attn_mask = dec_enc_attn_mask.unsqueeze(1).repeat(1, self.n_head, 1, 1)

        # 计算decoder_context和encoder_context的点积,得到多头注意力分数,其实就是在原有的基础上多加一个尺度
        scores = torch.matmul(Q, K.transpose(-2, -1)) # -> (N , num_head , seq_len_1 , seq_len_2)
        scores.masked_fill_(attn_mask , -1e9)
        # print(scores.shape ,1 )

        # 自注意力原始权重进行缩放
        scale_factor = K.size(-1) ** 0.5
        scaled_weights = scores / scale_factor # -> (N , num_head , seq_len_1 , seq_len_2)
        # print(scaled_weights.shape , 2)

        # 归一化分数
        attn_weights = nn.functional.softmax(scaled_weights, dim=-1) # -> (N , num_head , seq_len_1 , seq_len_2)
        # print(attn_weights.shape , 3)

        # 将注意力权重乘以encoder_context,得到加权的上下文向量
        attn_outputs = torch.matmul(attn_weights, V) # -> (N , num_head , seq_len_1 , embedding // num_head)
        # print(attn_outputs.shape , 4) 

        # 将多头合并下(output  & attention)
        attn_outputs  = self.combine_heads(attn_outputs) # 与Q的尺度是一样的
        attn_weights = self.combine_heads(attn_weights)
        # print(attn_weights.shape , attn_outputs.shape , 5) #
        return attn_outputs, attn_weights
  
    # 将所有头的结果拼接起来,就是把n_head 这个维度去掉,
    def combine_heads(self , tensor):
        # print(tensor.size())
        batch_size, num_heads, seq_len, head_dim = tensor.size()
        feature_dim = num_heads * head_dim
        return tensor.transpose(1, 2).contiguous().view(batch_size, seq_len, feature_dim)


    def split_heads(self , tensor):
        batch_size, seq_len, feature_dim = tensor.size()
        head_dim = feature_dim // self.n_head
        # print(tensor.shape, head_dim , self.n_head)
        return tensor.view(batch_size, seq_len, self.n_head, head_dim).transpose(1, 2)


多头注意力的解码器,这里添加了mask机制。

class DecoderWithMutliHeadAttention(nn.Module):
    def __init__(self, hidden_size, output_size , n_head):
        super(DecoderWithMutliHeadAttention, self).__init__()
        self.hidden_size = hidden_size # 设置隐藏层大小
        self.n_head = n_head # 多头
        self.embedding = nn.Embedding(output_size, hidden_size) # 创建词嵌入层
        self.rnn = nn.RNN(hidden_size, hidden_size, batch_first=True) # 创建RNN层
        self.multi_attention = Mult_attention(n_head = n_head)
        self.out = nn.Linear(2 * hidden_size, output_size)  # 修改线性输出层,考虑隐藏状态和上下文向量


    def forward(self, inputs, hidden, encoder_outputs , encoder_input):
        embedded = self.embedding(inputs)  # 将输入转换为嵌入向量
        rnn_output, hidden = self.rnn(embedded, hidden)  # 将嵌入向量输入RNN层并获取输出 
        dec_enc_attn_mask = self.get_attn_pad_mask(inputs, encoder_input) # 解码器-编码器掩码
        context, attn_weights = self.multi_attention(rnn_output, encoder_outputs , dec_enc_attn_mask)  # 计算注意力上下文向量
        output = torch.cat((rnn_output, context), dim=-1)  # 将上下文向量与解码器的输出拼接
        output = self.out(output)  # 使用线性层生成最终输出
        return output, hidden, attn_weights
  
    def get_attn_pad_mask(self , seq_q, seq_k):
        #-------------------------维度信息--------------------------------
        # seq_q 的维度是 [batch_size, len_q]
        # seq_k 的维度是 [batch_size, len_k]
        #-----------------------------------------------------------------
        # print(seq_q.size(), seq_k.size())
        batch_size, len_q = seq_q.size()
        batch_size, len_k = seq_k.size()
        # 生成布尔类型张量[batch_size,1,len_k(=len_q)]
        pad_attn_mask = seq_k.data.eq(0).unsqueeze(1)  #<PAD> Token的编码值为0 
        # 变形为何注意力分数相同形状的张量 [batch_size,len_q,len_k]
        pad_attn_mask = pad_attn_mask.expand(batch_size, len_q, len_k)
        #-------------------------维度信息--------------------------------
        # pad_attn_mask 的维度是 [batch_size,len_q,len_k]
        #-----------------------------------------------------------------
        return pad_attn_mask # [batch_size,len_q,len_k]


结果

整体实验结果如下,可能是因为整体语料库太小了,所以翻译结果不是太好,但是多头注意力机制还是都跑通了:

自然语言处理: 第五章Attention注意力机制,自然语言处理,自然语言处理,人工智能文章来源地址https://www.toymoban.com/news/detail-580641.html

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

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

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

相关文章

  • Coursera自然语言处理专项课程04:Natural Language Processing with Attention Models笔记 Week03(完结)

    Introduction https://www.coursera.org/specializations/natural-language-processing Certificate Course Certificate 本文是学习这门课 Natural Language Processing with Attention Models的学习笔记,如有侵权,请联系删除。 Explore transfer learning with state-of-the-art models like T5 and BERT, then build a model that can answer questions. Le

    2024年04月13日
    浏览(124)
  • 【AI视野·今日NLP 自然语言处理论文速览 第五十三期】Thu, 12 Oct 2023

    AI视野 ·今日CS.NLP 自然语言处理论文速览 Thu, 12 Oct 2023 Totally 69 papers 👉 上期速览 ✈更多精彩请移步主页 To Build Our Future, We Must Know Our Past: Contextualizing Paradigm Shifts in Natural Language Processing Authors Sireesh Gururaja, Amanda Bertsch, Clara Na, David Gray Widder, Emma Strubell NLP 正处于一个颠覆性变

    2024年02月07日
    浏览(43)
  • 【AI视野·今日NLP 自然语言处理论文速览 第五十四期】Fri, 13 Oct 2023

    AI视野 ·今日CS.NLP 自然语言处理论文速览 Fri, 13 Oct 2023 Totally 75 papers 👉 上期速览 ✈更多精彩请移步主页 Tree-Planner: Efficient Close-loop Task Planning with Large Language Models Authors Mengkang Hu, Yao Mu, Xinmiao Yu, Mingyu Ding, Shiguang Wu, Wenqi Shao, Qiguang Chen, Bin Wang, Yu Qiao, Ping Luo 本文研究闭环任务规

    2024年02月07日
    浏览(46)
  • 基于Bert+Attention+LSTM智能校园知识图谱问答推荐系统——NLP自然语言处理算法应用(含Python全部工程源码及训练模型)+数据集

    这个项目充分利用了Google的Bert模型,这是一种基于Attention的大规模语料预训练模型,以及LSTM命名实体识别网络。项目的目标是设计一套通用的问答系统处理逻辑,以实现智能问答任务。 首先,我们采用了Bert模型,这是一种在自然语言处理领域非常强大的预训练模型。它具备

    2024年02月09日
    浏览(67)
  • 机器学习&&深度学习——NLP实战(自然语言推断——注意力机制实现)

    👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习深度学习——NLP实战(自然语言推断——数据集) 📚订阅专栏:机器学习深度学习 希望文章对你们有所帮助 在之前已经介绍了什么是自然语言推断,并且下载并处理了SNLI数据集。由于许

    2024年02月11日
    浏览(39)
  • 【自然语言处理】自然语言处理 --- NLP入门指南

    NLP的全称是 Natuarl Language Processing ,中文意思是自然语言处理,是人工智能领域的一个重要方向 自然语言处理(NLP)的一个最伟大的方面是跨越多个领域的计算研究,从人工智能到计算语言学的多个计算研究领域都在研究计算机与人类语言之间的相互作用。它主要关注计算机

    2024年02月03日
    浏览(65)
  • [自然语言处理] 自然语言处理库spaCy使用指北

    spaCy是一个基于Python编写的开源自然语言处理库。基于自然处理领域的最新研究,spaCy提供了一系列高效且易用的工具,用于文本预处理、文本解析、命名实体识别、词性标注、句法分析和文本分类等任务。 spaCy的官方仓库地址为:spaCy-github。本文主要参考其官方网站的文档,

    2024年02月15日
    浏览(100)
  • 自然语言处理从入门到应用——自然语言处理的常见任务

    分类目录:《自然语言处理从入门到应用》总目录 语言模型(Language Model,LM)(也称统计语言模型)是描述自然语言概率分布的模型,是一个非常基础和重要的自然语言处理任务。利用语言模型,可以计算一个词序列或一句话的概率,也可以在给定上文的条件下对接下来可

    2024年02月07日
    浏览(66)
  • 【数据挖掘与人工智能自然语言处理】自然语言处理和人工智能:如何利用自然语言处理技术进行数据挖掘

    作者:禅与计算机程序设计艺术 随着互联网和大数据时代的到来,数据挖掘已成为各个行业的热门话题。数据挖掘的核心在于发现数据中的有价值信息,而自然语言处理(NLP)技术是实现这一目标的重要手段。本文旨在通过自然语言处理技术进行数据挖掘,为数据挖掘提供一

    2024年02月05日
    浏览(102)
  • 以ChatGPT为例进行自然语言处理学习——入门自然语言处理

    ⭐️我叫忆_恒心,一名喜欢书写博客的在读研究生👨‍🎓。 如果觉得本文能帮到您, 麻烦点个赞 👍呗! 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧,喜欢的小伙伴给个三连支持一下呗。👍⭐️❤️ Qt5.9专栏 定期更新Qt的一些项目Demo

    2023年04月23日
    浏览(83)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包