Attention 和 Transformer

news2025/1/11 6:59:50

本文参考d2l,搭配知识点和代码,助力一口气搞懂Transformer,参考:

  • chapter_attention-mechanisms-and-transformers https://d2l.ai/chapter_attention-mechanisms-and-transformers/index.html

目录如下:

  • x.1 Queries, Keys, and Values
  • x.2 Attention Pooling by Similarity通过相似度进行注意力汇聚
  • x.3 Attention Scoring Functions注意力评分函数
  • x.4 The Bahdanau Attention Mechanism ,即RNN + Attention, (略)
  • x.5 Multi-Head Attention 多头注意力(重点)
  • x.6 Self-Attention and Positional Encoding 自注意力 + 位置编码
  • x.7 The Transformer Architecture (Transformer的架构)(重点)
  • x.8 ViT (重点)
  • x.9 多尺度Transformer预训练模型

x.1 Queries, Keys, and Values

我们使用Queries和Keys来生成注意力权重,将权重值乘以我们现有的所有特征Values,来生成对单个特征Value的注意程度,将所有特征的注意程度加和得到了最终的该样本的attention pooling注意力汇聚分数。可以通过下式表达,

请添加图片描述

这样就形成了我们最简单的一个注意力,但作为一个概率模型(非负且加和为1),我们还需要进行下面的操作。其中(11.1.2)保证加权为1,操作(11.1.3)保证非负。

请添加图片描述

请添加图片描述

现代注意力的计算公式如下,并产生了最终的attention pooling注意力汇聚的值。

请添加图片描述

由于Q和K生成attention weight注意力权重可以用一个三维的图表达,所以我们这里可视化attention weight可以参考heatmap热力图,如下图表示的意思是:用颜色的深浅表示attention weight的大小,当且仅当key==value时,attention weight最大。也可以叫attention weight map注意力权重图.

如一个value_1对应的query_1为(2,1,3),key_1为(2,1,3)时,这个value_1的注意力权重 α ( q u e r y , v a l u e ) \alpha(query, value) α(query,value)很大,为一个小于1的很大的值。value_1的向量也占很大比重。

请添加图片描述

x.2 Attention Pooling by Similarity通过相似度进行注意力汇聚

即讨论 α ( q , k ) \alpha(q, k) α(q,k)中的 α \alpha α,常见的有很多,如下:

请添加图片描述

对应的注意力权重图。

请添加图片描述

x.3 Attention Scoring Functions注意力评分函数

上面中的Gaussian使用的是距离公式,但是距离公式的开销往往大于内积开销,所以我们接下来将使用点积表示注意力机制。

其中 α \alpha α就是所谓的attention scoring functions注意力评分函数。

现代attention计算如下,我们只用一个Query和多个Key-Value pairs来生成最终的ouput。

请添加图片描述

请添加图片描述

||q||一范数是确定的,由于LayerNorm的存在||K||是个确定的常数,所以只有Q点乘K的是不确定。所以我们最终计算公式如下:

请添加图片描述

我们简化Q和K的二范数得到了点积注意力机制。用点积来表示注意力权重大大减小了乘方带来的计算开销。

x.3.2 mask

由于人在说一句话的时候,句子长度往往是不确定的,如下所示:

请添加图片描述

但是为了高效并行计算时,最好保证句子的长度相同,基于这种需求,我们引入了Mask操作,以保证NLP中的Sequence保持相同的长度。我们通过将注意力权重值在softmax前(即QK内积后)置为一个无穷小来实现,例如10的负六次方。这样是为了方便GPU并行计算快(if-else开销更大)。

x.3.3 Batch Matrix Multiplication 多样本计算

但是在并行计算中,我们往往是选取多个batch进行计算注意力(即多个sample样本),这个时候引入bmm进行batch个矩阵间内积操作:

Q = torch.ones((2, 3, 4))
K = torch.ones((2, 4, 6))
print(torch.bmm(Q, K).shape) # (2, 3, 6))

在这里插入图片描述

x.3.4 Scaled Dot-Product Attention

注意力权重的计算公式如下:

请添加图片描述

我们注意到注意到点积 QK 的结果的尺度随着 d 的增加而增加。为了抵消这种尺度变化,我们将点积除以 根号d 。这样做的目的是使点积的平均值保持在一个相对稳定的范围内,不受向量维度 d 的影响。这种缩放操作有助于使得注意力分数的大小保持在一个合适的范围,并更好地进行梯度传播。

至此,我们得到了点积注意力机制的计算公式,可以看到是一个很简单的Query和Key的BMM操作,做softmax后dropout后,再和Value做BMM的操作。如下:

class DotProductAttention(nn.Module):
    """Scaled dot product attention.

    Defined in :numref:`subsec_additive-attention`"""
    def __init__(self, dropout, **kwargs):
        super(DotProductAttention, self).__init__(**kwargs)
        self.dropout = nn.Dropout(dropout)

    # Shape of `queries`: (`batch_size`, no. of queries, `d`)
    # Shape of `keys`: (`batch_size`, no. of key-value pairs, `d`)
    # Shape of `values`: (`batch_size`, no. of key-value pairs, value
    # dimension)
    # Shape of `valid_lens`: (`batch_size`,) or (`batch_size`, no. of queries)
    def forward(self, queries, keys, values, valid_lens=None):
        d = queries.shape[-1]
        # Set `transpose_b=True` to swap the last two dimensions of `keys`
        scores = torch.bmm(queries, keys.transpose(1,2)) / math.sqrt(d)
        self.attention_weights = masked_softmax(scores, valid_lens)
        return torch.bmm(self.dropout(self.attention_weights), values)

x.4 The Bahdanau Attention Mechanism ,即RNN + Attention, (略)

x.5 Multi-Head Attention 多头注意力(重点)

x.5.1 整体流程

说说是说,先将Q, K, V分裂成多头,对单头进行可学习参数调整后,再计算Attention。但实际代码实现过程中,先使用Linear层进行可学习参数调整,再使用transpose_qkv分裂成多头,但只不过是3个三维矩阵query,key,value。进行mask,再将这3个三维矩阵进行点积注意力机制计算。

计算完attention后,再通过transpose_output(即多头逆操作)将维度concat。concat后再经过一个可学习参数Linear层产生最终的输出。

我们能够注意到:

  • 所有的可学习参数 W q , W k , W v , W o W_q, W_k, W_v, W_o Wq,Wk,Wv,Wo都是在原大小(即非分裂头)上进行学习的,且都是由线性层组成。
  • num_hiddens == Query dimension
        # Shape of queries, keys, or values:
        # (batch_size, no. of queries or key-value pairs, num_hiddens)
        # Shape of valid_lens: (batch_size,) or (batch_size, no. of queries)
        
        # After transposing, shape of output queries, keys, or values:
        # (batch_size * num_heads, no. of queries or key-value pairs, num_hiddens / num_heads)
        queries = self.transpose_qkv(self.W_q(queries))
        keys = self.transpose_qkv(self.W_k(keys))
        values = self.transpose_qkv(self.W_v(values))
        
        # generate the mask of each Q, K, V
        if valid_lens is not None:
            # On axis 0, copy the first item (scalar or vector) for num_heads
            # times, then copy the next item, and so on
            valid_lens = torch.repeat_interleave(
                valid_lens, repeats=self.num_heads, dim=0)
        
        # Shape of output: (batch_size * num_heads, no. of queries, num_hiddens / num_heads)
        output = self.attention(queries, keys, values, valid_lens)
        
        # Shape of output_concat: (batch_size, no. of queries, num_hiddens)
        output_concat = self.transpose_output(output)
        return self.W_o(output_concat)

x.5.2 使用transpose_qkv分裂成多头

在实践中,给定相同的查询、键和值集,我们可能希望我们的模型将来自相同注意机制的不同行为的知识结合起来,例如在一个序列中捕获不同范围(例如,短范围和长范围)的依赖关系。即,将生成的token_query(batch, number of query, dimension)中的dimension均分成heads等分来达到多头的目的,以学到多尺度的特征向量(类比卷积学到的多尺度特征)。故引入Multi-Head Attention (MA)。

请添加图片描述

例如,你输入的query.shape==[2, 4, 100],经过多头分裂后就变成了query.shape==[10, 4, 20]均分成多头的代码:

    def transpose_qkv(self, X):
        """Transposition for parallel computation of multiple attention heads."""
        # Shape of input X: (batch_size, no. of queries or key-value pairs,
        # num_hiddens). Shape of output X: (batch_size, no. of queries or
        # key-value pairs, num_heads, num_hiddens / num_heads)
        X = X.reshape(X.shape[0], X.shape[1], self.num_heads, -1)
        # Shape of output X: (batch_size, num_heads, no. of queries or key-value
        # pairs, num_hiddens / num_heads)
        X = X.permute(0, 2, 1, 3)
        # Shape of output: (batch_size * num_heads, no. of queries or key-value
        # pairs, num_hiddens / num_heads)
        return X.reshape(-1, X.shape[2], X.shape[3])

x.5.3 使用nn.LazyLinear进行单头可学习参数调整

对于单个head的计算,我们还会引入三个可学习参数用于分别和K,Q,V进行计算,是通过fully connection(FC/全连接层/线性层)实现的,式中的 f f f是Attention pooling如点积注意力机制等的方法。

请添加图片描述

他的代码实现过程如下:

self.W_q = nn.LazyLinear(num_hiddens, bias=bias)

x.5.4 点积注意力

使用x.3.4的点积注意力对3个三维矩阵进行点积注意力操作。

        # Shape of output: (batch_size * num_heads, no. of queries, # num_hiddens / num_heads)
        output = self.attention(queries, keys, values, valid_lens)

x.5.5 concat拼接后进行Linear可学习参数

最终所有的heads输出都会进行concat拼接(维度方向上进行拼接),拼接完毕后,还会引入一个可学习参数用于和Output进行计算,也是通过线性层实现的。

请添加图片描述

        # Shape of output_concat: (batch_size, no. of queries, num_hiddens)
        output_concat = self.transpose_output(output)
        return self.W_o(output_concat)

x.6 Self-Attention and Positional Encoding 自注意力 + 位置编码

x.6.1 自注意力机制

借鉴点积注意力和多头注意力,产生了自注意机制。自注意力机制的输入输出token的长度相同。每一个token的向量长度为(batch size, number of time steps or sequence length in tokens, d)

这里的d比如说query为三维矩阵(mini-batch size, number of query, dimension), dimension = num_hiddens = length of token (= number of query-key pairs) != number of key-value pairs.

x.6.2 Position Encoding

与RNN一个一个处理token不同,Self-attention模块是并行处理很多,这导致了它会丢失掉先后顺序的位置信息。

我们可以通过position encoding添加位置信息。position encoding 的方式包括can either be learned or fixed a priori(被先前学习或者被固定在输入向量中)。We now describe a simple scheme for fixed positional encodings based on sine and cosine functions我们现在引入一种固定位置的方式在sin,cos中。我们通过X+P引入位置向量,其中P是 n x d 的矩阵,维度大小同Query,包含位置信息。

class PositionalEncoding(nn.Module):  #@save
    """Positional encoding."""
    def __init__(self, num_hiddens, dropout, max_len=1000):
        super().__init__()
        self.dropout = nn.Dropout(dropout)
        # Create a long enough P
        self.P = torch.zeros((1, max_len, num_hiddens))
        X = torch.arange(max_len, dtype=torch.float32).reshape(
            -1, 1) / torch.pow(10000, torch.arange(
            0, num_hiddens, 2, dtype=torch.float32) / num_hiddens)
        self.P[:, :, 0::2] = torch.sin(X)
        self.P[:, :, 1::2] = torch.cos(X)

    def forward(self, X):
        X = X + self.P[:, :X.shape[1], :].to(X.device)
        return self.dropout(X)

x.7 The Transformer Architecture (Transformer的架构)(重点)

x.7.1 整体介绍

Transformer是一个Encoder-Decoder架构,由n摞encoder-decoder组成。

其中在一开始会有Embedding将句子中的每一个词转为token词向量,但是self-attention缺少上下文位置信息,所以经过Positional encoding来用加操作叠加位置信息。

Encoder模块有两个sub-layer组成:multi-head attentionpositionwise FFN

Decoder模块有三个sub-layer组成:masked multi-head attentionmulti-head attentionpositionwise FFN

其中add是Residual残差模块,norm是Layer Norm用于归一化。

整体计算过程可以参考https://blog.csdn.net/qq_43369406/article/details/129306734
请添加图片描述

x.7.2 N摞什么意思

N摞指的是串行结构,提取了多次特征或者解码了多次。由于CV用不到decoder,便不讲述decoder部分,例如循环右移,每次蹦出一个词下一层Decoder输入是上一层Decorder的输出增加mask以保证只关注当前位置向量等。整体n摞架构如下:

请添加图片描述

x.7.3 encoder模块

我们的特征经过n摞encoder进行特征提取。多头注意力机制内容一样,这里增加讲解一下positionwise FFNlayer norm

Positionwise FFN主要用于增强模型在每个位置上的表示能力。每个位置上的表示能力指的是模型对输入序列中每个位置的理解和表达能力。在Transformer模型中,使用了自注意力机制(self-attention),用于对每个位置的表示进行建模,以捕捉与该位置相关的上下文信息。然而,自注意力机制本身并没有位置感知性,它对所有位置的表示都采取了相同的操作。因此,Positionwise FFN的作用就是在自注意力机制之后,通过非线性映射和变换,增强每个位置上的表示能力,使得模型可以更好地区分和编码不同位置的特征和语义信息。

位置编码前馈网络(positionwise feed-forward network)使用相同的多层感知机(MLP)来对序列中所有位置的表示进行转换,由两层Linear和一层ReLU组成,它的整体代码如下:

class PositionWiseFFN(nn.Module):  #@save
    """The positionwise feed-forward network."""
    def __init__(self, ffn_num_hiddens, ffn_num_outputs):
        super().__init__()
        self.dense1 = nn.LazyLinear(ffn_num_hiddens)
        self.relu = nn.ReLU()
        self.dense2 = nn.LazyLinear(ffn_num_outputs)

    def forward(self, X):
        return self.dense2(self.relu(self.dense1(X)))

layer norm指的是对每个样本进行归一化。

x.8 ViT (重点)

x.8.1 整体过程

首先我们拥有一个height为 h 和width为 w 的图片, 然后我们将图片分割为 p x p , 最终我们将原图变成了 m = h x w / ( p x p ) 个数量的patches, 然后每一个patch展平为 c x p x p 长度的vector.

我们将 m 个vectors的最开头 追加一个用于表示 cls 的vector, 最终我们有 m + 1 个vectors.

将m + 1个vecotrs添加 positional Embedding 位置编码,然后再传入Transformer中训练.

最终取出第一个vector,做Norm和MLP,生成了 class 类别标签.

请添加图片描述

x.8.2 与Transformer中的encoder的不同之处

ViT的 MLP 和 Transformer的position-wise FFN 不同, 虽然其指代的是同一个。First, here the activation function uses the Gaussian error linear unit (GELU), which can be considered as a smoother version of the ReLU. Second, dropout is applied to the output of each fully connected layer in the MLP for regularization. 首先使用了 GELU 而不是 ReLU ( 虽然Transformer中有使用ReLU, 在FFN中 ), 接着引入了dropout( Trans 中只在 Position encoding 后有dropout, 而在FFN中是没有dropout ).

The vision Transformer encoder block implementation just follows the pre-normalization design in Fig. 11.8.1, where normalization is applied right before multi-head attention or the MLP. In contrast to post-normalization (“add & norm” in Fig. 11.7.1), where normalization is placed right after residual connections, pre-normalization leads to more effective or efficient training for Transformers. 使用了 pre-normalization 代替 post-normalization 即 “先 norm 再 MSA”, 这样更加快速和有效.

x.9 多尺度Transformer预训练模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/582427.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目复盘四步:怎么做才有成效?这些关键点不可忽略

在项目管理中,及时复盘是非常重要的,因为只有通过反思和分析,才能找到差距存在的原因。 复盘分析的第一步是回顾目标 因为目标是工作开展的关键。在执行项目的过程中,要始终朝着所设定的目标去努力实现。计划和现实会存在偏差&…

超详细Zookeeper+Kafka+ELK集群部署

一、Zookeeper 概述 1、Zookeeper 定义 Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。 2、Zookeeper 工作机制 Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理…

AutoCV第九课:ML基础

目录 矩阵运算前言1. 矩阵乘法和求导总结 矩阵运算 前言 手写AI推出的全新保姆级从零手写自动驾驶CV课程,链接。记录下个人学习笔记,仅供自己参考。 本次课程主要学习矩阵运算的基础,考虑使用矩阵来表达多个线性回归模型。 课程大纲可看下面…

多元回归预测 | Matlab龙格算法(RUN)优化最小二乘支持向量机回归预测,RUN-LSSVM回归预测,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab龙格算法(RUN)优化最小二乘支持向量机回归预测,RUN-LSSVM回归预测,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源码 %--…

注意力机制(一)SE模块(Squeeze-and-Excitation Networks)论文总结和代码实现

Squeeze-and-Excitation Networks(压缩和激励网络) 论文地址:Squeeze-and-Excitation Networks 论文中文版:Squeeze-and-Excitation Networks_中文版 代码地址:GitHub - hujie-frank/SENet: Squeeze-and-Excitation Ne…

git 文件恢复与项目还原:008

1. 【文件恢复】:将文件恢复到上一次提交的状态 注意:新建且没有提交的文件无法使用文件恢复 命令: git checkout -- 文件名假如我们的一开始是这样的,这是没有报错的状态文件 然后我添加了一段内容, 比如我添加这段内…

做外贸算运费的时候需不需要多算一些

看到一个网友在一篇文章下留言说:客户算运费的时候需不需要多算一些 听公司老员工说给客户算运费要多加20% 这样合适吗 我个人感觉有点离谱。 那我们就这个话题,谈一谈运费是否要多加一些呢?为什么要多加一些? 首先,要…

Zookeeper学习---3、服务器动态上下线监听案例、ZooKeeper 分布式锁案例、企业面试真题

1、服务器动态上下线监听案例 1、需求 某分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线。 2、需求分析 3、具体实现 (1)先在集群上创建/servers 节点 &#xff…

软考A计划-试题模拟含答案解析-卷八

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…

2023年上半年系统集成项目管理工程师下午真题及答案解析

试题一(18分) A公司跨国收购了B公司的主营业务,保留了B公司原有的人员组织结构和内部办公系统。为了解决B公司内部办公系统与A公司原有系统不兼容的问题,财务、人力和行政部门联合向公司高层申请尽快启动系统和业务的整合。 A公司领导指定HR总监王工担…

云容灾部署前的准备指南

据ITIC的研究表明,98%的千人规模企业每年都会遭遇停机危机,每停机一小时就会损失约700,000人民币。当灾难发生时,使用云容灾的企业可以通过云平台提供的资源和服务,快速帮助企业恢复业务。 HyperBDR云容灾,深度对接全…

Kibana:使用 Docker 安装 Kibana - 8.x

Kibana 的 Docker 镜像可从 Elastic Docker 注册中心获得。 基本映像是 ubuntu:20.04。www.docker.elastic.co 上提供了所有已发布的 Docker 图像和标签的列表。 源代码在 GitHub 中。 这些镜像包含免费和订阅功能。 开始 30 天试用以试用所有功能。 如果你还没有安装好自己的…

一文了解什么是ChatGPT

ChatGPT 是一种自然语言人工智能聊天机器人。在最基本的层面上,这意味着你可以问它任何问题,它会生成一个答案。 一、如何使用聊天 GPT 首先,转到chat.openai.com。如果这是您的第一次,您需要在开始之前使用 OpenAI 设置一个免费…

C919中有哪些项目是华为之作?

#C919# C919和华为都是我们国人的骄傲。那你知道在C919中有哪些项目是华为之作吗?C919与华为的合作主要涉及航空电子领域: 1.飞机高清视频传输系统:该系统使用华为的数字视频传输技术,可以将高清视频信号快速地传输到地面监控中心…

Gradio的web界面演示与交互机器学习模型,高级接口特征《6》

大多数模型都是黑盒,其内部逻辑对最终用户是隐藏的。为了鼓励透明度,我们通过简单地将Interface类中的interpretation关键字设置为default,使得向模型添加解释变得非常容易。这允许您的用户了解输入的哪些部分负责输出。 1、Interpret解释 …

NetApp E 系列混合闪存阵列——专为需要高带宽的专用应用程序而构建(如数据分析、视频监控、HPC、基于磁盘的备份)

E 系列混合闪存阵列:专为交付而构建 为什么选择 NetApp E 系列阵列? 超过 100 万次的安装和计数 凭借其提供的精简性和可靠性,我们的 E 系列阵列成为了众多企业的首选系统。从推动数据密集型应用程序(如分析、视频监控和基于磁盘…

PLC/DCS系统常见的干扰现象及判断方法

一般来说,常见的干扰现象有以下几种: 1.系统发指令时,电机无规则地转动; 2.信号等于零时,数字显示表数值乱跳; 3。传感器工作时,DCS/PLC 采集过来的信号与实际参数所对应的信号值不吻合,且误…

微信小程序报错:“该小程序提供的服务出现故障,请稍后再试”(IOS报错,Android则正常)

记录对接微信小程序时遇到的问题,问题表现为: 1、发送消息后出现报错:该小程序提供的服务出现故障,请稍后再试 2、只有IOS会报错,Android则是正常的 3、IOS报错的微信号,即使在电脑端登录,使…

HKPCA Show携手电巢直播开启“云”观展!掀起一场电子人的顶级狂欢!

近日,国际电子电路(深圳)展览会(HKPCA Show)已于深圳国际会展中心圆满举办!本次展览划分七大主题专区,面积超50,000平方米,展位超2500个,汇聚众多行业知名、有影响力的参…

腾讯云3年轻量应用服务器和5年CVM云服务器限制说明

腾讯云轻量服务器2核2G4M带宽三年388元、2核4G5M带宽三年599元、CVM云服务器2核2G配置5年1728元、2核4G配置5年3550元、4核8G配置5年6437元,从性价比角度来看,还是轻量应用服务器比较划算,腾讯云百科分享阿里云3年轻量应用服务器和5年云服务器…