深度学习理论基础(七)Transformer编码器和解码器

学习目录:

深度学习理论基础(一)Python及Torch基础篇
深度学习理论基础(二)深度神经网络DNN
深度学习理论基础(三)封装数据集及手写数字识别
深度学习理论基础(四)Parser命令行参数模块
深度学习理论基础(五)卷积神经网络CNN
深度学习理论基础(六)Transformer多头自注意力机制
深度学习理论基础(七)Transformer编码器和解码器

本文目录

  • 学习目录:
  • 前述: Transformer总体结构框图
  • 一、编码器encoder
    • 1. 编码器作用
    • 2. 编码器部分
      • (1)单个编码器层代码
      • (2)编码器总体代码
  • 二、解码器decoder
    • 1. 解码器作用
    • 2. 解码器部分
      • (1)单个解码器层代码
      • (2)解码器总体代码
  • 三、Transformer
    • 1. 框图
    • 2. 代码

  

前述: Transformer总体结构框图

在这里插入图片描述
(1)嵌入层:编码器的输入是一系列的词嵌入(Word Embeddings),它将文本中的每个词映射到一个高维空间中的向量表示。
  嵌入层的作用是将离散符号转换为连续的向量表示,降低数据维度同时保留语义信息,提供词语的上下文信息以及初始化模型参数,从而为深度学习模型提供了有效的输入表示。

class Embedder(nn.Module):def __init__(self, vocab_size, d_model):super().__init__()self.d_model = d_modelself.embed = nn.Embedding(vocab_size, d_model)def forward(self, x):return self.embed(x)

(2)位置编码器:为了使 Transformer 能够处理序列信息,位置编码被引入到词嵌入中,以区分不同位置的词。通常使用正弦和余弦函数来生成位置编码。
  一句话中同一个词,如果词语出现位置不同,意思可能发生翻天覆地的变化,就比如:我爱你 和 你爱我。这两句话的意思完全不一样。可见获取词语出现在句子中的位置信息是一件很重要的事情。但是Transformer 的是完全基于self-Attention地,而self-attention是不能获取词语位置信息的,就算打乱一句话中词语的位置,每个词还是能与其他词之间计算attention值,就相当于是一个功能强大的词袋模型,对结果没有任何影响。所以在我们输入的时候需要给每一个词向量添加位置编码。
   位置编码是通过在输入序列的每个位置上添加一个与位置相关的固定向量来实现的。这个向量会在前向传播过程中与输入的词嵌入向量相加,以产生具有位置信息的新的向量表示。

●公式:
在这里插入图片描述
PE:表示位置编码矩阵,可先使用 torch.zeros(行,列) 创建一个全0的矩阵,然后再通过操作将其中的某些元素赋值,形成含有位置信息的矩阵。
pos:表示输入序列所在行的位置。范围0~输入序列矩阵行长度。
d_model :输入、输出向量的维度大小。
i:取值范围为 [ 0, d_model] ,但每次移动步长为2。 因为当 i 为偶数时,使用sin函数,当 i 为奇数时,使用cos函数。

●代码:

class PositionalEncoder(nn.Module):def __init__(self, d_model, max_seq_len = 200, dropout = 0.1):super().__init__()self.d_model = d_model   #输入维度self.dropout = nn.Dropout(dropout)pe = torch.zeros(max_seq_len, d_model)  # 创建一个形状为 (max_seq_len, d_model) 的位置编码矩阵,元素权威0for pos in range(max_seq_len):for i in range(0, d_model, 2):pe[pos, i]     = math.sin(pos / (10000 ** ((2 * i)/d_model)))pe[pos, i + 1] = math.cos(pos / (10000 ** ((2 * i)/d_model)))pe = pe.unsqueeze(0)   # 在第0维度上添加一个维度,变成 (1, max_seq_len, d_model)# PE位置编码矩阵其中的元素修改好后,可以注册位置编码矩阵为模型的 buffer,即封装起来。self.register_buffer('pe', pe) def forward(self, x):# 将输入乘以一个与模型维度相关的缩放因子x = x * math.sqrt(self.d_model)# 将位置编码添加到输入中seq_len = x.size(1)pe = self.pe[:, :seq_len].clone().detach()  # 从缓冲区中获取位置编码if x.is_cuda:pe = pe.cuda()  # 将位置编码移到GPU上,如果输入张量也在GPU上x = x + pe         # 输入向量,加上位置编码器。return self.dropout(x)   # 加上丢弃层,防止过拟合。

(3)多头注意力层:这是编码器的核心组件之一。它允许模型在输入序列中学习词与词之间的依赖关系,通过计算每个词对其他词的注意力权重来实现。多头机制允许模型在不同的表示空间中并行地学习多种关注方向。多头注意力层详情查看地址!

def attention(q, k, v, d_k, mask=None, dropout=None): scores = torch.matmul(q, k.transpose(-2, -1)) /  math.sqrt(d_k)if mask is not None:mask = mask.unsqueeze(1)scores = scores.masked_fill(mask == 0, -1e9)   scores = F.softmax(scores, dim=-1)if dropout is not None:scores = dropout(scores)output = torch.matmul(scores, v)return outputclass MultiHeadAttention(nn.Module):def __init__(self, heads, d_model, dropout = 0.1):super().__init__()self.d_model = d_model  #输入向量的维度self.d_k = d_model // headsself.h = headsself.q_linear = nn.Linear(d_model, d_model)self.k_linear = nn.Linear(d_model, d_model)self.v_linear = nn.Linear(d_model, d_model)self.dropout = nn.Dropout(dropout)self.out = nn.Linear(d_model, d_model)def forward(self, q, k, v, mask=None):bs = q.size(0)# perform linear operation and split into N headsq = self.q_linear(q).view(bs, -1, self.h, self.d_k)k = self.k_linear(k).view(bs, -1, self.h, self.d_k) v = self.v_linear(v).view(bs, -1, self.h, self.d_k)# transpose to get dimensions bs * N * sl * d_modelk = k.transpose(1,2)q = q.transpose(1,2)v = v.transpose(1,2)scores = attention(q, k, v, self.d_k, mask, self.dropout)concat = scores.transpose(1,2).contiguous().view(bs, -1, self.d_model)output = self.out(concat)return outputif __name__ == '__main__':  heads = 8d_model = 64# 创建输入张量 x2 和 mask# 假设 x2 和 mask 的形状为 [batch_size, seq_len, embedding_dim]batch_size = 16seq_len = 10embedding_dim = d_modelx2 = torch.randn(batch_size, seq_len, embedding_dim)mask = torch.zeros(batch_size, seq_len)  # 假设没有特殊的 mask# 实例化 MultiHeadAttention 模型attn = MultiHeadAttention(heads, d_model, dropout=0.1)# 使用 MultiHeadAttention 进行前向传播output = attn(x2, x2, x2, mask)print(output.shape)  # 输出张量的形状

(4) 残差连接与规范化层:在多头自注意力层之后,通常会添加残差连接和规范化层来加速训练和提高模型稳定性。残差连接主要是保存原图信息,防止过拟合

"""规范化层"""
class Norm(nn.Module):def __init__(self, d_model, eps = 1e-6):super().__init__()self.size = d_model# create two learnable parameters to calibrate normalisationself.alpha = nn.Parameter(torch.ones(self.size))self.bias = nn.Parameter(torch.zeros(self.size))self.eps = epsdef forward(self, x):norm = self.alpha * (x - x.mean(dim=-1, keepdim=True)) \/ (x.std(dim=-1, keepdim=True) + self.eps) + self.biasreturn norm

(5) 前馈全连接层:在多头自注意力层之后,还有一个前馈全连接层,它对每个位置的词向量进行非线性变换和映射。

class FeedForward(nn.Module):def __init__(self, d_model, d_ff=2048, dropout = 0.1):super().__init__() # We set d_ff as a default to 2048self.linear_1 = nn.Linear(d_model, d_ff)self.dropout = nn.Dropout(dropout)self.linear_2 = nn.Linear(d_ff, d_model)def forward(self, x):x = self.dropout(F.relu(self.linear_1(x)))x = self.linear_2(x)return x

  

一、编码器encoder

1. 编码器作用

  编码器的作用是将输入序列转换为语义表示,学习输入序列中词与词之间的依赖关系,并提取输入序列的特征表示,为解码器生成目标序列提供有用的信息。
在这里插入图片描述

2. 编码器部分

(1)单个编码器层代码

在这里插入图片描述

class EncoderLayer(nn.Module):def __init__(self, d_model, heads, dropout=0.1):super().__init__()self.norm_1 = Norm(d_model)  #定义规范化层self.norm_2 = Norm(d_model)self.attn = MultiHeadAttention(heads, d_model, dropout=dropout) #定义多头注意力层self.ff = FeedForward(d_model, dropout=dropout)   #前馈全连接层self.dropout_1 = nn.Dropout(dropout)   #丢弃层self.dropout_2 = nn.Dropout(dropout)def forward(self, x, mask):x2 = self.norm_1(x)x = x + self.dropout_1(self.attn(x2,x2,x2,mask))    #残差连接,注意力中qkv全部来自自身。x2 = self.norm_2(x)x = x + self.dropout_2(self.ff(x2))return x    

(2)编码器总体代码

这里需要将上述的编码器层进行克隆复制n份。
在这里插入图片描述

 """编码器总体""   #克隆多层编码器层  def get_clones(module, N):return nn.ModuleList([copy.deepcopy(module) for i in range(N)])class Encoder(nn.Module):def __init__(self, vocab_size, d_model, N, heads, dropout):super().__init__()self.N = N      #n个编码器层self.embed = Embedder(vocab_size, d_model)    #嵌入层self.pe = PositionalEncoder(d_model, dropout=dropout)   #位置编码self.layers = get_clones(EncoderLayer(d_model, heads, dropout), N) #复制n个编码器层self.norm = Norm(d_model)  #规范化层def forward(self, src, mask):x = self.embed(src)x = self.pe(x)for i in range(self.N):x = self.layers[i](x, mask)return self.norm(x)

  

二、解码器decoder

1. 解码器作用

在这里插入图片描述

2. 解码器部分

(1)单个解码器层代码

在这里插入图片描述

class DecoderLayer(nn.Module):def __init__(self, d_model, heads, dropout=0.1):super().__init__()self.norm_1 = Norm(d_model)   #定义规范化层self.norm_2 = Norm(d_model)self.norm_3 = Norm(d_model)self.dropout_1 = nn.Dropout(dropout)  #定义丢弃层self.dropout_2 = nn.Dropout(dropout)self.dropout_3 = nn.Dropout(dropout)self.attn_1 = MultiHeadAttention(heads, d_model, dropout=dropout)  #多头注意力层self.attn_2 = MultiHeadAttention(heads, d_model, dropout=dropout)self.ff = FeedForward(d_model, dropout=dropout)  #前馈全连接层def forward(self, x, e_outputs, src_mask, trg_mask):x2 = self.norm_1(x)x = x + self.dropout_1(self.attn_1(x2, x2, x2, trg_mask))x2 = self.norm_2(x)x = x + self.dropout_2(self.attn_2(x2, e_outputs, e_outputs, \src_mask))x2 = self.norm_3(x)x = x + self.dropout_3(self.ff(x2))return x

  

(2)解码器总体代码

在这里插入图片描述

def get_clones(module, N):return nn.ModuleList([copy.deepcopy(module) for i in range(N)])class Decoder(nn.Module):def __init__(self, vocab_size, d_model, N, heads, dropout):super().__init__()self.N = Nself.embed = Embedder(vocab_size, d_model)   #嵌入层self.pe = PositionalEncoder(d_model, dropout=dropout) #位置编码self.layers = get_clones(DecoderLayer(d_model, heads, dropout), N) #复制n层解码器层self.norm = Norm(d_model)  #规范化层def forward(self, trg, e_outputs, src_mask, trg_mask):x = self.embed(trg)  x = self.pe(x)for i in range(self.N):x = self.layers[i](x, e_outputs, src_mask, trg_mask)return self.norm(x)

  

三、Transformer

1. 框图

在这里插入图片描述

2. 代码

class Transformer(nn.Module):def __init__(self, src_vocab, trg_vocab, d_model, N, heads, dropout):super().__init__()self.encoder = Encoder(src_vocab, d_model, N, heads, dropout)  #编码器总体self.decoder = Decoder(trg_vocab, d_model, N, heads, dropout)  #解码器总体self.out = nn.Linear(d_model, trg_vocab)  #全连接层输出def forward(self, src, trg, src_mask, trg_mask):e_outputs = self.encoder(src, src_mask) d_output = self.decoder(trg, e_outputs, src_mask, trg_mask)output = self.out(d_output)return outputmodle=Transformer()

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

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

相关文章

手机软件何时统一--桥接模式

1.1 凭什么你的游戏我不能玩 2007年苹果手机尚未出世,机操作系统多种多样(黑莓、塞班、Tizen等),互相封闭。而如今,存世的手机操作系统只剩下苹果OS和安卓,鸿蒙正在稳步进场。 1.2 紧耦合的程序演化 手机…

vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户

1.后端返回的json数据结构为: {"message":"下载失败,下载文件不存在,请联系管理员处理!","code":500} 2.vue 请求后台接口返回的 Blob数据 3.问题出现的原因是,正常其他数据列表接口&…

[C++][算法基础]堆排序(堆)

输入一个长度为 n 的整数数列,从小到大输出前 m 小的数。 输入格式 第一行包含整数 n 和 m。 第二行包含 n 个整数,表示整数数列。 输出格式 共一行,包含 m 个整数,表示整数数列中前 m 小的数。 数据范围 1≤m≤n≤&#x…

第4章 Redis,一站式高性能存储方案,笔记问题

点赞具体要实现功能有哪些? 可以点赞的地方:对帖子点赞,对评论点赞点一次是点赞,再点一次是取消赞统计点赞的数量(计数,string),帖子被点赞的数量,某个用户被点赞的数量…

【数据结构】考研真题攻克与重点知识点剖析 - 第 5 篇:树与二叉树

(考研真题待更新) 欢迎订阅专栏:408直通车 请注意,本文中的部分内容来自网络搜集和个人实践,如有任何错误,请随时向我们提出批评和指正。本文仅供学习和交流使用,不涉及任何商业目的。如果因本…

2024免费Mac电脑用户的系统清理和优化软件CleanMyMac

作为产品营销专家,对于各类产品的特性与优势有着深入的了解。CleanMyMac是一款针对Mac电脑用户的系统清理和优化软件,旨在帮助用户轻松管理、优化和保护Mac电脑。以下是关于CleanMyMac的详细介绍: CleanMyMac X2024全新版下载如下: https://…

阿里云乱扣费故障,技术堪忧

2024年4月3日,距离2023年11月的故障没有多久,阿里云又出现乱扣费故障,导致账号欠费3000多,oss,块存储,cdn等所有后付费服务停止工作,不知道这个故障能算什么级别的。 凌晨1点多,收到…

用Vue全家桶手工搓了一个类似抖音短视频的软件,全开源

用Vue全家桶手工搓了一个类似抖音短视频的软件,全开源 软件简介 用Vue全家桶手工搓了一个高仿抖音,全开源 PC浏览器请用手机模式访问。先按F12调出控制台,再按CtrlShiftM切换到手机模式,手机请用Via浏览器或者Chrome浏览器预览。…

Octopus V2:设备端super agent的高级语言模型

论文:Octopus v2: On-device language model for super agent论文地址:https://arxiv.org/abs/2404.01744模型主页:https://huggingface.co/NexaAIDev/Octopus-v2 Octopus-V2-2B Octopus-V2-2B 是一款具有20亿参数的开源先进语言模型&#…

性能分析-docker知识

docker的相关概念 docker是一个做系统虚拟化的软件,跟vmware类似,虚拟出来的也是操作系统。我们现在在企业中, 使用docker虚拟出来的系统,大多都是linux系统。 docker镜像image:就是虚拟一个docker容器需要的操作系统…

Ubuntu 20.04.06 PCL C++学习记录(十八)

[TOC]PCL中点云分割模块的学习 学习背景 参考书籍:《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,,PCL版本为1.10.0,CMake版本为3.16 学习内容 PCL中实现欧式聚类提取。在点云处理中,聚类是一种常见的任务,它将点云数据划分为多…

基于单片机三相温度测量控制系统设计

**单片机设计介绍,基于单片机三相温度测量控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机三相温度测量控制系统设计概要主要包括系统组成、温度测量原理、控制逻辑、软件设计以及测试与验证等…

2.k8s架构

目录 k8s集群架构 控制平面 kube-apiserver kube-scheduler etcd kube-controller-manager node 组件 kubelet kube-proxy 容器运行时(Container Runtime) cloud-controller-manager 相关概念 k8s集群架构 一个Kubernetes集群至少包含一个控制…

PPT 操作

版式 PPT中,巧妙使用母版,可以提高效率。 双击母版,选择其中一个版式,插入装饰符号。 然后选择关闭。 这个时候,在该版式下的所有页面,就会出现新加入的符号。不在该版式下的页面,不会出现新加…

八股面试——数据库——索引

索引的概念 B树的概念: 索引的作用 聚簇索引与非聚簇索引 聚簇索引就是主键值,在B树上,通过主键大小(数据在B树叶子节点按主键顺序排序)寻找对应的叶子节点,叶子节点保存的一整条记录。 非聚簇索引&#x…

ctfshow web入门 命令执行 web53--web77

web53 日常查看文件 怎么回事不让我看十八 弄了半天发现并不是很对劲,原来我发现他会先回显我输入的命令再进行命令的回显 ?cnl${IFS}flag.php||web54 绕过了很多东西 基本上没有什么命令可以用了但是 grep和?通配符还可以用 ?cgrep${IFS}ctfshow${IFS}???…

分类预测 | Matlab实现ABC-LSSVM人工蜂群算法优化最小二乘支持向量机数据分类预测

分类预测 | Matlab实现ABC-LSSVM人工蜂群算法优化最小二乘支持向量机数据分类预测 目录 分类预测 | Matlab实现ABC-LSSVM人工蜂群算法优化最小二乘支持向量机数据分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现ABC-LSSVM人工蜂群算法优化最小二乘支…

BeautifulSoup数据抓取优化

优化 BeautifulSoup 数据抓取可以帮助提高数据抓取的效率和性能,优化的数据抓取方式更加友好,减少了对目标网站的访问压力,降低了被封禁或限制访问的风险。那边在日常中会遇到一些复杂的问题,如何解决?看看下面的几种解…

【C++】详解vector二维数组的全部操作(超细图例解析!!!)

目录 一、前言 二、 深度理解vector 的二维数组(重点!) 三、vector 二维数组的空间理解(重点!) ✨问题分析 ✨如何合理定制vector的内存空间 四、vector 二维数组的初始化 五、vector 二维数组的 添加…

性能优化 - 你能说一说,为什么做了骨架屏,FCP的指标还是没有提升吗

难度级别:中高级及以上 提问概率:80% FCP的全程是First Contentful Paint,是衡量网页性能的一个重要指标,很多人把FCP理解为元素内容首次渲染到浏览器上的时间。但由于现在比较流行的Vue或是React项目中,HTML文档最初只有一个id为app的DIV…