【论文笔记】Transformer

Transformer

2017 年,谷歌团队提出 Transformer 结构,Transformer 首先应用在自然语言处理领域中的机器翻译任务上,Transformer 结构完全构建于注意力机制,完全丢弃递归和卷积的结构,这使得 Transformer 结构效率更高。迄今为止,Transformer 广泛应用于深度学习的各个领域。

模型架构

Transformer 结构如下图所示,Transformer 遵循编码器-解码器(Encoder-Decoder)的结构,每个 Transformer Block 的结构基本上相同,其编码器和解码器可以视为两个独立的模型,例如:ViT 仅使用了 Transformer 编码器,而 GPT 仅使用了 Transformer 解码器。

Transformer Architecture

编码器

编码器包含 N = 6 N=6 N=6 个相同的层,每个层包含两个子层,分别是多头自注意力层(Multi Head Self-Attention)和前馈神经网络层(Feed Forward Network),每个子层都包含残差连接(Residual Connection)和层归一化(Layer Normalization),使模型更容易学习。FFN 层是一个两层的多层感知机(Multi Layer Perceptron)。

解码器

解码器也包含 N = 6 N=6 N=6 个相同的层,包含三个子层,分别是掩码多头自注意力层(Masked Multi-Head Attention)、编码器-解码器多头注意力层(Cross Attention)和前馈神经网络层。

其中,掩码多头自注意力层用于将输出的 token 进行编码,在应用注意力机制时存在一个注意力掩码,以保持自回归(Auto Regressive)特性,即先生成的 token 不能注意到后生成的 token,编码后作为 Cross Attention 层的 Query,而 Cross Attention 层的 Key 和 Value 来自于编码器的输出,最后通过 FFN 层产生解码器块的输出。

位置编码

递归神经网络(Recurrent Neural Networks)以串行的方式处理序列信息不同,注意力机制本身不包含位置关系,因此 Transformer 需要为序列中的每个 token 添加位置信息,因此需要位置编码。Transformer 中使用了正弦位置编码(Sinusoidal Position Embedding),位置编码由以下数学表达式给出:

P E p o s , 2 i = sin ⁡ ( p o s 1000 0 2 i / d model ) P E p o s , 2 i + 1 = cos ⁡ ( p o s 1000 0 2 i / d model ) \begin{aligned} &PE_{pos,2i} = \sin \left( \frac{pos}{10000^{2i/d_{\text{model}}}} \right)\\ &PE_{pos,2i+1} = \cos \left( \frac{pos}{10000^{2i/d_{\text{model}}}} \right) \end{aligned} PEpos,2i=sin(100002i/dmodelpos)PEpos,2i+1=cos(100002i/dmodelpos)

其中,pos 为 token 所在的序列位置,i 则是对应的特征维度。作者采用正弦位置编码是基于正弦位置编码可以使模型更容易学习到相对位置关系的假设。

下面是正弦位置编码的 PyTorch 实现代码,仅供参考。

class PositionEmbedding(nn.Module):"""Sinusoidal Positional Encoding."""def __init__(self, d_model: int, max_len: int) -> None:super(PositionEmbedding, self).__init__()self.pe = torch.zeros(max_len, d_model, requires_grad=False)factor = 10000 ** (torch.arange(0, d_model, step=2) / d_model)pos = torch.arange(0, max_len).float().unsqueeze(1)self.pe[:, 0::2] = torch.sin(pos / factor)self.pe[:, 1::2] = torch.cos(pos / factor)def forward(self, x: Tensor) -> Tensor:seq_len = x.size()[1]pos_emb = self.pos_encoding[:seq_len, :].unsqueeze(0).to(x.device)return pos_emb

注意力机制

注意力机制出现在 Transformer 之前,包括两种类型:加性注意力和乘性注意力。Transformer 使用的是乘性注意力,这也是最常见的注意力机制,首先计算一个点积相似度,然后通过 Softmax 后得到注意力权重,根据注意力权重对 Values 进行加权求和,具体的过程可以表示为以下数学公式:

Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q,K,V)=\text{softmax}(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dk QKT)V

Attention

其中,注意力计算中包含了一个温度参数 d k \sqrt{d_k} dk ,一个直观的解释是避免点积的结果过大或过小,导致 softmax 后的结果梯度几乎为 0 的区域,降低模型的收敛速度。对于自回归生成任务而言,我们不希望前面生成的 token 关注后面生成 token,因此可能会采用一个下三角的 Attention Mask,掩盖掉 attention 矩阵的上三角部分,注意力机制可以重写为:

Attention ( Q , K , V ) = softmax ( Q K T d k + M ) V \text{Attention}(Q,K,V)=\text{softmax}(\frac{QK^T}{\sqrt{d_k}}+M)V Attention(Q,K,V)=softmax(dk QKT+M)V

具体实现中,需要 mask 掉的部分设置为负无穷即可,这会使得在 softmax 操作后得到的注意力权重为 0,避免注意到特定的 token。

有趣的是,注意力机制本身不包含可学习参数,因此,在 Transformer 中引入了多头注意力机制,同时希望多头注意力能够捕捉多种模式,类似于卷积。多头注意力机制可以表示为:

MultiHead ( Q , K , V ) = Concat ( head 1 , head 2 , … , head h ) W O where  head i = Attention ( Q W i Q , K W i K , V W i V ) \begin{aligned} \text{MultiHead}(Q,K,V)=\text{Concat}(\text{head}_1,\text{head}_2,\dots,\text{head}_h)W^O\\ \text{where }\text{head}_i=\text{Attention}(QW_i^Q,KW_i^K,VW_i^V) \end{aligned} MultiHead(Q,K,V)=Concat(head1,head2,,headh)WOwhere headi=Attention(QWiQ,KWiK,VWiV)

以下为多头注意力机制的 PyTorch 实现代码,仅供参考。

from torch import nn, Tensor
from functools import partialclass MultiHeadAttention(nn.Module):"""Multi-Head Attention."""def __init__(self, d_model: int, n_heads: int) -> None:super(MultiHeadAttention, self).__init__()self.n_heads = n_headsself.proj_q = nn.Linear(d_model, d_model)self.proj_k = nn.Linear(d_model, d_model)self.proj_v = nn.Linear(d_model, d_model)self.proj_o = nn.Linear(d_model, d_model)self.attention = ScaledDotProductAttention()def forward(self, q: Tensor, k: Tensor, v: Tensor, mask: Tensor | None = None) -> Tensor:# input tensor of shape (batch_size, seq_len, d_model)# 1. linear transformationq, k, v = self.proj_q(q), self.proj_k(k), self.proj_v(v)# 2. split tensor by the number of headsq, k, v = map(partial(_split, n_heads=self.n_heads), (q, k, v))# 3. scaled dot-product attentionout = self.attention(q, k, v, mask)# 4. concatenate headsout = _concat(out)# 5. linear transformationreturn self.proj_o(out)class ScaledDotProductAttention(nn.Module):"""Scaled Dot-Product Attention."""def __init__(self) -> None:super(ScaledDotProductAttention, self).__init__()self.softmax = nn.Softmax(dim=-1)def forward(self, q: Tensor, k: Tensor, v: Tensor, mask: Tensor | None = None) -> Tensor:# input tensor of shape (batch_size, n_heads, seq_len, d_head)d_k = k.size()[3]k_t = k.transpose(2, 3)# 1. compute attention scorescore: Tensor = (q @ k_t) * d_k**-0.5# 2. apply mask(optional)if mask is not None:score = score.masked_fill(mask == 0, float("-inf"))# 3. compute attention weightsattn = self.softmax(score)# 4. compute attention outputout = attn @ vreturn outdef _split(tensor: Tensor, n_heads: int) -> Tensor:"""Split tensor by the number of heads."""batch_size, seq_len = tensor.size()[:2]d_model = tensor.size()[2]d_head = d_model // n_headsreturn tensor.view(batch_size, seq_len, n_heads, d_head).transpose(1, 2)def _concat(tensor: Tensor) -> Tensor:"""Concatenate tensor after splitting."""batch_size, n_heads, seq_len, d_head = tensor.size()d_model = n_heads * d_head

参考

[1] A. Vaswani et al., “Attention is All you Need,” in Advances in Neural Information Processing Systems, Curran Associates, Inc., 2017.

[2] A. Dosovitskiy et al., “An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale,” Jun. 03, 2021, arXiv: arXiv:2010.11929.

[3] K. He, X. Zhang, S. Ren, and J. Sun, “Deep Residual Learning for Image Recognition,” Dec. 10, 2015, arXiv: arXiv:1512.03385.

[4] A. Radford, K. Narasimhan, T. Salimans, and I. Sutskever, “Improving Language Understanding by Generative Pre-Training”.

[5] hyunwoongko. "Transformer: PyTorch Implementation of ‘Attention Is All You Need’ " Github 2019. [Online] Available: https://github.com/hyunwoongko/transformer

[6] 李沐. “Transformer论文逐段精读【论文精读】” Bilibili 2021. [Online] Available: https://www.bilibili.com/video/BV1pu411o7BE/?spm_id_from=333.337.search-card.all.click&vd_source=c8a32a5a667964d5f1068d38d6182813

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

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

相关文章

CI/CD(三) 安装nfs并指定k8s默认storageClass

一、NFS 服务端安装(主节点 10.60.0.20) 1. 安装 NFS 服务端 sudo apt update sudo apt install -y nfs-kernel-server 2. 创建共享目录并配置权限 sudo mkdir -p /data/k8s sudo chown nobody:nogroup /data/k8s # 允许匿名访问 sudo chmod 777 /dat…

【QA】单件模式在Qt中有哪些应用?

单例设计模式确保一个类仅有一个实例,并提供一个全局访问点来获取该实例。在 Qt 框架中,有不少类的设计采用了单例模式,以下为你详细介绍并给出相应代码示例。 1. QApplication QApplication 是 Qt GUI 应用程序的核心类,每个 Q…

存储过程触发器习题整理1

46、{blank}设有商品表(商品号,商品名,单价)和销售表(销售单据号,商品号,销售时间,销售数量,销售单价)。其中,商品号代表一类商品,商品号、单价、销售数量和销售单价均为整型。请编写…

基于ChatGPT、GIS与Python机器学习的地质灾害风险评估、易发性分析、信息化建库及灾后重建高级实践

第一章、ChatGPT、DeepSeek大语言模型提示词与地质灾害基础及平台介绍【基础实践篇】 1、什么是大模型? 大模型(Large Language Model, LLM)是一种基于深度学习技术的大规模自然语言处理模型。 代表性大模型:GPT-4、BERT、T5、Ch…

单表达式倒计时工具:datetime的极度优雅(智普清言)

一个简单表达式,也可以优雅自成工具。 笔记模板由python脚本于2025-03-22 20:25:49创建,本篇笔记适合任意喜欢学习的coder翻阅。 【学习的细节是欢悦的历程】 博客的核心价值:在于输出思考与经验,而不仅仅是知识的简单复述。 Pyth…

最优编码树的双子性

现在看一些书,不太愿意在书上面做一些标记,也没啥特殊的原因。。哈哈。 树的定义 无环连通图,极小连通图,极大无环图。 度 某个节点,描述它的度,一般默认是出度,分叉的边的条数。或者说孩子…

MiB和MB

本文来自腾讯元宝 MiB 和 ​MB 有区别,尽管它们都用于表示数据存储的单位,但它们的计算方式不同,分别基于不同的进制系统。 1. ​MiB(Mebibyte)​ ​MiB 是基于二进制的单位,使用1024作为基数。1 MiB 102…

Labview和C#调用KNX API 相关东西

叙述:完全没有听说过KNX这个协议...................我这次项目中也是简单的用了一下没有过多的去研究 C#调用示例工程链接(labview调用示例在 DEBUG文件夹里面) 通过网盘分享的文件:KNX调用示例.zip 链接: https://pan.baidu.com/s/1NQUEYM11HID0M4ksetrTyg?pwd…

损失函数理解(二)——交叉熵损失

损失函数的目的是为了定量描述不同模型(例如神经网络模型和人脑模型)的差异。 交叉熵,顾名思义,与熵有关,先把模型换成熵这么一个数值,然后用这个数值比较不同模型之间的差异。 为什么要做这一步转换&…

Kubernetes的Replica Set和ReplicaController有什么区别

ReplicaSet 和 ReplicationController 是 Kubernetes 中用于管理应用程序副本的两种资源,它们有类似的功能,但 ReplicaSet 是 ReplicationController 的增强版本。 以下是它们的主要区别: 1. 功能的演进 ReplicationController 是 Kubernete…

信息系统运行管理员教程3--信息系统设施运维

第3章 信息系统设施运维 信息系统设施是支撑信息系统业务活动的信息系统软硬件资产及环境。 第1节 信息系统设施运维的管理体系 信息系统设施运维的范围包含信息系统涉及的所有设备及环境,主要包括基础环境、硬件设备、网络设备、基础软件等。 信息系统设施运维…

如何通过Python实现自动化任务:从入门到实践

在当今快节奏的数字化时代,自动化技术正逐渐成为提高工作效率的利器。无论是处理重复性任务,还是管理复杂的工作流程,自动化都能为我们节省大量时间和精力。本文将以Python为例,带你从零开始学习如何实现自动化任务,并通过一个实际案例展示其强大功能。 一、为什么选择Pyt…

Spring Boot 与 MyBatis Plus 整合 KWDB 实现 JDBC 数据访问

​ 引言 本文主要介绍如何在 IDEA 中搭建一个使用 Maven 管理的 Spring Boot 应用项目工程,并结合在本地搭建的 KWDB 数据库(版本为:2.0.3)来演示 Spring Boot 与 MyBatis Plus 的集成,以及对 KWDB 数据库的数据操作…

Java锁等待唤醒机制

在 Java 并发编程中,锁的等待和唤醒机制至关重要,通常使用 wait()、notify() 和 notifyAll() 来实现线程间的协调。本文将详细介绍这些方法的用法,并通过示例代码加以说明。 1. wait()、notify() 与 notifyAll() 在 Java 中,Obj…

 UNIX网络编程笔记:TCP客户/服务器程序示例

服务器实例 有个著名的项目&#xff0c;tiny web&#xff0c;本项目将其改到windows下&#xff0c;并使用RAII重构&#xff0c;编写过程中对于内存泄漏确实很头疼&#xff0c;还没写完&#xff0c;后面会继续更&#xff1a; #include <iostream> #include <vector&g…

AI Agent开发大全第四课-提示语工程:从简单命令到AI对话的“魔法”公式

什么是提示语工程&#xff1f;一个让AI“听话”的秘密 如果你曾经尝试过用ChatGPT或者其他大语言模型完成任务&#xff0c;那么你一定遇到过这样的情况&#xff1a;明明你的问题是清晰的&#xff0c;但答案却离题万里&#xff1b;或者你认为自己提供的信息足够详尽&#xff0c…

系统架构设计知识体系总结

1.技术选型 1.什么是技术选型&#xff1f; 技术选型是指评估和选择在项目或系统开发中使用的最合适的技术和工具的过程。这涉及考虑基于其能力、特性、与项目需求的兼容性、可扩展性、性能、维护和其他因素的各种可用选项。技术选型的目标是确定与项目目标相符合、能够有效解…

基于3DMax与Vray引擎的轻量级室内场景渲染实践

欢迎踏入3DMAX室内渲染的沉浸式学习之旅!在这个精心设计的实战教程中,我们将携手揭开3DMAX与Vray这对黄金搭档在打造现实室内场景时的核心奥秘。无论您是渴望入门的3D新手,还是追求极致效果的专业设计师,这里都将为您呈现从场景蓝图构建到光影魔法施加的完整技术图谱。我们…

逻辑卷,vdo,(阿里加速器)

一、逻辑卷 10 20 30 1.逻辑卷的2个特点 &#xff08;1&#xff09;逻辑卷可以将多个分区或者磁盘整合成一个更大的逻辑磁盘&#xff0c;然后可以从逻辑磁盘上划分出分区&#xff08;逻辑磁盘的大小等于整合的物理磁盘大小之和。&#xff09; &#xff08;2&#xff09;能…

检索增强生成(2)本地PDF 本地嵌入模型

from langchain_community.document_loaders import PyPDFLoader from pathlib import Pathdef load_local_pdf(file_path):if not Path(file_path).exists():raise FileNotFoundError(f"文件 {file_path} 不存在&#xff01;")loader PyPDFLoader(file_path)try:do…