06_注意力机制

发布于:2025-06-30 ⋅ 阅读:(18) ⋅ 点赞:(0)

注意力机制笔记

一、课程内容


  • 1-注意力机制介绍

  • 2-注意力机制的实现方法

  • 3-注意力机制的优缺点


二、为什么提出注意力机制

引入Attention的原因1: 1、在 Attention 机制引入之前,有一个问题大家一直很苦恼:长距离的信息会被弱化,就好像记忆能力弱的人,记不住过去的事情是一样的。
引入Attention的原因2: 参数少、速度快、效果好
最初场景问题: 文本翻译问题
    问题1: 如果翻译的句子很长很复杂,比如直接一篇文章输进去,模型的计算量很大,并且模型的准确率下降严重
    问题2: 没有考虑词与词之间的相关性,导致翻译效果比较差


三、什么是注意力机制

3.1 实用例子解释Attention:

 通俗理解注意力机制原理与本质:Q(query)、K(key)、V(value)
  - 第一步【查询】:打开京东网站,我们输入查询(query,Q),比如“笔记本”
  - 第二步【计算相似性】:京东后台拿到这个查询Q,会用这个查询Q去和后台的所有商品的关键字(或者title)(key, K)一一来对比,找到物品和我们查询的相似性(或者说物品对应的相似性的权重),相似性越高,越可能推送给我们
  - 第三步【得到价值】:这个时候我们还需要考虑物品的价值(value, V),这个V不是指物品值几块钱,而是这个物品在算法中的价值。如果商家给了京东广告费,或者商品物美价廉,评论好,点赞高等,那么算法就越有可能把物品排在前面推送给我们
  - 第四步【计算带权重的价值】:我们拿刚刚得到的相似性,乘以物品在算法中的价值V,计算结果就是每件物品的最后带有相似性权重的价值,京东最后的算法就是返回这个带权重的价值,也就是把排序好的商品推送给我们
  - **【总结】**:这是个典型的注意力过程,它推送在最前面给我们展示的商品,肯定是它最希望获得我们注意力的商品。当然,京东内部的算法肯定不是这样的,但是他们本质原理一样,都是基于注意力,并且我们看到的现象也是一样的。 

3.2 Attention概念

“注意力机制”实际上就是想将人的感知方式、注意力的行为应用在机器上,让机器学会去感知数据中的重要和不重要的部分。

3.3 注意力机制分类:

1、软注意力: 注意力权重值分布在0-1之间,关注所有的词汇,但是不同词汇根据权重大小关注的程度不一样。
2、硬注意力: 注意力权重值是0或者1,只关注哪些重要的部分,忽略次要的部分
3、自注意力: 通过输入项内部的"表决"来决定应该关注哪些输入项.

3.4 注意力计算步骤(常见三步走战略)

Attention计算构成元素:

query(Q)、key(K)、value(V)

(计算过程的普遍性表达):

第一步: query和key进行相似度计算,得到attention_score
第二步: 对attention_score进行softmax归一化得到权重值,压缩数值到0-1之间
第三步: 对上一步的权重值和value进行融合,得到具有权重信息的新value


基本步骤
第一步: 根据注意力计算规则, 对Q,K,V进行相应的计算.
第二步: 根据第一步采用的计算方法, 如果是拼接方法,则需要将Q与第一步的计算结果再进行拼接, 如果是转置点积, 一般是自注意力, Q与V相同, 则不需要进行与Q的拼接.
第三步: 最后为了使整个attention机制按照指定尺寸输出, 使用线性层作用在第二步的结果上做一个线性变换, 得到最终对Q的注意力表示.

四、注意力计算规则

计算规则前提:

必须有指定的数据: Q、K、V;当输入的Q=K=V时(或者Q\K\V来自于同一个X), 称作自注意力计算规则;当Q、K、V不相等时称为一般注意力计算规则

三种规则方法:

第一种方法: 将Q和K进行纵轴拼接,然后经过线性变换,再经过Softmax进行处理得到权重,最后和V进行相乘

第二种方法: 将Q和K进行纵轴拼接,接着经过一次线性变化,然后进过tanh激活函数处理,再进行sum求和,再经过softmax进行处理得到权重,最后和V进行张量的乘法

第三种方法: 将Q和K的转置进行点乘,然后除以一个缩放系数,再经过softmax进行处理得到权重,最后和V进行张量的乘法


五、注意力机制的作用

概念:

在解码器端的注意力机制: 能够根据模型目标有效的聚焦编码器的输出结果, 当其作为解码器的输入时提升效果. 改善以往编码器输出是单一定长张量, 无法存储过多信息的情况.
在编码器端的注意力机制: 主要解决表征问题, 相当于特征提取过程, 得到输入的注意力表示. 一般使用自注意力(self-attention).

注意力机制实现步骤(深度学习中):

第一步: 按照注意力规则,对Q、K、V进行注意力的计算
第二步: 如果第一步是拼接操作,需要将Q和第一步计算的结果进行再次拼接,如果是点乘运算,Q和K、V相等,一般属于自注意力,不需要拼接
第三步: 我们需要将第二步的结果,进行线性变化,按照指定输出维度进行结果的表示

代码实现:

class MyAtt(nn.Module):
    #                   32          32          32              64      32
    def __init__(self, query_size, key_size, value_size1, value_size2, output_size):
        super(MyAtt, self).__init__()
        self.query_size = query_size
        self.key_size = key_size
        self.value_size1 = value_size1
        self.value_size2 = value_size2
        self.output_size = output_size
​
        # 线性层1 注意力权重分布
        self.attn = nn.Linear(self.query_size + self.key_size, self.value_size1)
​
        # 线性层2 注意力结果表示按照指定维度输出层 self.attn_combine
        self.attn_combine = nn.Linear(self.query_size+self.value_size2, output_size)
​
    def forward(self, Q, K, V):
        # 1 求查询张量q的注意力权重分布, attn_weights[1,32]
        # [1,1,32],[1,1,32]--> [1,32],[1,32]->[1,64]
        # [1,64] --> [1,32]
        # tmp1 = torch.cat( (Q[0], K[0]), dim=1)
        # tmp2 = self.attn(tmp1)
        # tmp3 = F.softmax(tmp2, dim=1)
        attn_weights = F.softmax( self.attn(torch.cat( (Q[0], K[0]), dim=-1)), dim=-1)
​
        # 2 求查询张量q的结果表示 bmm运算, attn_applied[1,1,64]
        # [1,1,32] * [1,32,64] ---> [1,1,64]
        attn_applied =  torch.bmm(attn_weights.unsqueeze(0), V)
​
        # 3 q 与 attn_applied 融合,再按照指定维度输出 output[1,1,64]
        # 3-1 q与结果表示拼接 [1,32],[1,64] ---> [1,96]
        output = torch.cat((Q[0], attn_applied[0]), dim=-1)
        # 3-2 shape [1,96] ---> [1,32]
        output = self.attn_combine(output).unsqueeze(0)
​
        # 4 返回注意力结果表示output:[1,1,32], 注意力权重分布attn_weights:[1,32]
        return output, attn_weights