当前位置: 首页 > article >正文

【NLP251】Transformer API调用

1. nn.Transformer

nn.Transformer封装了Transformer中的包含编码器(Encoder)和解码器(Decoder)。如下图所示,它对Encoder和Decoder两部分的包装,它并没有实现输入中的Embedding和Positional Encoding和最后输出的Linear+Softmax部分。

我们可以注意到,在torch.nn的模块中,提供了构建transformer所需的各类元素,但却没有直接给出一个完整的Transformer算法模型。原因在于自然语言处理(NLP)领域中,不同的任务对Transformer架构有着多样化的需求。编码器和解码器作为Transformer的核心组成部分,被设计为既可以独立工作,也可以联合使用。这种灵活的设计允许研究者和开发者根据具体NLP任务的需求,将它们以不同的方式组合起来,从而适应各种复杂的应用场景。

  • 只使用编码器的任务

编码器部分的任务是从输入数据中提取特征。编码器通常用于不需要生成新文本序列的任务。

  • 只使用解码器的任务

解码器部分专注于生成新文本。通常使用自回归方式,基于之前的输出生成下一个词。

  • 编码器和解码器都使用的任务

当任务涉及到理解输入序列并生成新的输出序列时,编码器和解码器会联合使用。

这种模块化的方法不仅提高了模型的灵活性,还为研究者探索和优化特定任务的架构提供了便利。

2. nn.Transformer的参数构造详解

参数名解释
d_modelEncoder和Decoder输入参数的特征维度。也就是词向量的维度。默认为512
nhead多头注意力机制中,head的数量。默认值为8。
num_encoder_layersTransformerEncoderLayer的数量。该值越大,网络越深,网络参数量越多,计算量越大。默认值为6
num_decoder_layersTransformerDecoderLayer的数量。该值越大,网络越深,网络参数量越多,计算量越大。默认值为6
dim_feedforwardFeed Forward层(Attention后面的全连接网络)的隐藏层的神经元数量。该值越大,网络参数量越多,计算量越大。默认值为2048
dropout内dropout值。默认值为0.1
activation内Feed Forward层的激活函数。取值可以是string(“relu” or “gelu”)或者一个一元可调用的函数。默认值是relu
custom_encoder自定义Encoder。若你不想用官方实现的TransformerEncoder,你可以自己实现一个。默认值为None
custom_decoder自定义Decoder。若你不想用官方实现的TransformerDecoder,你可以自己实现一个。
layer_norm_epsAdd&Norm层中,BatchNorm的eps参数值。默认为1e-5
batch_firstbatch维度是否是第一个。如果为True,则输入的shape应为(batch_size, 词数,词向量维度),否则应为(词数, batch_size, 词向量维度)。默认为False。这个要特别注意,因为大部分人的习惯都是将batch_size放在最前面,而这个参数的默认值又是False,所以会报错。
norm_first是否要先执行norm。例如,在图中的执行顺序为 Attention -> Add -> Norm。若该值为True,则执行顺序变为:Norm -> Attention -> Add。

3. 构建Transformer网络时常用API

我们在1.小节中提到nn.Transformer封装了Transformer中的包含编码器(Encoder)和解码器(Decoder)它并没有实现输入中的Embedding和Positional Encoding和最后输出的Linear+Softmax部分,所以在使用TransformerAPI时我们常使用以下API

3.1分割的编码器与解码器

nn.TransformerEncoderLayernn.TransformerDecoderLayer:这两个类分别代表Transformer架构中编码器和解码器的单层结构。它们内部包含了自注意力机制(self-attention)和前馈神经网络(feedforward network),同时还具备必要的层归一化(layer normalization)和残差连接(residual connections),以确保模型在训练过程中的稳定性和性能表现。

nn.TransformerEncodernn.TransformerDecoder: 这两个类是Transformer编码器的实现和解码器的实现,其中nn.TransformerEncoder包含了多个nn.TransformerEncoderLayer层的堆叠,nn.TransformerDecoder包含了多个nn.TransformerDecoderLayer层的堆叠。

3.2 其他API组件 

nn.MultiheadAttention: 这个模块实现了多头注意力机制,这是Transformer模型的核心组件之一。多头注意力允许模型在不同的位置同时处理来自序列不同部分的信息,这有助于捕捉序列内的复杂依赖关系。

nn.LayerNorm: 层归一化(Layer Normalization)通常用在Transformer的各个子层的输出上,有助于稳定训练过程,并且提高了训练的速度和效果。

nn.PositionalEncoding: 虽然PyTorch的nn模块中没有这个类,但在使用Transformer时通常会添加一个位置编码层来给模型提供关于词汇在序列中位置的信息,因为Transformer本身不具备处理序列顺序的能力。

nn.Embedding:一个预训练好的语义空间,它将每个标记(如单词、字符等)映射到一个高维空间的向量。这使得模型能够处理文本数据,并为每个唯一的标记捕获丰富的语义属性。嵌入层通常是自然语言处理模型的第一层,用于将离散的文本数据转化为连续的向量表示。其输入是索引列表,输出是对应的嵌入向量。

nn.Transformer.generate_square_subsequent_mask:掩码函数。用于生成一个方形矩阵,用作Transformer模型中自注意力机制的上三角遮罩。这个遮罩确保在序列生成任务中,例如语言模型中,任何给定的元素只会考虑到序列中先于它的元素(即它只能看到过去的信息,不能看到未来的信息)。这种掩码通常在解码器部分使用,防止在预测下一个输出时“作弊”。具体来说,该函数创建了一个方阵,其中对角线及其以下的元素为0(表示可以“看到”这些位置的元素),其余元素为负无穷大(在softmax之前应用,表示位置被屏蔽,不应该有注意力权重)。

import torch.nn as nn
nn.Transformer.generate_square_subsequent_mask(5) # 5指的是target的维度

4. 文本分类任务实战(只使用编码器的任务

import torch
from torch import nn
from torch.nn import TransformerEncoder, TransformerEncoderLayer# 假设超参数和数据预处理已经完成
vocab_size = 1000  # 词汇量
embedding_size = 512  # 嵌入维度
nhead = 8  # 多头注意力的头数
num_encoder_layers = 6  # 编码器层数
dropout = 0.1  # dropout比率
num_classes = 10  # 类别数class TextClassificationModel(nn.Module):def __init__(self, vocab_size, embedding_size, nhead, num_encoder_layers, dropout, num_classes):super(TextClassificationModel, self).__init__()#只使用了Transformer的Encoder部分encoder_layers = TransformerEncoderLayer(d_model=embedding_size, nhead=nhead, dropout=dropout)self.transformer_encoder = TransformerEncoder(encoder_layer=encoder_layers, num_layers=num_encoder_layers)self.embedding = nn.Embedding(vocab_size, embedding_size)self.positional_encoding = nn.Parameter(torch.zeros(1, 5000, embedding_size))  # 假定最大句子长度为 5000self.linear = nn.Linear(embedding_size, num_classes)#----必填参数----#src:Encoder的输入。也就是将token进行Embedding和Positional Encoding之后的tensor。必填参数。Shape为(batch size,sequence length,embedding size)#----可选参数----#src_mask:对src进行mask。不常用。Shape为(sequence length, sequence length)#src_key_padding_mask:对src的token进行mask. 常用。Shape为(batch size, sequence length) def forward(self, src, src_mask, src_padding_mask):src_emb = self.embedding(src) + self.positional_encoding[:, :src.size(1)]encoded_src = self.transformer_encoder(src_emb, src_mask, src_padding_mask)# 假设我们只关心输入序列的第一个元素return self.linear(encoded_src[:, 0])# 假定 src 已经是预处理并被转换成 tensor 的索引
# src = [batch_size, src_len]model = TextClassificationModel(vocab_size, embedding_size, nhead, num_encoder_layers, dropout, num_classes)# 接下来你需要定义mask和padding mask,并且运行模型
# 比如 src_mask, src_padding_mask
# 输出会是一个[batch_size, num_classes]的tensor

5. 类似GPT的文本生成式模型(只使用解码器的任务

import torch
from torch import nnclass GPTLikeModel(nn.Module):def __init__(self, vocab_size, embedding_size, nhead, num_decoder_layers, dropout):super(GPTLikeModel, self).__init__()self.embedding_size = embedding_sizeself.embeddings = nn.Embedding(vocab_size, embedding_size)self.positional_encodings = nn.Parameter(torch.zeros(1, 1024, embedding_size))#只使用了Transformer的Decoder部分self.transformer_decoder_layer = nn.TransformerDecoderLayer(d_model=embedding_size,  nhead=nhead, dropout=dropout)self.transformer_decoder = nn.TransformerDecoder(self.transformer_decoder_layer, num_layers=num_decoder_layers)self.output_layer = nn.Linear(embedding_size, vocab_size)#生成上三角矩阵掩码def generate_square_subsequent_mask(self, sz):mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1)mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))return mask#----必填参数---- #tgt:与src同理,Decoder的输入。 必填参数。也就是将token进行Embedding和Positional Encoding之后的tensor。Shape为(batch size,sequence length,embedding size)#----可选参数----#tgt_mask:对tgt进行mask。常用。Shape为(sequence length, sequence length) #tgt_key_padding_mask:对tgt的token进行mask。常用。Shape为(batch size, sequence length) #memory_key_padding_mask:对tgt的token进行mask。不常用。Shape为(batch size, sequence length) def forward(self, tgt, memory_key_padding_mask):input_mask = self.generate_square_subsequent_mask(input.size(0)).to(input.device)embeddings = self.embeddings(input) * math.sqrt(self.embedding_size)embeddings += self.positional_encodings[:, :tgt.size(0), :]transformer_output = self.transformer_decoder(embeddings, memory, tgt_mask=tgt_mask)output = self.output_layer(transformer_output)return outputdef generate(self, input, max_length):memory = Nonegenerated = inputfor _ in range(max_length):#进行一个字的生成output = self.forward(generated, memory)#只取最后一个时间步的输出,包含所有可能生成的字的概率next_token_logits = output[-1, :, :]  #使用argmax取出概率最大的字next_token = torch.argmax(next_token_logits, dim=-1).unsqueeze(0) #合并生成的字与之前的文本generated = torch.cat((generated, next_token), dim=0)if next_token.item() == eos_token_id:  # 假设eos_token_id是结束标记的IDbreakreturn generated

6. 机器翻译任务(编码器和解码器都使用的任务

import torch
from torch import nn
from torch.nn import Transformer# 假设一些超参数和数据预处理已经完成
src_vocab_size = 1000  # 源语言词汇量
tgt_vocab_size = 1000  # 目标语言词汇量
embedding_size = 512  # 嵌入维度
nhead = 8  # 多头注意力中的头数
num_encoder_layers = 6  # 编码器层数
num_decoder_layers = 6  # 解码器层数
dropout = 0.1  # dropout比率class TranslationModel(nn.Module):def __init__(self, src_vocab_size, tgt_vocab_size, embedding_size, nhead, num_encoder_layers, num_decoder_layers, dropout):super(TranslationModel, self).__init__()self.transformer = Transformer(d_model=embedding_size, nhead=nhead, num_encoder_layers=num_encoder_layers, num_decoder_layers=num_decoder_layers, dropout=dropout)self.src_tok_emb = nn.Embedding(src_vocab_size, embedding_size)self.tgt_tok_emb = nn.Embedding(tgt_vocab_size, embedding_size)self.positional_encoding = nn.Parameter(torch.zeros(1, 5000, embedding_size))  # 假定最大句子长度为 5000self.generator = nn.Linear(embedding_size, tgt_vocab_size)#----必填参数----#src:Encoder的输入。也就是将token进行Embedding和Positional Encoding之后的tensor。必填参数。Shape为(batch size,sequence length,embedding size)#tgt:与src同理,Decoder的输入。 必填参数。Shape为(sequence length,embedding size)#----可选参数----#src_mask:对src进行mask。不常用。Shape为(sequence length, sequence length)#tgt_mask:对tgt进行mask。常用。Shape为(sequence length, sequence length) #src_key_padding_mask:对src的token进行mask. 常用。Shape为(batch size, sequence length) #tgt_key_padding_mask:对tgt的token进行mask。常用。Shape为(batch size, sequence length) def forward(self, src, tgt, src_mask = None, tgt_mask = None, memory_mask = None, src_key_padding_mask = None, tgt_key_padding_mask = None,memory_key_padding_mask = None):src_emb = self.src_tok_emb(src) + self.positional_encoding[:, :src.size(1)]tgt_emb = self.tgt_tok_emb(tgt) + self.positional_encoding[:, :tgt.size(1)]outs = self.transformer(src_emb, tgt_emb, src_mask, tgt_mask, None, src_key_padding_mask, tgt_key_padding_mask, memory_key_padding_mask)return self.generator(outs)# 假定 src 和 tgt 已经是预处理并被转换成 tensor 的索引
# src = [batch_size, src_len]
# tgt = [batch_size, tgt_len]model = TranslationModel(src_vocab_size, tgt_vocab_size, embedding_size, nhead, num_encoder_layers, num_decoder_layers, dropout)# 接下来你需要定义mask和padding mask,并且运行模型
# 比如 src_mask, tgt_mask, src_padding_mask, tgt_padding_mask, memory_key_padding_mask
# 输出会是一个[batch_size, tgt_len, tgt_vocab_size]的tensor

相关文章:

【NLP251】Transformer API调用

1. nn.Transformer nn.Transformer封装了Transformer中的包含编码器(Encoder)和解码器(Decoder)。如下图所示,它对Encoder和Decoder两部分的包装,它并没有实现输入中的Embedding和Positional Encoding和最…...

ubuntu下迁移docker文件夹

在 Ubuntu 系统中迁移 Docker 文件夹(如 Docker 数据存储文件夹 /var/lib/docker)到另一个磁盘或目录,通常是为了释放系统盘空间。以下是迁移过程的详细步骤: 1. 停止 Docker 服务 在进行迁移之前,必须停止 Docker 服…...

为AI聊天工具添加一个知识系统 之93 详细设计之34 Derivation 之 8 实现和平台

本文要点 要点 插入话题:实现 “实现”作为一个普通名词(一般术语)应该遵循第一性第二性第三性原则。其 第一性第二性第三性 分别是:完整性/鲁棒性/健壮性 ,三者 分别注重 性能/功能/能力。即 首先是 实现完整性的性…...

idea 如何使用deepseek 保姆级教程

1.安装idea插件codegpt 2.注册deepseek并生成apikey deepseek 开发平台: DeepSeek​​​​​​​ 3.在idea进行codegpt配置 打开idea的File->Settings->Tools->CodeGPT->Providers->Custom OpenAI Chat Completions的URL填写 https://api.deepseek…...

python实现情绪识别模块,并将模块封装成可执行文件

目录: 1.源码:2.情绪识别模型运行流程:3.模型封装需要注意的地方:4.未解决问题: 1.源码: https://gitcode.com/xyint/deep_learning.git 2.情绪识别模型运行流程: 需要获取用户摄像头权限&…...

AH比价格策略源代码

用python 获取在A股和香港上市的公司和在A股和香港上市的公司股票代码和名称并且选出港股和A股涨幅相差比较大的股票 import akshare as akdef get_ah_stocks():# 获取A股股票列表a_stock_list ak.stock_zh_a_spot_em()print(a_stock_list)a_stock_list a_stock_list[[&quo…...

trimesh 加载obj mesh处理

目录 trimesh 加载obj trimesh入门 主要功能 安装 基本用法 1. 加载和保存 3D 模型 2. 几何操作 3. 网格分析 4. 可视化 5. 布尔运算 6. 碰撞检测 trimesh 加载obj template_mesh trimesh.load_mesh(r"E:\project\3d\lilpotat--pytorch3d\pixie_data\smplx_te…...

常见数据结构的C语言定义---《数据结构C语言版》

文章目录 1. 静态分配的顺序表2. 动态分配的顺序表3. 单 链 表4. 双 链 表5. 静态链表6. 顺序栈7. 链栈8. 顺序存储的队列9. 链式存储的队列10. 链式存储的二叉树11. 线索二叉树12. 树的双亲表示法13. 树的孩子兄弟表示法12. 图的邻接矩阵法13. 图的邻接表法1-13集合版本 #defi…...

C++小知识记录,不定时更新

1. 普通函数不能在头文件中定义: 当多个.cpp调用时,在编译链接时会在.o文件中重复定义报错 2. 为什么内联函数可以在头文件中定义:适用短小函数 当.cpp调用时,编译器只会在当前文件展开该函数,相当于每个.cpp会重新定…...

python--sqlite

1. 连接到数据库 使用 sqlite3.connect() 方法可以创建一个到SQLite数据库的连接。如果指定的数据库文件不存在,它会自动创建一个新的数据库文件。 import sqlite3# 连接到数据库,如果数据库文件不存在则会创建一个新的 conn sqlite3.connect(example…...

使用 Axios ——个人信息修改与提示框实现

目录 详细介绍:个人信息设置与修改页面实现 1. HTML 结构 2. CSS 样式 3. JavaScript 核心逻辑 a. 信息渲染与表单提交 b. 头像上传与预览 4. 功能详解 5. 总结 提示: 这段代码展示了如何创建一个简单的个人信息设置页面,包含用户个…...

群晖安装Gitea

安装Docker Docker运行Gitea 上传gitea包,下载地址:https://download.csdn.net/download/hmxm6/90360455 打开docker 点击印象,点击新增,从文件添加 点击启动 可根据情况,进行高级设置,没有就下一步 点击应…...

LabVIEW商业软件开发

在商业软件开发和仪器自动测试领域,LabVIEW以其图形化编程方式、高效的数据采集能力和强大的硬件集成优势,成为众多工程项目的核心开发工具。然而,商业软件的开发远不止编写代码和实现功能那么简单,尤其是在仪器自动测试领域&…...

内容中台赋能人工智能技术提升业务创新能力

内容概要 在当今快速变化的市场环境中,企业需要不断寻求创新以保持竞争力。内容中台作为一种新型的内容管理架构,能够极大地提升企业在内容创建、管理和分发方面的效率。通过与人工智能技术的深度融合,企业能够将海量的数据和信息转化为有价…...

spring 基于构造方法实例化对象

在 spring 中,对象的实例化创建都在 AbstractAutowireCapableBeanFactory#createBeanInstance 方法中完成,其中定义了不少实例化策略,如:Supplier、工厂方法、构造方法、无参构造。其中无参构造,即 AbstractAutowireCa…...

生成式聊天机器人 -- 基于Pytorch + Global Attention + 双向 GRU 实现的SeqToSeq模型 -- 下

生成式聊天机器人 -- 基于Pytorch Global Attention 双向 GRU 实现的SeqToSeq模型 -- 下 训练Masked 损失单次训练过程迭代训练过程 测试贪心解码(Greedy decoding)算法实现对话函数 训练和测试模型完整代码 生成式聊天机器人 – 基于Pytorch Global Attention 双向 GRU 实…...

Vue.js 与第三方插件的集成

Vue.js 与第三方插件的集成 今天我们来聊聊如何在 Vue 项目中集成第三方插件。随着项目功能不断增多,我们常常需要引入各种第三方库和插件,比如国际化、图表、日期处理等,来提升开发效率和用户体验。下面就跟大家分享一下集成第三方插件的常…...

Netty初学九 心跳与空闲检测

一、网络问题 1.连接假死: 连接假死的现象是:在某一端看来,底层的Tcp连接已经断开,但是应用程序没有捕获到,会认为这条连接仍然是存在的。从TCP层面来说,只有收到四次握手数据包或者一个RST数据包才可以表示…...

数据分析如何做EDA

探索性数据分析(EDA,Exploratory Data Analysis)是数据分析过程中至关重要的一步,其目的是通过统计和可视化技术对数据进行初步分析,从而揭示数据的潜在模式、特征和异常值,并为后续的数据预处理、特征工程…...

AD域控粗略了解

一、前提 转眼大四,目前已入职上饶一公司从事运维工程师,这与我之前干的开发有着很大的差异,也学习到了许多新的知识。今天就写下我对于运维工作中常用的功能——域控的理解。 二、为什么要有域控,即域控的作用 首先我们必须要…...

【计算机网络】TCP/IP 网络模型有哪几层?

目录 应用层 传输层 网络层 网络接口层 总结 为什么要有 TCP/IP 网络模型? 对于同一台设备上的进程间通信,有很多种方式,比如有管道、消息队列、共享内存、信号等方式,而对于不同设备上的进程间通信,就需要网络通…...

使用 Typora 编写 MD 文档:从入门到精通(附赠百度网盘下载地址)

引言 Markdown(简称 MD)是一种轻量级标记语言,广泛应用于技术写作、博客撰写、文档管理等领域。Typora 是一款功能强大且易于使用的 Markdown 编辑器,支持实时预览、语法高亮、主题切换等功能,深受开发者和写作者的喜…...

Spring统一修改RequestBody

我们编写RestController时,有可能多个接口使用了相同的RequestBody,在一些场景下需求修改传入的RequestBody的值,如果是每个controller中都去修改,代码会比较繁琐,最好的方式是在一个地方统一修改,比如将he…...

【Flink实战】Flink -C实现类路径配置与实现UDF Jar

文章目录 1. 描述2. 使用语法3. -C 适用的 Flink 运行模式4. USING JAR 不可用 1. 描述 Flink 中的 -C 选项用于将 URL 添加到作业的类加载器中。URL可以指向本地、HTTP 服务器或 HDFS 等资源的Jar文件。 注意: 此处的classpath的url必须是一个能够在client&…...

DevOps的个人学习

一、DevOps介绍 软件开发最初是由两个团队组成: 开发团队:负责设计和构建系统。运维团队:负责测试代码后部署上线,确保系统稳定安全运行。 这两个看似目标不同的团队需要协同完成一个软件的开发。DevOps整合了开发与运维团队&a…...

【东莞常平】戴尔R710服务器不开机维修分享

1:2025-02-06一位老客户的朋友刚开工公司ERP服务器一台戴尔老服务器故障无法开机,于是经老客户介绍找到我们。 2:服务器型号是DELL PowerEdge R710 这个服务器至少也有15年以上的使用年限了。 3:客户反馈的故障问题为:…...

STM32自学记录(八)

STM32自学记录 文章目录 STM32自学记录前言一、ADC杂记二、实验1.学习视频2.复现代码 总结 前言 ADC 一、ADC杂记 ADC其实就是一个电压表,把引脚的电压值测出来,放在一个变量里。 ADC:模拟——数字转换器。 ADC可以将引脚上连续变化的模拟电…...

【Java八股】JVM

JVM 1. jvm内存区域分为哪些部分 线程私有的:程序计数器、虚拟机栈、本地方法栈 程序计数器:指示当前线程执行到的字节码文件的行号,是线程切换后保证线程能恢复到正确的执行位置的关键 虚拟机栈:用于存储方法调用的数据&…...

Citespace之关键词爆发检测分析(进阶分析)

在开始citespace进行关键词爆发检测分析之前,如果不会使用citespace的,可以参考我之前这一篇博客: https://blog.csdn.net/m0_56184997/article/details/145536095?spm1001.2014.3001.5501 一、创建工程后进行设置 在创建好工程后&#xf…...

解锁 DeepSeek 模型高效部署密码:蓝耘平台深度剖析与实战应用

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...