transformer--解码器

在编码器中实现了编码器的各种组件,其实解码器中使用的也是这些组件,如下图:

解码器组成部分:

  1. 由N个解码器层堆叠而成
  2. 每个解码器层由三个子层连接结构组成
  3. 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接
  4. 第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接
  5. 第三个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接 

解码器层code

# 解码器层的类实现
class DecoderLayer(nn.Module):def __init__(self, size, self_attn, src_attn, feed_forward,dropout) -> None:"""size : 词嵌入维度self_attn:多头自注意对象,需要Q=K=Vsrc_attn:多头注意力对象,这里Q!=K=Vfeed_forward: 前馈全连接层对象"""super(DecoderLayer,self).__init__()self.size = sizeself.self_attn = self_attnself.src_attn = src_attnself.feed_forward = feed_forward# 根据论文图使用clones克隆三个子层对象self.sublayer = clones(SublayerConnection(size,dropout), 3)def forward(self, x, memory, source_mask, target_mask):"""x : 上一层的输入memory: 来自编码器层的语义存储变量source_mask: 源码数据掩码张量,针对就是输入到解码器的数据target_mask: 目标数据掩码张量,针对解码器最后生成的数据,一个一个的推理生成的词"""m = memory# 将x传入第一个子层结构,第一个子层结构输入分别是x和self_attn函数,因为是自注意力机制,所以Q=K=V=x# 最后一个参数是目标数据掩码张量,这时要对目标数据进行掩码,因为此时模型可能还没有生成任何目标数据,# 比如在解码器准备生成第一个字符或词汇时,我们其实已经传入第一个字符以便计算损失# 但是我们不希望在生成第一个字符时模型能利用这个信息,因为我们会将其遮掩,同样生成第二个字符或词汇时# 模型只能使用第一个字符或词汇信息,第二个字符以及以后得信息都不允许被模型使用x = self.sublayer[0](x, lambda x: self.self_attn(x,x,x,target_mask))# 紧接着第一层的输出进入第二个子层,这个子层是常规的注意力机制,但是q是输入x;k、v是编码层输出memory# 同样也传入source_mask, 但是进行源数据遮掩的原因并非是抑制信息泄露,而是遮蔽掉对结果没有意义的的字符而产生的注意力# 以此提升模型的效果和训练速度,这样就完成第二个子层的处理x = self.sublayer[1](x, lambda x: self.src_attn(x,m,m,source_mask))# 最后一个子层就是前馈全连接子层,经过他的处理后就可以返回结果,这就是解码器层的结构return self.sublayer[2](x,self.feed_forward)

测试代码全放到最后

测试结果:

embr.shape =  torch.Size([2, 4, 512])
pe_result.shape =  torch.Size([2, 4, 512])
en_result.shape :  torch.Size([2, 4, 512])
en_result :  tensor([[[-1.0392, -1.2399, -0.0508,  ..., -0.0731,  0.0161,  0.1734],[ 0.4218, -0.8372,  0.0657,  ...,  1.1024, -0.0273,  0.0458],[ 1.1038,  0.7187, -0.4767,  ...,  0.0396,  0.4021, -0.2545],[-0.4050,  0.2746,  0.2608,  ..., -0.0969,  0.1556,  0.7639]],[[ 1.1785,  0.7174, -0.4660,  ..., -0.7642,  0.2084, -0.2262],[-0.2988,  0.7209,  0.1552,  ..., -0.4515,  0.2163, -0.5891],[-0.6027, -0.3825, -0.2690,  ...,  2.3163,  0.3059, -1.7363],[-0.5485, -1.7348,  0.5710,  ..., -1.8011, -3.2616,  0.6475]]],grad_fn=<AddBackward0>)
dl_result.shape =  torch.Size([2, 4, 512])
dl_result =  tensor([[[-23.0521, -28.3426,  -0.5458,  ...,  -6.1061,  -0.1419,   5.0221],[ 11.1962, -23.1371,  -0.3318,  ...,  24.4704,  -0.2596,   0.3329],[ 22.7772,  15.4876, -13.8883,  ...,  -0.7536,   6.2517,  -6.4530],[ -8.6034,   5.9488,   4.5170,  ...,  -1.7604,   3.1385,  18.6994]],[[ 20.9259,  18.1934, -13.7914,  ..., -18.0120,   0.2210,  -6.3908],[ -9.2162,  19.0768,  -0.3693,  ..., -11.8371,   5.5636, -15.0215],[-14.9818,  -8.8418,  -8.3098,  ...,  61.9500,   3.2425, -43.5170],[-16.1407, -38.8550,  10.6465,  ..., -44.7966, -83.8235,  12.7915]]],grad_fn=<AddBackward0>)

解码器

解码器的作用:根据编码器的结果以及上一次预测的结果,对下一次可能出现的值进行特征表示

# 解码器
class Decoder(nn.Module):def __init__(self,layer,N) -> None:""" layer: 解码器层, N:解码器层的个数"""super(Decoder,self).__init__()self.layers = clones(layer,N)self.norm = LayerNorm(layer.size)def forward(self, x, memory,source_mask, target_mask):# x:目标数据的嵌入表示# memory:编码器的输出# source_mask: 源数据的掩码张量# target_mask: 目标数据的掩码张量for layre in self.layers:x = layer(x,memory,source_mask,target_mask)return self.norm(x)

测试代码放到最后代码

结果:

de_result.shape :  torch.Size([2, 4, 512])
de_result :  tensor([[[-0.0569,  0.3506, -0.4071,  ..., -1.0797,  0.4819,  1.5599],[ 0.2342,  0.0497,  0.8868,  ...,  1.8162,  0.1724, -0.0384],[-0.0438, -0.8501,  1.2952,  ...,  0.5489,  0.1530,  1.2819],[-2.7741,  0.4939,  1.5461,  ..., -0.7539,  0.6964, -0.4137]],[[ 1.1773, -0.7767,  1.2400,  ...,  0.4109, -0.0105,  1.3137],[ 0.0067, -0.5182,  0.1695,  ..., -1.0328, -1.6252,  1.3039],[-0.8350, -0.8536, -0.4261,  ..., -1.2965,  0.1531,  0.2299],[-0.2015,  0.5470, -0.9219,  ..., -0.1534,  1.3922, -0.2488]]],grad_fn=<AddBackward0>)

输出部分

线性层的作用:

通过对上一步的线性变化得到指定维度的输出,也就是转换维度的作用,

softmax层的作用:

使最后一维的向量中的数字缩放到0-1的概率值域内,并满足他们的和为1 

 code

# 输出
class Generator(nn.Module):def __init__(self,d_mode, vocab_size) -> None:"""d_mode: 词嵌入vocab_size: 词表大小"""super(Generator,self).__init__()self.project = nn.Linear(d_mode, vocab_size)def forward(self, x):return F.log_softmax(self.project(x),dim=-1)

输出:

gen_result.shape : torch.Size([2, 4, 1000])
gen_result:  tensor([[[-7.3236, -6.3419, -6.6023,  ..., -6.8704, -6.2303, -6.9161],[-7.3549, -7.2196, -8.2483,  ..., -6.5249, -6.9905, -6.4151],[-6.7272, -6.5778, -7.1534,  ..., -6.3917, -7.4114, -6.7917],[-6.7106, -7.3387, -7.4814,  ..., -6.7696, -6.8284, -7.5407]],[[-7.0403, -6.6602, -6.6994,  ..., -6.5930, -7.5068, -7.0125],[-6.4951, -7.2265, -7.4753,  ..., -7.0645, -7.2771, -7.2495],[-7.5860, -7.3894, -8.1477,  ..., -6.7407, -6.4232, -8.4255],[-7.4713, -6.9773, -7.0890,  ..., -7.6705, -7.1161, -7.3006]]],grad_fn=<LogSoftmaxBackward0>)

测试代码 


import numpy as np
import torch
import torch.nn.functional as F
import torch.nn as nn
import matplotlib.pyplot as plt
import math
import copy 
from inputs import Embeddings,PositionalEncoding
from encode import  subsequent_mask,attention,clones,MultiHeadedAttention,PositionwiseFeedForward,LayerNorm,SublayerConnection,Encoder,EncoderLayer
# encode 代码在前面几节# 解码器层的类实现
class DecoderLayer(nn.Module):def __init__(self, size, self_attn, src_attn, feed_forward,dropout) -> None:"""size : 词嵌入维度self_attn:多头自注意对象,需要Q=K=Vsrc_attn:多头注意力对象,这里Q!=K=Vfeed_forward: 前馈全连接层对象"""super(DecoderLayer,self).__init__()self.size = sizeself.self_attn = self_attnself.src_attn = src_attnself.feed_forward = feed_forward# 根据论文图使用clones克隆三个子层对象self.sublayer = clones(SublayerConnection(size,dropout), 3)def forward(self, x, memory, source_mask, target_mask):"""x : 上一层的输入memory: 来自编码器层的语义存储变量source_mask: 源码数据掩码张量,针对就是输入到解码器的数据target_mask: 目标数据掩码张量,针对解码器最后生成的数据,一个一个的推理生成的词"""m = memory# 将x传入第一个子层结构,第一个子层结构输入分别是x和self_attn函数,因为是自注意力机制,所以Q=K=V=x# 最后一个参数是目标数据掩码张量,这时要对目标数据进行掩码,因为此时模型可能还没有生成任何目标数据,# 比如在解码器准备生成第一个字符或词汇时,我们其实已经传入第一个字符以便计算损失# 但是我们不希望在生成第一个字符时模型能利用这个信息,因为我们会将其遮掩,同样生成第二个字符或词汇时# 模型只能使用第一个字符或词汇信息,第二个字符以及以后得信息都不允许被模型使用x = self.sublayer[0](x, lambda x: self.self_attn(x,x,x,target_mask))# 紧接着第一层的输出进入第二个子层,这个子层是常规的注意力机制,但是q是输入x;k、v是编码层输出memory# 同样也传入source_mask, 但是进行源数据遮掩的原因并非是抑制信息泄露,而是遮蔽掉对结果没有意义的的字符而产生的注意力# 以此提升模型的效果和训练速度,这样就完成第二个子层的处理x = self.sublayer[1](x, lambda x: self.src_attn(x,m,m,source_mask))# 最后一个子层就是前馈全连接子层,经过他的处理后就可以返回结果,这就是解码器层的结构return self.sublayer[2](x,self.feed_forward)# 解码器
class Decoder(nn.Module):def __init__(self,layer,N) -> None:""" layer: 解码器层, N:解码器层的个数"""super(Decoder,self).__init__()self.layers = clones(layer,N)self.norm = LayerNorm(layer.size)def forward(self, x, memory,source_mask, target_mask):# x:目标数据的嵌入表示# memory:编码器的输出# source_mask: 源数据的掩码张量# target_mask: 目标数据的掩码张量for layre in self.layers:x = layer(x,memory,source_mask,target_mask)return self.norm(x)# 输出
class Generator(nn.Module):def __init__(self,d_mode, vocab_size) -> None:"""d_mode: 词嵌入vocab_size: 词表大小"""super(Generator,self).__init__()self.project = nn.Linear(d_mode, vocab_size)def forward(self, x):return F.log_softmax(self.project(x),dim=-1)if __name__ == "__main__":# 词嵌入dim = 512vocab  =1000emb = Embeddings(dim,vocab)x = torch.LongTensor([[100,2,321,508],[321,234,456,324]])embr  =emb(x)print("embr.shape = ",embr.shape)# 位置编码pe = PositionalEncoding(dim,0.1) # 位置向量的维度是20,dropout是0pe_result = pe(embr)print("pe_result.shape = ",pe_result.shape)# 编码器测试size = 512dropout=0.2head=8d_model=512d_ff = 64c = copy.deepcopyx = pe_resultself_attn = MultiHeadedAttention(head,d_model,dropout)ff = PositionwiseFeedForward(d_model,d_ff,dropout)# 编码器层不是共享的,因此需要深度拷贝layer= EncoderLayer(size,c(self_attn),c(ff),dropout)N=8mask = torch.zeros(8,4,4)en = Encoder(layer,N)en_result = en(x,mask)print("en_result.shape : ",en_result.shape)print("en_result : ",en_result)# 解码器层测试size = 512dropout=0.2head=8d_model=512d_ff = 64self_attn = src_attn = MultiHeadedAttention(head,d_model,dropout)ff = PositionwiseFeedForward(d_model,d_ff,dropout)x = pe_resultmask = torch.zeros(8,4,4)source_mask = target_mask = maskmemory = en_resultdl = DecoderLayer(size,self_attn,src_attn,ff,dropout)dl_result = dl(x,memory,source_mask,target_mask)print("dl_result.shape = ", dl_result.shape)print("dl_result = ", dl_result)# 解码器测试size = 512dropout=0.2head=8d_model=512d_ff = 64memory = en_resultc = copy.deepcopyx = pe_resultself_attn = MultiHeadedAttention(head,d_model,dropout)ff = PositionwiseFeedForward(d_model,d_ff,dropout)# 编码器层不是共享的,因此需要深度拷贝layer= DecoderLayer(size,c(self_attn),c(self_attn),c(ff),dropout)N=8mask = torch.zeros(8,4,4)source_mask = target_mask = maskde = Decoder(layer,N)de_result = de(x,memory,source_mask, target_mask)print("de_result.shape : ",de_result.shape)print("de_result : ",de_result)# 输出测试d_model = 512vocab =1000x = de_resultgen = Generator(d_mode=d_model,vocab_size=vocab)gen_result = gen(x)print("gen_result.shape :", gen_result.shape)print("gen_result: ", gen_result)

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

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

相关文章

小巧且强大,一键批量操作谁不爱?

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; 两款Office批量打印工具展现了优秀的人性化设计&#xff1a;其界面清晰、操作简便。这些工具支持Word、Excel、PPT等多种文档格式进行批量打印&#…

VMware虚拟机安装linux教程

CentOS7下载 下载 (centos.org)https://www.centos.org/download/新建虚拟机 选择自定义安装 这里要注意兼容性&#xff0c;如果是VMware12创建的虚拟机复制到VM11、10或者更低的版本会出现一不兼容的现象。如果是用VMware10创建的虚拟机在VMware12中打开则不会出现兼容性问题…

vue中使用echarts实现人体动态图

最近一直处于开发大屏的项目&#xff0c;在开发中遇到了一个小知识点&#xff0c;在大屏中如何实现人体动态图。然后看了下echarts官方文档&#xff0c;根据文档中的示例调整出来自己想要的效果。 根据文档上发现 series 中 type 类型设置为 象形柱形图&#xff0c;象形柱图是…

SpringCloud之Nacos入门与实战系列

目录 一、Nacos介绍 1.1、配置中心和注册中心的概念 1.2 Nacos 优点 二、Nacos的使用 2.1 以单机模式启动Nacos 2.2 Nacos部署方式介绍 2.3 配置数据源 2.4 开启控制台权限登录 三、配置中心的使用 3.1 创建配置信息 3.2 SpringBoot使用配置中心 四、注册中心的使用 4…

图书推荐|Word文稿之美

让你的文档从平凡到出众&#xff01; 本书内容 《Word文稿之美》是一本全面介绍Word排版技巧和应用的实用指南。从初步认识数字排版到高效利用模板、图文配置和表格与图表的排版技巧&#xff0c;再到快速修正错误和保护文件&#xff0c;全面系统地讲解数字排版的技术和能力&…

基于Docker部署本地ChatGPT环境

基于Docker部署本地ChatGPT环境 一、拉取镜像 docker pull pengzhile/pandora二、运行镜像 docker run -e PANDORA_CLOUDcloud -e PANDORA_SERVER0.0.0.0:8899 -p 8899:8899 -d pengzhile/pandora三、查看容器是否启动成功 docker ps四、登录 http://IP:8899 这里有两种方…

ssm+springboot音乐播放器网站mybatis+jsp

测试流程 &#xff08;1&#xff09; 登录系统、填写用户名、密码选择角色&#xff0c;主要内容&#xff1a;进行权限控制。 &#xff08;2&#xff09; 用户查看音乐信息、音乐资讯功能&#xff0c;主要是测试系统实用性、方便性。 &#xff08;3&#xff09; 信息修…

【C++】类和对象之初始化列表与static成员

个人主页 &#xff1a; zxctscl 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 再谈构造函数2.1 构造函数体赋值2.2 初始化列表2.3 explicit关键字 3. static成员3.1 概念3.2 特性 1. 前言 在前面的博客中已经分享有关构造函数 【C】构造函数和…

9.WEB渗透测试-Linux基础知识-Linux用户权限管理(上)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;8.WEB渗透测试-Linux基础知识-Linux基础操作&#xff08;二&#xff09;-CSDN博客 用户管…

uniapp实现进度条组件

首先&#xff0c;在uniapp项目中创建一个自定义组件&#xff0c;可以命名为Progress.vue。在Progress.vue中&#xff0c;编写如下代码&#xff1a; <template><view class"progress"><view class"progress-bar" :style"{width: progr…

缓存淘汰策略看完这篇就够了

LFU 缓存淘汰算法 LFU 是 Least Frequently Used 的缩写&#xff0c;即 最少使用 缓存淘汰算法。LFU算法根据数据项在缓存中的访问频率来决定淘汰哪些数据项。访问频率越高 的数据项被认为是更重要的&#xff0c;访问频率越低 的数据项被认为是更不重要的。 LFU算法的具体工作原…

Kali Linux 2024.1

Kali Linux 2024.1刚刚发布&#xff0c;标志着这个备受欢迎的安全重点Linux发行版在今年的首次重大更新。以其先进的渗透测试和安全审计功能而闻名&#xff0c;它是安全专业人员和爱好者的首选工具。 Kali 2024.1 亮点 本次发布由 Linux 内核 6.6 提供支持&#xff0c;突出了…

C语言qsort函数介绍

前言 学到了函数指针&#xff0c;那这篇博客我们可以根据函数指针&#xff0c;了解一个函数qsort的应用与模拟实现 欢迎关注个人主页&#xff1a;小张同学zkf 若有疑问 评论区见 目录 1.回调函数 2.qsort函数使用 3.qsort模拟实现 1.回调函数 讲这个东西之前我们来认识一下…

mq基础类设计

消息队列就是把阻塞队列这样的数据结构单独提取成一个程序独立进行部署。——>实现生产者消费者模型。 但是阻塞队列是在一个进程内部进行的&#xff1b; 消息队列是在进程与进程之间进行实现的&#xff0c; 解耦合&#xff1a;就是在分布式系统中&#xff0c;A服务器调用B…

Tomcat -2

① 单机反向代理 7-2 代理服务器 7-5 tomcat 设置 7-3 测试&#xff1a; 代理服务器那里写什么就显示什么 ② 多机反向代理 实现动静分离和负载均衡 7-2 nginx 7-3 7-5 测试&#xff1a; 看静态&#xff1a; 看动态&#xff1a; ③ 反向代理多机多级 7-2 7-1 和 7-4 7-3…

【STM32】STM32学习笔记-读写内部FLASH 读取芯片ID(49)

00. 目录 文章目录 00. 目录01. FLASH概述02. 读写内部FLASH接线图03. 读写内部FLASH相关API04. 读写内部FLASH程序示例05. 读写芯片ID接线图06. 读写芯片ID程序示例07. 程序示例下载08. 附录 01. FLASH概述 STM32F10xxx内嵌的闪存存储器可以用于在线编程(ICP)或在程序中编程(…

华为OD机试 - 数字排列 - 深度优先搜索dfs算法(Java 2024 C卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出3、说明 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&a…

外部存储器接口(EMIF)

外部存储器接口&#xff08;EMIF&#xff09; 该设备支持双核架构&#xff1b;为了为每个CPU子系统提供一个专用的EMIF&#xff0c;该设备支持两个EMIF模块——EMIF1和EMIF2。两个模块完全相同&#xff0c;具有相同的功能集&#xff0c;但具有不同的地址/数据大小。EMIF1在CPU…

Unity 角色控制(初版)

角色控制器组件&#xff0c;当然是将组件放在角色上了。 using System.Collections; using System.Collections.Generic; using UnityEngine;public class c1 : MonoBehaviour {// 获取角色控制器private CharacterController player;void Start(){// 加载角色控制器player …

机器学习 | 模型性能评估

目录 一. 回归模型的性能评估1. 平均平方误差(MSE)2. 平均绝对误差(MAE)3. R 2 R^{2} R2 值3.1 R 2 R^{2} R2优点 二. 分类模型的性能评估1. 准确率&#xff08;Accuracy&#xff09;2. 召回率&#xff08;Recall&#xff09;3. 精确率&#xff08;Precision&#xff09;4. …