文章目录

  • 7-2 自注意力机制 原理
  • 1. 简介
  • 2. NLP中自注意力
  • 3. 图像中的自注意力+代码
  • 4. 问题


7-2 自注意力机制 原理

上一章已经讲过什么是注意力,注意力有哪几种???
接下来,讲一下什么叫做自注意力机制??

李宏毅视频讲解:https://www.bilibili.com/video/BV1v3411r78R

PPT:https://speech.ee.ntu.edu.tw/~hylee/ml/ml2021-course-data/self_v7.pdf

自注意力机制实际上是注意力机制中的一种,

自注意力机制实际上也是一种网络的构型,它想要解决的问题是网络接收的输入是很多向量,并且向量的大小也是不确定的情况,比如机器翻译(序列到序列的问题,机器自己决定多少个标签),词性标注(Pos tagging一个向量对应一个标签),语义分析(多个向量对应一个标签)等文字处理问题。

1. 简介

Query,Key,Value的概念取自于信息检索系统,举个简单的搜索的例子来说。

当你在某电商平台搜索某件商品(年轻女士冬季穿的红色薄款羽绒服)时,

  • 你在搜索引擎上输入的内容便是Query
  • 然后搜索引擎根据Query为你匹配Key(例如商品的种类,颜色,描述等),
  • 然后根据Query和Key的相似度得到匹配的内容(Value)

self-attention中的Q,K,V也是起着类似的作用,在矩阵计算中,点积是计算两个矩阵相似度的方法之一,因此式1中使用了QKT进行相似度的计算。接着便是根据相似度进行输出的匹配,这里使用了加权匹配的方式,而权值就是query与key的相似度。

2. NLP中自注意力

自注意力计算公式
7-2 自注意力机制 原理_自然语言处理

现在我们有一组一维的向量,那么向量b是如何产生的呢?

7-2 自注意力机制 原理_自然语言处理_02

步骤1: 对于每个向量7-2 自注意力机制 原理_深度学习_03,分别乘上三个系数7-2 自注意力机制 原理_深度学习_04,得到7-2 自注意力机制 原理_深度学习_05三个值

7-2 自注意力机制 原理_transformer_06写成向量形式7-2 自注意力机制 原理_算法_07

7-2 自注意力机制 原理_自然语言处理_08写成向量形式7-2 自注意力机制 原理_算法_09

7-2 自注意力机制 原理_算法_10写成向量形式7-2 自注意力机制 原理_自然语言处理_11

得到的Q,K,V分别表示query,key和value。这3个w的参数就是我们需要学习的参数

7-2 自注意力机制 原理_自注意力机制_12


步骤2

利用得到的7-2 自注意力机制 原理_自注意力机制_137-2 自注意力机制 原理_深度学习_14计算每两个输入向量之间的相关性,也就是计算attention的值7-2 自注意力机制 原理_自然语言处理_157-2 自注意力机制 原理_自然语言处理_15的计算方法有多种,通常采用点乘的方式。

7-2 自注意力机制 原理_自然语言处理_17写成向量形式:7-2 自注意力机制 原理_自注意力机制_18

7-2 自注意力机制 原理_自注意力机制_19

矩阵A中的每一个值记录了对应的两个输入向量的Attention的大小7-2 自注意力机制 原理_自然语言处理_15

7-2 自注意力机制 原理_自注意力机制_21代表7-2 自注意力机制 原理_自注意力机制_22个查询向量(样本特征)与7-2 自注意力机制 原理_自注意力机制_22个键向量(信息特征)之间的相似度。

如果7-2 自注意力机制 原理_深度学习_24的第一行为7-2 自注意力机制 原理_transformer_25,则代表第一个样本与第一、二、三条信息之间的相似度2,5,3


步骤3

对A矩阵进行softmax操作或者relu操作得到A’。通常为7-2 自注意力机制 原理_自注意力机制_26

7-2 自注意力机制 原理_算法_27就是各个样本与各条信息间相关或相似程度的分布

对于上一段提到的例子,我们简单地令7-2 自注意力机制 原理_transformer_28,得到7-2 自注意力机制 原理_深度学习_29。这代表第一个样本与第一、二、三条信息的相关或相似度分别为20%、50%和30%。

步骤4:利用得到的7-2 自注意力机制 原理_自然语言处理_307-2 自注意力机制 原理_自然语言处理_31计算每个输入向量a对应的self-attention层的输出向量b:

7-2 自注意力机制 原理_自注意力机制_32,写成向量形式7-2 自注意力机制 原理_transformer_33

7-2 自注意力机制 原理_transformer_34

7-2 自注意力机制 原理_深度学习_35值向量(信息)的加权和,权值为各个样本与各条信息间相关或相似程度的分布,这就是自注意力的最终结果。

拿第一个向量a1对应的self-attention输出向量b1举例,它的产生过程如下:

7-2 自注意力机制 原理_自注意力机制_36

3. 图像中的自注意力+代码

7-2 自注意力机制 原理_深度学习_37

7-2 自注意力机制 原理_自然语言处理_38

代码来自SAGAN这篇论文:

论文代码: https://arxiv.org/abs/1805.08318

代码链接: https://github.com/heykeetae/Self-Attention-GAN

自注意力代码如下

import numpy as np
import torch
from einops import rearrange
from torch import nn


class Self_Attn(nn.Module):
    """ Self attention Layer"""

    def __init__(self, in_dim, activation=None):
        super(Self_Attn, self).__init__()
        # self.chanel_in = in_dim
        # self.activation = activation

        self.query_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1)
        self.key_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1)
        self.value_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim, kernel_size=1)
        self.gamma = nn.Parameter(torch.zeros(1))

        self.softmax = nn.Softmax(dim=-1)  #

    def forward(self, x):
        """
            inputs :
                x : input feature maps( B X C X W X H)
            returns :
                out : self attention value + input feature
                attention: B X N X N (N is Width*Height)
        """
        # batch,通道数,宽,高
        m_batchsize, C, width, height = x.size()  # [1, 16, 32, 32]

        # 步骤1, 通过conv 得出q,k
        q = self.query_conv(x).view(m_batchsize, -1, width * height).permute(0, 2,
                                                                             1)  # B X CX(N) torch.Size([1, 1024, 2])
        k = self.key_conv(x).view(m_batchsize, -1, width * height)  # B X C x (*W*H) torch.Size([1, 2, 1024])
        # 步骤1, 计算得出v
        v = self.value_conv(x).view(m_batchsize, -1, width * height)  # B X C X N  torch.Size([1, 16, 1024])

        # 步骤2,  矩阵的乘法 ,q,k进行相乘,得出特征图
        # [batch_size,1024,2]*[batch_size,2,1024]
        energy = torch.bmm(q, k)  # transpose check [1, 1024, 1024]
        # 特征图attention map,通过softmax
        attention = self.softmax(energy)  # BX (N) X (N)  torch.Size([1, 1024, 1024])

        # 步骤3,v * 特征图= 注意力
        # [1,16,1024]  *  [1,1024,1024]= torch.Size([1, 16, 1024])
        out = torch.bmm(v, attention.permute(0, 2, 1))  # torch.Size([1, 16, 1024])

        # 重新resize
        out = out.view(m_batchsize, C, width, height)  # torch.Size([1, 16, 32, 32])

        # 加上残差
        out = self.gamma * out + x
        return out, attention


if __name__ == '__main__':
    # 这个通道数需要 是8的倍数。因为 q,k,v 是使用conv算出的。 输出通道需要大于 8
    x = torch.randn(size=(1, 16, 32, 32))
    model = Self_Attn(16)
    out, attention = model(x)
    print(out.shape)
    print(attention.shape)

4. 问题

自注意力机制虽然考虑了所有的输入向量,但没有考虑到向量的位置信息。在实际的文字处理问题中,可能在不同位置词语具有不同的性质,比如动词往往较低频率出现在句首。

有学者提出可以通过位置编码(Positional Encoding)来解决这个问题:对每一个输入向量加上一个位置向量e,位置向量的生成方式有多种,通过e来表示位置信息带入self-attention层进行计算。

[2003.09229] Learning to Encode Position for Transformer with Continuous Dynamical Model (arxiv.org)

参考资料

注意力机制 & 自注意力模型 - 知乎 (zhihu.com)

https://zhuanlan.zhihu.com/p/48508221

(1条消息) 机器学习中的自注意力(Self Attention)机制详解_I am zzxn的博客