Transformer是怎样处理序列数据的?

Transformer模型最初是一种广泛应用于自然语言处理(NLP)和其他序列建模任务的架构。它由编码器(encoder)和解码器(decoder)组成。
Transformer结构

以下是Transformer模型输入和输出的详细介绍:

输入

1. 输入序列(Input Sequence)

输入的内容可以是一句话,比如"Hello, how are you?"。输入序列是指用分词器(tokenizer)将文本转化为一系列标识符(token IDs)。这些标识符是一个词汇表中不同词汇的索引。Transformer模型的词汇表大小(vocabulary size)取决于具体任务和所使用的预训练模型。词汇表大小表示模型在处理输入序列时可以识别的不同词汇或子词的数量。BERT-base和BERT-large模型的词汇表大小通常为30,000。GPT-2模型的词汇表大小为50,257。常见的预训练模型的词汇表大小在30,000到50,000之间。

  • Token IDs:因此,句子“Hello, how are you?”可能会被分词为[101, 7592, 1010, 2129, 2024, 2017, 1029, 102],其中每个数字对应一个词汇或标点的唯一ID。
  • Shape:输入序列的形状通常是(batch_size, sequence_length),其中batch_size是一次输入的序列数量,sequence_length是每个序列的长度。

2. 输入嵌入(Input Embedding)

嵌入层是一个查找表,将每个token ID映射到一个固定维度的向量表示。例如,对于词汇表大小为vocab_size,嵌入维度为embedding_dim,嵌入层是一个形状为(vocab_size, embedding_dim)的矩阵。

  • Shape:形状为(batch_size, sequence_length, embedding_dim),这是通过将Token IDs通过嵌入层(embedding layer)转换得到的。

3. 位置编码(Positional Encoding)

  • Purpose:因为Transformer没有内置的顺序信息,位置编码被添加到输入的token嵌入中,以引入序列的顺序信息。
  • Shape:形状为(sequence_length, embedding_dim),位置编码会与输入嵌入相加。
    在实际操作中,位置编码通常会扩展维度,使其形状为(1, sequence_length, embedding_dim),这样可以方便地与输入嵌入进行广播相加。

4. 注意力掩码(Attention Mask)

  • Purpose:掩码用于指示哪些位置的token应该被注意力机制忽略(例如,填充token)。
  • Shape:形状通常是(batch_size, sequence_length),每个位置上是0或1。

5. 目标序列(Target Sequence,解码器输入)

  • Token IDs:对于训练解码器时,目标序列也会被转化为token IDs,形状类似于输入序列。
  • Shape:形状通常是(batch_size, target_sequence_length)。

输出

1. 编码器输出(Encoder Output)

  • Contextualized Representations:编码器输出每个输入token的上下文表示,是一个三维张量。
  • Shape:通常是(batch_size, sequence_length, hidden_size),其中hidden_size是编码器的隐藏层大小。

2. 解码器输出(Decoder Output)

  • Logits:解码器在每个时间步输出的是未归一化的概率分布,即logits。
  • Shape:形状通常是(batch_size, target_sequence_length, vocab_size),vocab_size是词汇表的大小。

3. 注意力权重(Attention Weights)

  • Attention Scores:有时我们需要注意力机制的权重,表示模型在每个时间步对输入序列中每个位置的关注程度。
  • Shape:通常是(batch_size, num_heads, sequence_length, sequence_length),其中num_heads是多头注意力机制的头数。

Transformer的结构

编码器(Encoder)

  • 输入嵌入(Input Embedding):将输入token IDs转化为嵌入向量。
  • 位置编码(Positional Encoding):将位置编码添加到嵌入向量中。
  • 多头自注意力机制(Multi-head Self Attention):每个token与其他token进行交互以获得上下文表示。
  • 前馈神经网络(Feed-forward Neural Network):非线性变换每个位置的表示。
  • 层归一化(Layer Normalization)和残差连接(Residual Connection):提高训练稳定性和深度表示。

解码器(Decoder)

  • 输入嵌入和位置编码:与编码器类似,但输入是目标序列。
  • 多头自注意力机制:处理目标序列自身的依赖关系。
  • 编码器-解码器注意力(Encoder-Decoder Attention):将编码器的上下文表示整合到解码器中。
  • 前馈神经网络:类似于编码器。
  • 输出层(Output Layer):生成词汇表中每个词的概率分布。

Transformer的工作流程

  1. 编码器处理输入序列

    • 将输入token IDs通过嵌入层转化为嵌入向量,并添加位置编码。
    • 多头自注意力机制计算每个位置的上下文表示。
    • 前馈神经网络对上下文表示进行变换。
  2. 解码器生成输出序列

    • 解码器接收目标序列的前缀(训练时是完整的目标序列,推理时是已经生成的部分)。
    • 多头自注意力机制处理目标序列自身的依赖关系。
    • 编码器-解码器注意力将编码器的输出整合到解码器中。
    • 前馈神经网络对解码器的表示进行变换,生成logits。
    • 通过softmax层将logits转化为概率分布。

这种结构使得Transformer能够高效地处理长序列并捕捉远距离依赖关系,成为目前许多NLP任务的首选模型架构。
下面是一个简化的Transformer模型的编码器和解码器的实现代码,使用了PyTorch框架。这段代码实现了一个基础的Transformer架构,包括编码器和解码器部分。

Transformer编码器和解码器代码

import torch
import torch.nn as nn
import torch.nn.functional as F
import math# 定义位置编码类
class PositionalEncoding(nn.Module):def __init__(self, d_model, max_len=5000):super(PositionalEncoding, self).__init__()self.pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))self.pe[:, 0::2] = torch.sin(position * div_term)self.pe[:, 1::2] = torch.cos(position * div_term)self.pe = self.pe.unsqueeze(0).transpose(0, 1)def forward(self, x):return x + self.pe[:x.size(0), :]# 定义编码器层类
class EncoderLayer(nn.Module):def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):super(EncoderLayer, self).__init__()self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)self.linear1 = nn.Linear(d_model, dim_feedforward)self.dropout = nn.Dropout(dropout)self.linear2 = nn.Linear(dim_feedforward, d_model)self.norm1 = nn.LayerNorm(d_model)self.norm2 = nn.LayerNorm(d_model)self.dropout1 = nn.Dropout(dropout)self.dropout2 = nn.Dropout(dropout)def forward(self, src, src_mask=None, src_key_padding_mask=None):src2 = self.self_attn(src, src, src, attn_mask=src_mask, key_padding_mask=src_key_padding_mask)[0]src = src + self.dropout1(src2)src = self.norm1(src)src2 = self.linear2(self.dropout(F.relu(self.linear1(src))))src = src + self.dropout2(src2)src = self.norm2(src)return src# 定义编码器类
class Encoder(nn.Module):def __init__(self, num_layers, d_model, nhead, dim_feedforward=2048, dropout=0.1):super(Encoder, self).__init__()self.layers = nn.ModuleList([EncoderLayer(d_model, nhead, dim_feedforward, dropout) for _ in range(num_layers)])self.norm = nn.LayerNorm(d_model)def forward(self, src, mask=None, src_key_padding_mask=None):for layer in self.layers:src = layer(src, src_mask=mask, src_key_padding_mask=src_key_padding_mask)return self.norm(src)# 定义解码器层类
class DecoderLayer(nn.Module):def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):super(DecoderLayer, self).__init__()self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)self.multihead_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)self.linear1 = nn.Linear(d_model, dim_feedforward)self.dropout = nn.Dropout(dropout)self.linear2 = nn.Linear(dim_feedforward, d_model)self.norm1 = nn.LayerNorm(d_model)self.norm2 = nn.LayerNorm(d_model)self.norm3 = nn.LayerNorm(d_model)self.dropout1 = nn.Dropout(dropout)self.dropout2 = nn.Dropout(dropout)self.dropout3 = nn.Dropout(dropout)def forward(self, tgt, memory, tgt_mask=None, memory_mask=None, tgt_key_padding_mask=None, memory_key_padding_mask=None):tgt2 = self.self_attn(tgt, tgt, tgt, attn_mask=tgt_mask, key_padding_mask=tgt_key_padding_mask)[0]tgt = tgt + self.dropout1(tgt2)tgt = self.norm1(tgt)tgt2 = self.multihead_attn(tgt, memory, memory, attn_mask=memory_mask, key_padding_mask=memory_key_padding_mask)[0]tgt = tgt + self.dropout2(tgt2)tgt = self.norm2(tgt)tgt2 = self.linear2(self.dropout(F.relu(self.linear1(tgt))))tgt = tgt + self.dropout3(tgt2)tgt = self.norm3(tgt)return tgt# 定义解码器类
class Decoder(nn.Module):def __init__(self, num_layers, d_model, nhead, dim_feedforward=2048, dropout=0.1):super(Decoder, self).__init__()self.layers = nn.ModuleList([DecoderLayer(d_model, nhead, dim_feedforward, dropout) for _ in range(num_layers)])self.norm = nn.LayerNorm(d_model)def forward(self, tgt, memory, tgt_mask=None, memory_mask=None, tgt_key_padding_mask=None, memory_key_padding_mask=None):for layer in self.layers:tgt = layer(tgt, memory, tgt_mask=tgt_mask, memory_mask=memory_mask, tgt_key_padding_mask=tgt_key_padding_mask, memory_key_padding_mask=memory_key_padding_mask)return self.norm(tgt)# 定义完整的Transformer模型
class Transformer(nn.Module):def __init__(self, src_vocab_size, tgt_vocab_size, d_model=512, nhead=8, num_encoder_layers=6, num_decoder_layers=6, dim_feedforward=2048, dropout=0.1, max_len=5000):super(Transformer, self).__init__()self.src_embedding = nn.Embedding(src_vocab_size, d_model)self.tgt_embedding = nn.Embedding(tgt_vocab_size, d_model)self.positional_encoding = PositionalEncoding(d_model, max_len)self.encoder = Encoder(num_encoder_layers, d_model, nhead, dim_feedforward, dropout)self.decoder = Decoder(num_decoder_layers, d_model, nhead, dim_feedforward, dropout)self.fc_out = nn.Linear(d_model, tgt_vocab_size)def forward(self, src, tgt, src_mask=None, tgt_mask=None, src_key_padding_mask=None, tgt_key_padding_mask=None):src_embedded = self.positional_encoding(self.src_embedding(src))tgt_embedded = self.positional_encoding(self.tgt_embedding(tgt))memory = self.encoder(src_embedded, mask=src_mask, src_key_padding_mask=src_key_padding_mask)output = self.decoder(tgt_embedded, memory, tgt_mask=tgt_mask, memory_mask=src_mask, tgt_key_padding_mask=tgt_key_padding_mask, memory_key_padding_mask=src_key_padding_mask)return self.fc_out(output)# 示例用法
# 假设我们有源语言和目标语言的词汇表大小分别为SRC_VOCAB_SIZE和TGT_VOCAB_SIZE
SRC_VOCAB_SIZE = 10000
TGT_VOCAB_SIZE = 10000
src = torch.randint(0, SRC_VOCAB_SIZE, (10, 32))  # (序列长度, 批次大小)
tgt = torch.randint(0, TGT_VOCAB_SIZE, (20, 32))  # (序列长度, 批次大小)model = Transformer(SRC_VOCAB_SIZE, TGT_VOCAB_SIZE)
output = model(src, tgt)
print(output.shape)  # 输出形状应该为 (目标序列长度, 批次大小, 目标词汇表大小)

代码说明

  • PositionalEncoding:位置编码,用于给序列中每个标记提供位置信息。
  • EncoderLayer:编码器层,包含一个多头自注意力层和一个前馈神经网络。
  • Encoder:编码器,由多个编码器层堆叠而成。
  • DecoderLayer:解码器层,包含一个自注意力层、一个交叉注意力层和一个前馈神经网络。
  • Decoder:解码器,由多个解码器层堆叠而成。
  • Transformer:完整的Transformer模型,包括嵌入层、位置编码、编码器和解码器,以及最终的线性层用于生成输出。

示例用法

代码示例展示了如何初始化Transformer模型,并用随机生成的源序列和目标序列进行前向传播。输出的形状应该为[目标序列长度, 批次大小, 目标词汇表大小]。

这个实现是基础版本,实际应用中可能需要更多的细节处理,如掩码的正确设置、优化器和损失函数的定义等。

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

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

相关文章

Maven学习——Maven的下载、安装与配置(详细攻略!)

目录 前言 1.下载与安装 2.配置Maven的环境变量 3.配置Maven的本地仓库 4. 配置Maven的镜像远程仓库 前言 我在之前写了一篇博客,是介绍Maven的基本概念和下载安装,但是由于篇幅过长,Maven的下载与安装写的并不详细🐶&#x…

TCP三次握手与四次挥手详解

1.什么是TCP TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议,属于互联网协议族(TCP/IP)的一部分。TCP 提供可靠的、顺序的、无差错的数据传输服务&…

TeamViewer手机端APP提示:请先验证账户

当你在手机端下载安装了TeamViewerAPP后,需要你先登录个人账号,然后还会要求你验证账户,同时跳转到一个网址中,但是这个网址并没有自动跳转到验证账户的位置。 解决办法: 在手机浏览器中进入下面这个网址:…

SpringCloudAlibaba-Seata2.0.0与Nacos2.2.1

一、下载 ## 下载seata wget https://github.com/apache/incubator-seata/releases/download/v2.0.0/seata-server-2.0.0.tar.gz## 解压 tar zxvf seata-server-2.0.0.tar.gz二、执行sql文件 ## 取出sql文件执行 cd /seata/script/server/db/mysql ## 找个mysql数据库执行三、…

分布式搜索引擎ES-elasticsearch入门

1.分布式搜索引擎:luceneVS Solr VS Elasticsearch 什么是分布式搜索引擎 搜索引擎:数据源:数据库或者爬虫资源 分布式存储与搜索:多个节点组成的服务,提高扩展性(扩展成集群) 使用搜索引擎为搜索提供服务。可以从海量…

算法基础之回溯法

本文将详细介绍回溯法的基本原理和适用条件,并通过经典例题辅助读者理解回溯法的思想、掌握回溯法的使用。本文给出的例题包括:N皇后问题、子集和问题。 算法原理 在问题的解空间树中,回溯法按照深度优先的搜索策略,从根结点出发…

IP溯源工具--IPTraceabilityTool

工具地址:xingyunsec/IPTraceabilityTool: 蓝队值守利器-IP溯源工具 (github.com) 工具介绍: 在攻防演练期间,对于值守人员,某些客户要求对攻击IP都进行分析溯源,发现攻击IP的时候,需要针对攻击IP进行分析…

Hive理论讲解

Hive介绍 1、Hive本质 Hive本质是【数仓设计方案】,hive本身并不存储数据【数据包含:元数据 (表)数据】。 2、hql和sql对比 sql 结构化查询语言【structured query language】hql hive/hadoop类sql查询语言【hive/hadoop query language like sql…

Python学习笔记40:游戏篇之外星人入侵(一)

前言 入门知识已经学完,常用标准库也了解了,pygame入门知识也学了,那么开始尝试小游戏的开发。 当然这个小游戏属于比较简单的小游戏,复杂的游戏需要长时间的编写累计开发经验,同时也需要一定的时间才能编写出来。现在的话还是嫩…

2024年7月16日(使用光盘创建本地仓库,引入网络镜像仓库,创建自建仓库)

了解yum源安装包的特点 了解常用的网络yum源 掌握本地和网络yum源的配置 能够使用yum工具安装软件包 rpm -ivh xxx 手动添加依赖 yum不止执行安装,会自动处理依赖安装 1、yum优点 rpm安装 (下载软件 单独安装 需要解决依赖关系) 源码安装 &am…

海外媒体发稿-瑞典SEO破茧成蝶:从0到10的实战精要-大舍传媒

海外媒体发稿-瑞典SEO破茧成蝶:从0到10的实战精要 一、迷茫与意义的探寻 有一天我找了王老师聊天,谈到生活迷茫和人生的意义。老师说了一段话:当全情投入于一件事情时,是没有时间去迷茫或思索人生意义的。我感触很深,当总感到迷…

linux服务器配置conda环境安装教程

1 软件准备 1.1 软件下载 https://repo.anaconda.com/archive/index.html 根据官网选择自己需要的版本。 这里下载的是 Anaconda3-2023.03-1-Linux-x86_64.sh 或者直接在linux中输入 wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh 1.…

操作系统内核源码杂谈篇:临界区

临界资源,是指同一时刻只能由一个线程(linux下为进程)访问的资源,而临界区就是为了确保临界资源访问是单一数据流。 临界区的代码执行,也就是进行原子操作,不会被打断。 先分析RTOS的运行架构&#xff0c…

Paypal个人支付申请及沙箱测试配置

目录 一. 申请paypal账号二. Sanbox 测试配置申请买家Account申请卖家AccountSandbox的Client ID及密钥申请Live的Client ID及密钥申请IPN回调设置 一. 申请paypal账号 浏览器输入https://www.paypal.com, 单击注册按钮 2. 我这里申请个人账户,如果你需要企业账户&…

AI绘画入门实践|Midjourney 的模型版本

模型分类 Midjourney 的模型主要分为2大类: 默认模型:目前包括:V1, V2, V3, V4, V5.0, V5.1, V5.2, V6 NIJI模型:目前包括:NIJI V4, NIJI V5, NIJI V6 模型切换 你在服务器输入框中输入 /settings: 回车后…

【深度学习驱动智能超材料设计与应用】

在深度学习与超材料融合的背景下,不仅提高了设计的效率和质量,还为实现定制化和精准化的治疗提供了可能,展现了在材料科学领域的巨大潜力。深度学习可以帮助实现超材料结构参数的优化、电磁响应的预测、拓扑结构的自动设计、相位的预测及结构…

抖音矩阵系统源码开发部署流程分享

#短视频矩阵源码 #短视频矩阵 #源码交付 抖音矩阵系统源码开发部署流程如下: 环境配置:首先,需要安装并配置开发环境,包括安装Java JDK、MySQL数据库、Eclipse开发工具等。 数据库设计:根据抖音矩阵系统的需求&…

【数字IC/FPGA】书籍推荐(2)----《那些年,我们拿下了FPGA》

在下这几年关于数字电路、Verilog、FPGA和IC方面的书前前后后都读了不少,发现了不少好书,也在一些废话书上浪费过时间。接下来会写一系列文章,把一部分读过的书做个测评,根据个人标准按十分制满分来打分分享给大家。 概述 &#x…

【C语言】全面解析冒泡排序

文章目录 什么是冒泡排序?冒泡排序的基本实现代码解释冒泡排序的优化冒泡排序的性能分析冒泡排序的实际应用结论 在C语言编程中,排序算法是一个非常基础且重要的概念。冒泡排序作为最简单、最易理解的排序算法之一,广泛应用于各种编程教学和实…

在VS Code上搭建Vue项目教程(Vue-cli 脚手架)

1.前期环境准备 搭建Vue项目使用的是Vue-cli 脚手架。前期环境需要准备Node.js环境,就像Java开发要依赖JDK环境一样。 1.1 Node.js环境配置 1)具体安装步骤操作即可: npm 安装教程_如何安装npm-CSDN博客文章浏览阅读836次。本文主要在Win…