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://xiahunao.cn/news/3250577.html

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

相关文章

数据结构-java中链表的存储原理及使用方式

目录 链表(线性表的链式存储) 代码实例:(链表构建,头插尾插) LinkedList LinkedList的使用: 1、构造方法 2、操作方法 LinkedList 和 ArrayList 的区别 链表(线性表的链式存储…

C语言 ——— 输入两个正整数,求出最小公倍数

目录 何为最小公倍数 题目要求 代码实现 方法一:暴力求解法(不推荐) 方法二:递乘试摸法(推荐) 何为最小公倍数 最小公倍数是指两个或者多个正整数(除了0以外)的最小的公共倍数…

吴恩达深度学习笔记:机器学习策略(2)(ML Strategy (2)) 2.9-2.10

目录 第三门课 结构化机器学习项目(Structuring Machine Learning Projects)第二周:机器学习策略(2)(ML Strategy (2))2.9 什么是端到端的深度学习?(What is end-to-end deep learning?&#x…

【matlab 投影寻踪】基于PSO算法的最优投影方向优化

一 投影寻踪算法 投影寻踪是处理和分析高维数据的一类统计方法,其基本思想是将高维数据投影到低维(1~3维)子空间上,寻找出反映原高维数据的结构或特征的投影,以达到研究和分析高维数据的目的。1974年&…

深度学习中的正则化技术 - Dropout篇

序言 在深度学习的浩瀚领域中,模型过拟合一直是研究者们面临的挑战之一。当模型在训练集上表现得近乎完美,却难以在未见过的数据(测试集)上保持同样优异的性能时,过拟合现象便悄然发生。为了有效缓解这一问题&#xf…

java文本比较解决方案

参考资料 VBA计算页码和行号https://learn.microsoft.com/zh-cn/office/vba/api/word.wdinformation 概述: 最近在做word文档对比的,总结了几种解决方案,记录一下 在java中,常用的文本对比方案有如下几种: 差异比较…

Pycharm 报错 Environment location directory is not empty 解

删除项目中ven文件夹(已存在的),然后再添加新的ven虚拟环境就可以了

Richteck立锜科技电源管理芯片简介及器件选择指南

一、电源管理简介 电源管理组件的选择和应用本身的电源输入和输出条件是高度关联的。 输入电源是交流或直流?需求的输出电压比输入电压高或是低?负载电流多大?系统是否对噪讯非常敏感?也许系统需要的是恒流而不是稳压 (例如 LED…

入门C语言只需一个星期(星期三)

点击上方"蓝字"关注我们 01、基本数据类型 char 1 字节 −128 ~ 127 单个字符/字母/数字/ASCIIsigned char 1 字节 −128 ~ 127 -unsigned char 1 字节 0 ~ 255 -int…

【自学安全防御】三、企业双机热备和带宽管理的综合实验

实验拓扑: 实验任务: 12,对现有网络进行改造升级,将当个防火墙组网改成双机热备的组网形式,做负载分担模式,游客区和DMZ区走FW3,生产区和办公区的流量走FW1 13,办公区上网用户限制流…

JavaSE 知识梳理(上)

1. Java语言的特性 简单性、面向对象、分布式、健壮性、安全性、体系结构中立、可移植性、解释性、高能效、多线程、动态性 2. JDK、JRE、JVM之间的关系 JDK(Java Development Kit):Java开发工具包,提供给Java程序员使用,包含了JRE,同时还…

使用Pycharm画图展示在窗口的侧栏Plots中无图像问题

使用Pycharm画图展示在窗口的侧栏Plots中无图像问题 在运行一个python文件时,突然出现侧栏Plots处提供预览的哪里没有出现图片,只有空白。解决方法如下: 找到Tools -> Python Plots,下图,取消勾选use interactive…

django报错(二):NotSupportedError:MySQL 8 or later is required (found 5.7.43)

执行python manage.py runserver命令时报版本不支持错误,显示“MySQL 8 or later is required (found 5.7.43)”。如图: 即要MySQL 8或更高版本。但是企业大所数用的还是mysql5.7相关版本。因为5.7之后的8.x版本是付费版本,贸然更新数据库肯定…

WEB前端07-DOM对象

DOM模型 1.DOM概念 文档对象模型属于BOM的一 部分,用于对BOM中的核心对象document进行操作,它是一种与平台、语言无关的接口,允许程序和脚本动态地访问或更新HTML、XML文档的内容、结构和样式,且提供了一系列的函数和对象来实现…

Vue从零到实战基础篇

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

C语言丢失精度 如何实现高精度计算

(1)int 类型举例 int :占4个字节,也就是32位,及最大值是2^32-11024*1024*1024*4-14294967295 以上说法错误,因为Int是有符号类型整数,所以最高位是符号位,及int的最大值应该是2^31…

spring是如何解决循环依赖的,为什么不是两级

1. Spring使用三级缓存来解决循环依赖问题 Spring使用三级缓存来解决循环依赖问题,‌而不是使用两级缓存。‌ 在Spring框架中,‌解决循环依赖的关键在于正确地管理Bean的生命周期和依赖关系。‌循环依赖指的是两个或多个Bean相互依赖,‌如果…

VC运营指南:提升亚马逊VC账户销量的策略——WAYLI威利跨境助力商家

亚马逊VC作为供应商中心账户,其运营策略与普通的第三方卖家账户有所不同。想要在此平台上取得卓越的销售业绩,需要深入理解和运用一系列策略。 1、产品策略是基石 深入市场研究,了解消费者的真实需求,是选择产品的关键。只有选对…

vue echarts 柱状图表,点击柱子,路由代参数(X轴坐标)跳转

一 myChart.on(click, (params) > {if (params.componentType series && params.dataIndex ! undefined) {const months this.month_htqd[params.dataIndex]; // 获取点击柱状图的 X 轴坐标值alert(点击了柱状图,值为: ${months});// 根据点击的柱状图…

7.SpringBoot整合Neo4j

1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-neo4j</artifactId> </dependency> 说明&#xff1a;这里引入neo4j的版本跟spring框架的版本有关系。需要注意不同的版本在neo…