Transformer总结

1.Transform背景介绍

1.1Transform的优势

相比于之前占领市场的LSTM和GRU模型,Transformer有两个显著的优势:

(1)Transform能够使用分布式GPU进行并行训练,提升模型训练效率

(2) 在分析预测更长的文本时,捕捉间隔较长的语义关联效果更好

2.认识Transformer架构

2.1Transfromer模型的作用

1.基于seq2seq架构的Transform模型可以完成nlp领域研究的典型任务,如机器翻译,文本生成等,同时有可以构建预训练语言模型,用于不同任务的迁移学习

2.在接下来的架构分析中,我们将假设使用Transformer模型处理从一种语言文本到另一种语言文本的翻译工作,因此很多命名方式遵循nlp中的规则,比如:Embedding层称为文本嵌入层,Embedding层产生的张量称为词嵌入张量,它的最后一维将称作词向量等

2.2Transfromer总体架构图

2.3Transformer组成结构分析

​​​​​​3.输入部分实现

3.1输入部分组成

源文本嵌入层以及位置编码器

目标文本嵌入层以及位置编码器

3.2文本嵌入层的作用

无论是原文本嵌入还是目标文本嵌入,都是为了将文本中词汇的数字表示转变为向量表示,希望在这样的高维空间捕捉词汇间的关系

文本嵌入层代码

import torch
import torch.nn as nn
import math
from torch.autograd import Variableclass Embeddings(nn.Module):def __init__(self, d_model, vocab):super(Embeddings, self).__init__()# 参数d_model  每个词汇的特征尺寸  词嵌入维度# 参数vocab  词汇表大小self.d_model = d_modelself.vocab = vocabself.lut = nn.Embedding(self.vocab, self.d_model)def forward(self, x):return self.lut(x) * math.sqrt(self.d_model)# embedding = nn.Embedding(10, 3)
# input = torch.LongTensor([[1, 2, 4, 5], [4, 3, 2, 9]])
# print(embedding(input))
# embedding = nn.Embedding(10, 3, padding_idx=0)
# input = torch.LongTensor([0, 2, 0, 5])
# print(embedding(input))
# 调用
def dm_test_Embeddings():d_model = 512vocab = 1000my_embeddings = Embeddings(d_model, vocab)x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))embed = my_embeddings(x)print('embed.shape',embed.shape,'\nembed--->\n',embed)
#dm_test_Embeddings()

3.3位置编码器

位置编码器的作用:在Transformer的编码器结构中,并没有针对词汇位置信息的处理,因此需要再Embedding层后加入位置编码器,将词汇位置不同可能会产生的不同语义的信息加入到词嵌入张量中,以弥补位置信息的缺失

位置编码器代码

import torch
import torch.nn as nn
import math
from torch.autograd import Variable
from 文本嵌入层 import Embeddingsclass PositionalEncoding(nn.Module):def __init__(self, d_model, dropout, max_len=5000):# 参数d_model 词嵌入维度 eg: 512个特征# 参数max_len 单词token个数 eg: 60个单词super(PositionalEncoding, self).__init__()# 定义dropout层self.dropout = nn.Dropout(p=dropout)# 思路:位置编码矩阵 + 特征矩阵 相当于给特征增加了位置信息# 定义位置编码矩阵PE eg pe[60, 512], 位置编码矩阵和特征矩阵形状是一样的pe = torch.zeros(max_len, d_model)# 定义位置列-矩阵position  数据形状[max_len,1] eg: [0,1,2,3,4...60]^Tposition = torch.arange(0, max_len).unsqueeze(1)# print('position--->', position.shape, position)# 定义变化矩阵div_term [1,256]# torch.arange(start=1, end=512, 2)结果并不包含end。在start和end之间做一个等差数组 [0, 2, 4, 6 ... 510]div_term = torch.exp(torch.arange(0, d_model, 2) * -(math.log(10000.0) / d_model))# 位置列-矩阵 @ 变化矩阵 做矩阵运算 [60*1]@ [1*256] ==> 60 *256# 矩阵相乘也就是行列对应位置相乘再相加,其含义,给每一个列属性(列特征)增加位置编码信息my_matmulres = position * div_term# print('my_matmulres--->', my_matmulres.shape, my_matmulres)# 给位置编码矩阵奇数列,赋值sin曲线特征pe[:, 0::2] = torch.sin(my_matmulres)# 给位置编码矩阵偶数列,赋值cos曲线特征pe[:, 1::2] = torch.cos(my_matmulres)# 形状变化 [60,512]-->[1,60,512]pe = pe.unsqueeze(0)# 把pe位置编码矩阵 注册成模型的持久缓冲区buffer; 模型保存再加载时,可以根模型参数一样,一同被加载# 什么是buffer: 对模型效果有帮助的,但是却不是模型结构中超参数或者参数,不参与模型训练self.register_buffer('pe', pe)def forward(self, x):# 注意:输入的x形状2*4*512  pe是1*60*512 形状 如何进行相加# 只需按照x的单词个数 给特征增加位置信息x = x + Variable(self.pe[:, :x.size()[1]], requires_grad=False)return self.dropout(x)# 调用
def dm_test_PositionalEncoding():d_model = 512vocab = 1000# 实例化词嵌入层my_embeddings = Embeddings(d_model, vocab)x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))embed = my_embeddings(x)my_pe = PositionalEncoding(d_model=d_model, dropout=0.1, max_len=60)# 给词嵌入数据embed 添加位置特征pe_result = my_pe(embed)print('pe_result.shape--->', pe_result.shape)print('pe_result--->', pe_result)
dm_test_PositionalEncoding()

3.4绘制词汇向量中特征的分布曲线

代码

import matplotlib.pyplot as plt
import numpy as np
import torch
from torch.autograd import Variablefrom 位置编码器 import PositionalEncoding# 绘制PE位置特征sin-cos曲线
def dm_draw_PE_feature():my_pe = PositionalEncoding(d_model=20, dropout=0)print('my_positionalencoding.shape-->', my_pe.pe.shape)y = my_pe(Variable(torch.zeros(1, 100, 20)))print('y-->', y.shape)plt.figure(figsize=(20, 20))plt.plot(np.arange(100), y[0, :, 4:8].numpy())plt.legend(['dim %d' %p for p in [4, 5, 6, 7]])plt.show()
dm_draw_PE_feature()

4.编码器部分的实现

4.1编码器介绍

编码器部分:由N个编码器层堆叠而成,每个编码器层由两个子层连接结构组成。第一个子层连接结构包括一个多头自注意力子层,规范化层和一个残差连接层,第二个子层连接结构包括一个前馈全连接层,规范化层和一个残差连接层

4.2掩码张量的介绍

掩码张量的作用:掩码的作用就是让另外一个张量的一些数值被遮掩

4.3掩码张量函数

掩码张量函数:subsquent_mask

它的输入是size,代表掩码张量的大小

它的输出是一个下三角阵

4.4注意力机制

注意力计算规则:Attention(Q,K,V)=Softmax(Q⋅KT/√dk)⋅V

注意力计算规则的代码分析

import math
import torch
import torch.nn.functional as F
from torch.autograd import Variable
from 文本嵌入层 import Embeddings
from 位置编码器 import PositionalEncodingdef attention(query, key, value, mask=None, dropout=None):d_k = query.size()[-1]scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k)if mask is not None:scores = scores.masked_fill(mask == 0, -1e9)p_attn = F.softmax(scores, dim=-1)if dropout is not None:p_attn = dropout(p_attn)return torch.matmul(p_attn, value), p_attn# 调用
def dm_test_attention():d_model = 512vocab = 1000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))my_embeddings = Embeddings(d_model, vocab)x = my_embeddings(x)drop_out = 0.1max_len = 60my_pe = PositionalEncoding(d_model, drop_out, max_len)pe_result = my_pe(x)query = key = value = pe_resultatten1, patten1 = attention(query, key, value)print("编码阶段,对注意力权重不做掩码")print("atten1--->", atten1.shape, '\n', atten1)print("patten1-->", patten1.shape, '\n', patten1)print('*' * 50)print("编码阶段,对注意力权重做掩码")mask = Variable(torch.zeros(2, 4, 4))atten2,patten2=attention(query,key,value,mask=mask)print("atten2-->",atten2.shape,'\n',atten2)print("patten2-->",patten2.shape,'\n',patten2)
dm_test_attention()

4.5多头注意力机制

1.多头注意力机制的概念

对三个变换张量Q,K,V分别进行线性变换,这些变换不会改变原有张量的尺寸,因此每个变换矩阵都是方阵,得到输出结果后,多头的作用才开始显现,每个头开始从词义层面分割输出的张量,也就是每个头都想获得一组Q,K,V来进行注意力机制的计算,但句子中的每个词的表示只获得一部分,也就是只分割了最后一维的词嵌入向量,这就是所谓的多头,将每个头获得的输入送到注意力机制中,就形成了多头注意力机制

2.多头注意力机制的作用

这种结构设计能够让每个注意力机制去优化每个词汇的不同特征部分,从而均衡同一种注意力机制可能产生的偏差,让词义拥有来自更多元的表达,实验表明可以从而提升模型效果

3.多头注意力机制的代码实现

import copy
import torch
import torch.nn as nn
from 注意力机制 import attention
from torch.autograd import Variable
from 文本嵌入层 import Embeddings
from 位置编码器 import PositionalEncodingdef clones(moudle, N):return nn.ModuleList([copy.deepcopy(moudle) for _ in range(N)])class MultiHeadAttention(nn.Module):def __init__(self, head, embedding_dim, dropout=0.1):super(MultiHeadAttention, self).__init__()assert embedding_dim % head == 0self.d_k = embedding_dim // headself.head = headself.linears = clones(nn.Linear(embedding_dim, embedding_dim), 4)self.attn = Noneself.dropout = nn.Dropout(p=dropout)def forward(self, query, key, value, mask=None):if mask is not None:mask = mask.unsqueeze(0)batch_size = query.size()[0]query, key, value = [model(x).view(batch_size, -1, self.head, self.d_k).transpose(1, 2)for model, x in zip(self.linears, (query, key, value))]x, self.attn = attention(query, key, value, mask=mask, dropout=self.dropout)x = x.transpose(1, 2).contiguous().view(batch_size, -1, self.head * self.d_k)return self.linears[-1](x)# 测试多头注意力机制
def dm_test_MultiHeadedAttention():d_model = 512vocab = 1000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))my_embeddings = Embeddings(d_model, vocab)x = my_embeddings(x)dropout = 0.1max_len = 60my_pe = PositionalEncoding(d_model, dropout, max_len)pe_result = my_pe(x)head = 8query = key = value = pe_result#输入的掩码张量maskmask = Variable(torch.zeros(8, 4, 4))my_mha = MultiHeadAttention(head, d_model, dropout)x = my_mha(query, key, value, mask)print('多头注意力机制后的x',x.shape,'\n',x)print('多头注意力机制的注意力权重分布',my_mha.attn.shape)dm_test_MultiHeadedAttention()

4.6前馈全连接层

1.概念:在Transformer中,前馈全连接层就是具有两层线性层的全连接网络

2.前馈全连接层的作用:考虑注意力机制可能对复杂过程的拟合程度不够,通过增加两层网络来增强模型的能力

前馈全连接层代码:

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
from 多头注意力机制 import MultiHeadAttention
from 位置编码器 import PositionalEncoding
from  文本嵌入层 import  Embeddingsclass PositionwiseFeedForward(nn.Module):def __init__(self, d_model, d_ff, dropput=0.1):super(PositionwiseFeedForward, self).__init__()self.w1 = nn.Linear(d_model, d_ff)self.w2 = nn.Linear(d_ff, d_model)self.dropout = nn.Dropout(p=dropput)def forward(self, x):return self.w2(self.dropout(F.relu(self.w1(x))))# 函数调用
def dm_test_PositionwiseFeedForward():d_model = 512vocab = 10000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))my_embeddings = Embeddings(d_model, vocab)x = my_embeddings(x)dropout = 0.1max_len = 60my_pe = PositionalEncoding(d_model, dropout, max_len)pe_result = my_pe(x)head = 8query = key = value = pe_result# 输入掩码张量maskmask = Variable(torch.zeros(8, 4, 4))my_mha = MultiHeadAttention(head, d_model, dropout)x = my_mha(query, key, value, mask)# 测试前馈全连接层my_PFF = PositionwiseFeedForward(d_model=512, d_ff=64, dropput=0.1)ff_result = my_PFF(x)print('x_result--->',ff_result.shape,'\n',ff_result)
dm_test_PositionwiseFeedForward()

4.7规范化层

1.规范化层的作用

它是所有深层网络都需要的标准网络层,因为随着网络层数的增加,通过多层的计算后参数可能出现过大或者过小的情况,这样可能导致学习过程出现异常,模型可能收敛的非常慢,因此都会在一定层数后接规范化层进行数值的规范化,使其特征数值在合理范围内

import torch.nn as nn
import torch
from torch.autograd import Variable
from 文本嵌入层 import Embeddings
from 注意力机制 import PositionalEncoding
from 多头注意力机制 import MultiHeadAttention
from 前馈全连接层 import PositionwiseFeedForwardclass LayerNorm(nn.Module):def __init__(self, features, eps=1e-6):super(LayerNorm, self).__init__()self.a2 = nn.Parameter(torch.ones(features))self.b2 = nn.Parameter(torch.zeros(features))self.eps = epsdef forward(self, x):mean = x.mean(-1, keepdims=True)std = x.std(-1, keepdims=True)# 对数据进行标准化转换y = self.a2 * (x - mean) / (std + self.eps) + self.b2return y# 函数调用
def dm_test_LayerNorm():embedding_dim = 512vocab = 1000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))emb = Embeddings(embedding_dim, vocab)embr = emb(x)dropout = 0.2max_len = 60x = embrpe = PositionalEncoding(embedding_dim, dropout, max_len)pe_result = pe(x)query = key = value = pe_result# 调用验证d_ff = 64head = 8# 多头注意力机制的输出  作为前馈全连接层的输入mask = Variable(torch.zeros(8, 4, 4))mha = MultiHeadAttention(head, embedding_dim, dropout)mha_result = mha(query, key, value, mask)x = mha_resultff = PositionwiseFeedForward(embedding_dim, d_ff, dropout)ff_result = ff(x)features = d_model = 512eps = 1e-6x = ff_resultln = LayerNorm(features, eps)ln_result = ln(x)print('规范化层:',ln_result.shape,'\n',ln_result)dm_test_LayerNorm()

4.8子层连接结构

概念:输入到子层以及规范化层的过程中还使用了残差连接(跳跃连接),因此我们把这一部分结构整体叫作子层连接,在每个编码器层中都有两个子层,这两个子层加上周围的连接结构就形成了两个子层连接结构

子层连接结构代码:

import torch
import torch.nn as nn
from 规范化层 import LayerNorm
from torch.autograd import Variable
from 文本嵌入层 import Embeddings
from 多头注意力机制 import PositionalEncoding
from 多头注意力机制 import MultiHeadAttentionclass SublayerConnection(nn.Module):def __init__(self, size, dropout=0.1):super(SublayerConnection, self).__init__()# 定义norm层self.norm = LayerNorm(size)# 定义dropoutself.dropout = nn.Dropout(dropout)def forward(self, x, sublayer):myres = x + self.dropout(sublayer(self.norm(x)))return myres# 函数调用
def dm_test_SublayerConnection():size = 512head = 8d_model = 512vocab = 1000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))emb = Embeddings(d_model, vocab)embr = emb(x)dropout = 0.2max_len = 60x = embrpe = PositionalEncoding(d_model, dropout, max_len)pe_result = pe(x)x = pe_resultmask = Variable(torch.zeros(8, 4, 4))# 多头自注意力子层self_attn = MultiHeadAttention(head, d_model)sublayer = lambda x: self_attn(x, x, x, mask)# 子层链接结构sc = SublayerConnection(size, dropout)sc_result = sc(x, sublayer)print('sc_result.shape--->', sc_result.shape)print('sc_result-->', sc_result)
dm_test_SublayerConnection()

4.9编码器层

作用:作为编码器的组成单元,每个编码器层完成一次对输入的特征的提取过程,即编码过程

代码演示

import torch
import torch.nn as nn
from 子层连接结构 import SublayerConnection
from 多头注意力机制 import clones
from torch.autograd import Variable
from 文本嵌入层 import Embeddings
from 多头注意力机制 import PositionalEncoding
from 多头注意力机制 import MultiHeadAttention
from 前馈全连接层 import PositionwiseFeedForward# 编码器层的代码分析
class EncoderLayer(nn.Module):def __init__(self, size, self_atten, feed_forward, dropout):super(EncoderLayer, self).__init__()# 实例化多头注意力对象self.self_atten = self_attenself.feed_forward = feed_forwardself.size = sizeself.sublayer = clones(SublayerConnection(size, dropout), 2)def forward(self, x, mask):x = self.sublayer[0](x, lambda x: self.self_atten(x, x, x, mask))x = self.sublayer[1](x, self.feed_forward)return x# 函数调用
def dm_test_EncoderLaayer():d_model = 512vocab = 1000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))emb = Embeddings(d_model, vocab)embr = emb(x)dropout = 0.2max_len = 60x = embrpe = PositionalEncoding(d_model, dropout, max_len)pe_result = pe(x)x = pe_resultsize = 512head = 8d_ff = 64self_attn = MultiHeadAttention(head, d_model)ff = PositionwiseFeedForward(d_model, d_ff, dropout)mask = Variable(torch.zeros(8, 4, 4))my_encoderlayer = EncoderLayer(size, self_attn, ff, dropout)el_result = my_encoderlayer(x, mask)print('el_result.shape', el_result.shape, el_result)
dm_test_EncoderLaayer()

4.10编码器

概念:编码器对输入进行指定的特征提取过程,也称为编码,由n个编码器层堆叠而成

代码演示

import copyimport torch
import torch.nn as nn
from 多头注意力机制 import clones
from 规范化层 import LayerNorm
from torch.autograd import Variable
from 文本嵌入层 import Embeddings
from 多头注意力机制 import PositionalEncoding
from 多头注意力机制 import MultiHeadAttention
from 前馈全连接层 import PositionwiseFeedForward
from 编码器层 import EncoderLayerclass Encoder(nn.Module):def __init__(self, layer, N):super(Encoder, self).__init__()self.layers = clones(layer, N)self.norm = LayerNorm(layer.size)def forward(self, x, mask):for layer in self.layers:x = layer(x, mask)return self.norm(x)# 函数调用
def dm_test_Encoder():d_model = 512vocab = 1000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))emb = Embeddings(d_model, vocab)embr = emb(x)dropout = 0.2max_len = 60x = embrpe = PositionalEncoding(d_model, dropout, max_len)pe_result = pe(x)x = pe_resultsize = 512head = 8d_model = 512d_ff = 64c = copy.deepcopyattn = MultiHeadAttention(head, d_model)dropout = 0.2ff = PositionwiseFeedForward(d_model, d_ff, dropout)layer = EncoderLayer(size, c(attn), c(ff), dropout)N=6mask=Variable(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)
dm_test_Encoder()

5.解码器部分的实现

5.1解码器介绍

解码器部分:

由N个解码器层堆叠而成

每个解码器层由三个子层连接结构组成

第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接

第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接

第三个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接

5.2解码器层的作用

作为解码器的组成单元,每个解码器层根据给定的输入向目标方向进行特征提取操作,即解码过程

import torch
import torch.nn as nn
from 规范化层 import LayerNorm
from torch.autograd import Variable
from 文本嵌入层 import Embeddings
from 多头注意力机制 import PositionalEncoding
from 多头注意力机制 import MultiHeadAttentionclass SublayerConnection(nn.Module):def __init__(self, size, dropout=0.1):super(SublayerConnection, self).__init__()# 定义norm层self.norm = LayerNorm(size)# 定义dropoutself.dropout = nn.Dropout(dropout)def forward(self, x, sublayer):myres = x + self.dropout(sublayer(self.norm(x)))return myres# 函数调用
def dm_test_SublayerConnection():size = 512head = 8d_model = 512vocab = 1000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))emb = Embeddings(d_model, vocab)embr = emb(x)dropout = 0.2max_len = 60x = embrpe = PositionalEncoding(d_model, dropout, max_len)pe_result = pe(x)x = pe_resultmask = Variable(torch.zeros(8, 4, 4))# 多头自注意力子层self_attn = MultiHeadAttention(head, d_model)sublayer = lambda x: self_attn(x, x, x, mask)# 子层链接结构sc = SublayerConnection(size, dropout)sc_result = sc(x, sublayer)print('sc_result.shape--->', sc_result.shape)print('sc_result-->', sc_result)
dm_test_SublayerConnection()

5.3解码器

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

import copyimport torch
import torch.nn as nn
from 多头注意力机制 import clones
from 规范化层 import LayerNorm
from torch.autograd import Variable
from 文本嵌入层 import Embeddings
from 多头注意力机制 import PositionalEncoding
from 多头注意力机制 import MultiHeadAttention
from 前馈全连接层 import PositionwiseFeedForward
from 解码器层 import DecoderLayer
from 编码器 import dm_test_Encoder# 解码器代码分析
class Decoder(nn.Module):def __init__(self, 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):for layer in self.layers:x = layer(x, memory, source_mask, target_mask)return self.norm(x)def dm_test_Decoder():d_model = 512vocab = 1000x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))emb = Embeddings(d_model, vocab)embr = emb(x)dropout = 0.2max_len = 60x = embrpe = PositionalEncoding(d_model, dropout, max_len)pe_result = pe(x)x = pe_resultsize = 512d_model = 512head = 8d_ff = 64dropout = 0.2c = copy.deepcopyattn = MultiHeadAttention(head, d_model)ff = PositionwiseFeedForward(d_model, d_ff, dropout)layer = DecoderLayer(d_model, c(attn), c(attn), c(ff), dropout)N = 6x = pe_resulten_result = dm_test_Encoder()memory = en_result# 掩码对象mask = Variable(torch.zeros(8, 4, 4))# sorce掩码  target掩码source_mask = target_mask = mask# 创建解码器对象de = Decoder(layer, N)# 解码器对象 解码de_result = de(x,memory,source_mask,target_mask)print(de_result)print(de_result.shape)
dm_test_Decoder()

6.输出部分实现

输出部分包括线性层和Softmax层

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

Softmax层:使最后一维向量中的数字缩放到0-1的概率值范围之内,并满足它们的和为1

import torch
import torch.nn as nn
import torch.nn.functional as Fclass Generator(nn.Module):def __init__(self, d_model, vocab_size):super(Generator, self).__init__()self.project = nn.Linear(d_model, vocab_size)def forward(self, x):x = F.log_softmax(self.project(x), dim=-1)return x
#函数的调用
d_model=512
vocab_size=1000
my_generator=Generator(d_model,vocab_size)
#准备模型数据
x=torch.randn(2,4,512)
#数据经过out层
gen_result=my_generator(x)
print('gen_result--->',gen_result,'\n',gen_result)

7.模型构建

1.编码器解码器结构的代码实现

import torch
import torch.nn as nn
from torch.autograd import Variable
from 编码器 import  Encoder as  en
from  解码器 import  Decoder as de
from 输出部分 import  Generator as genclass EncoderDecoder(nn.Module):def __init__(self, encoder, decoder, source_embed, target_embed, generator):super(EncoderDecoder, self).__init__()# 将参数传入到类中self.encoder = encoderself.decoder = decoderself.src_embed = source_embedself.tgt_embed = target_embedself.generator = generatordef forward(self, source, target, source_mask, target_mask):return self.generator(self.decode(self.encode(source, source_mask), source_mask, target, target_mask))def encode(self, source, source_mask):return self.encoder(self.src_embed(source), source_mask)def decode(self, memory, source_mask, target, target_mask):return self.decoder(self.tgt_embed(target), memory, source_mask, target_mask)# 实例化参数
vocab_size = 1000
d_model = 512
encoder = en
decoder = de
source_embed = nn.Embedding(vocab_size, d_model)
target_embed = nn.Embedding(vocab_size, d_model)
generator = gen
# 输入参数
source = target = Variable([[100, 2, 421, 508], [491, 998, 1, 221]])
source_mask = target_mask = Variable(torch.zeros(8, 4, 4))
ed = EncoderDecoder(encoder, decoder, source_embed, target_embed, generator)
ed_result = ed(source, target, source_mask, target_mask)
print(ed_result)
print(ed_result.shape)

2.transformer模型构建过程的代码分析

# transfromer模型构建过程的代码分析
import copyimport torch
import  torch.nn as nn
from 多头注意力机制 import MultiHeadAttention
from 前馈全连接层 import PositionwiseFeedForward
from 多头注意力机制 import PositionalEncoding
from 编码器解码器结构的代码实现 import EncoderDecoder
from 文本嵌入层 import Embeddings
from 编码器 import Encoder
from 编码器层 import EncoderLayer
from 解码器 import Decoder
from 解码器层 import DecoderLayer
from  输出部分 import  Generator
from  torch.autograd import  Variabledef make_model(source_vocab, target_vocab, N=6, d_model=512, d_ff=2048, head=8, dropout=0.1):c = copy.deepcopyattn = MultiHeadAttention(head=8, embedding_dim=512, dropout=dropout)ff = PositionwiseFeedForward(d_model=d_model, d_ff=d_ff, dropput=dropout)position = PositionalEncoding(d_model=d_model, dropout=dropout)# 构建EncoderDecoder对象model = EncoderDecoder(Encoder(EncoderLayer(d_model,c(attn),c(ff),dropout),N),Decoder(DecoderLayer(d_model,c(attn),c(ff),dropout),N),nn.Sequential(Embeddings(d_model,source_vocab),c(position)),nn.Sequential(Embeddings(d_model,target_vocab),c(position)),Generator(d_model,target_vocab))for p in model.parameters():if p.dim()>1:nn.init.xavier_uniform(p)return  model
def dm_test_make_model():source_vocab=500target_vocab=1000N=6my_transfrom_modelobj=make_model(source_vocab,target_vocab,N=6,d_model=512,d_ff=2048,head=8,dropout=0.1)print(my_transfrom_modelobj)source=target=Variable(torch.LongTensor([[1, 2, 3, 8], [3, 4, 1, 8]]))source_mask=target_mask=Variable(torch.zeros(8,4,4))mydata=my_transfrom_modelobj(source,target,source_mask,target_mask)print('mydata.shape--->',mydata.shape)print('mydata--->',mydata)
dm_test_make_model()

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

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

相关文章

zookeeper基础学习之六: zookeeper java客户端curator

简介 Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等等。Patrixck Hunt(Zookeeper)以一句“Guava is to Java…

【算法刷题 | 数组】3.12(二分查找、移除元素、有序数组的平方、长度最小的子数组、螺旋矩阵2)

文章目录 1.二分查找1.1题目1.2思路(核心:区间的定义)1.3左闭右闭1.4左闭右开1.5总结 2.移除元素2.1题目2.1思路2.2.1暴力解法2.2.2双指针法 23总结 3.有序数组的平方3.1题目3.2思路3.2.1暴力解法3.2.2双指针法 4.长度最小的子数组4.1题目4.2…

Linux中文件和目录管理(创建删除移动复制)

目录 1——一次建立一个或多个目录:mkdir ​2——创建一个空文件:touch 3——移动和重命名:mv 4——复制文件和目录:cp 5—— 删除目录和文件:rmdir和rm 在学习文件与目录的管理的一些命令之前,我们先…

深度学习-面经(part2、CNN)

2 CNN 对图像(不同的数据窗口数据)和滤波矩阵做内积(逐个元素相乘再求和)的操作就是所谓的『卷积』操作。 卷积神经网络由输入层、卷积层、激励层、池化层、全连接层组成。 ① 最左边: 数据输入层,对数据做一些处理…

数字后端 EDA 软件分享

数字后端 EDA 软件分享 推荐这几家的EDA工具吧,虽说我也支持国产工具,但是我还是选择了这几家的工具 apache cadence mentor synopsys 下图我现在用的eda环境,利用网上的资源,自己独立在vmware上搭建好的EDA环境 除去pdk&#…

从政府工作报告探究计算机行业发展

从政府工作报告探计算机行业发展 政府工作报告作为政府工作的全面总结和未来规划,不仅反映了国家整体的发展态势,也为各行各业提供了发展的指引和参考。随着信息技术的快速发展,计算机行业已经成为推动经济社会发展的重要引擎之一。因此&…

计算机考研|怎么备考「科软」?

学好408和考研数学就可以了 大家对于科软已经回到了理性的区间,很难再出现刚开始的300分上科软的现象,也不会再出现388分炸穿地心的现象。 如果大家想报考科软,我觉得一定要认真对待复习,不要抱有抄底的心态去复习。 众所周知&am…

7.JavaWebHTML:构建数字世界的语言和结构

目录 导语: 第一部分:Web概念与作用 1.1 Web的定义 1.2 Web的作用 1.3 JavaWeb 第二部分:HTML概念与内容 2.1 HTML的定义 2.2 HTML的内容 第三部分:HTML的作用 3.1 HTML的作用 3.2 HTML在现代Web开发中的角色 …

[Redis]——主从同步原理(全量同步、增量同步)

目录 Redis集群: 主从同步原理: replid和offset: 全量同步和增量同步: repl_baklog文件: 主从集群的优化: Redis集群: 部署多台Redis我们称之为Redis集群,他有一个主节点(负责写操作)&…

爱普生晶振发布RTC模块晶振(压电侠)

爱普生晶振一直以”省,小,精”技术作为资深核心,并且已经建立了一个原始的垂直整合制造模型,可以自己创建独特的核心技术和设备,使用这些作为基地的规划和设计提供独特价值的产品. 世界领先的石英晶体技术精工爱普生公…

中国联通智慧矿山行业解决方案

中国联通国际公司以其全球化服务能力,针对矿山行业的特殊挑战提供了定制化的解决方案,尤其是在网络通信基础设施搭建和智能应用部署方面,助力企业克服远程作业环境下的通信难题,并有效拓展海外市场。 对于矿山类企业而言&#xf…

【遍历方法】浅析Java中字符串、数组、集合的遍历

目录 前言 字符串篇 1.1 使用 for 循环和 charAt 方法 1.2 使用增强 for 循环(forEach 循环) 1.3 使用 Java 8 的 Stream API 最终效果 数组篇 2.1 使用普通 for 循环 2.2 使用增强型 for 循环( forEach 循环) 2.3 使用 Arrays.asList 和 forE…

解决:springboot项目访问hdfs文件提示guava版本不兼容

1、问题描述 版本说明:我用的hadoop版本:3.1.3 项目可以正常启动,但是调用访问hdfs的服务时候报错,报错消息如下:com.google.common.base.preconditions.checkArgument(ZL java/lang/String;Ljava/lang/Object:)V 原因分析&#x…

Flutter开发进阶之使用工具效率开发

Flutter开发进阶之使用工具效率开发 软件开发团队使用Flutter开发的原因通常是因为Flutter开发性能高、效率高、兼容性好、可拓展性高,作为软件PM来说主要考虑的是范围管理、进度管理、成本管理、资源管理、质量管理、风险管理和沟通管理等,可以看到Flu…

企业内部培训考试系统培训计划功能说明

培训计划是预设好的一套课程系列,包含课程和考试,分多个阶段,每完成一个阶段就会在学习地图上留下标记,让用户看到自己的努力成果,增强成就感,从而坚持完成课程。 企业内部培训考试系统中如何设置培训计划…

基于springboot的购物商城管理系统

1.项目简介 1.1 用户简介 用户主要分为管理员和用户端: 管理员: 管理员可以对后台数据进行管理、拥有最高权限、具体权限有登录后进行首页轮播图的配置管理、商品的配置、新品家具商城的配置管理、、家具商城分类管理配置、家具商城详情商品管理、用户…

react-面试题

一、组件基础 1. React 事件机制 <div onClick{this.handleClick.bind(this)}>点我</div> React并不是将click事件绑定到了div的真实DOM上&#xff0c;而是在document处监听了所有的事件&#xff0c;当事件发生并且冒泡到document处的时候&#xff0c;React将事…

网络安全JavaSE第二天(持续更新)

3. 基本数据与运算 3.6 运算符 3.6.1 算术运算符 在 Java 中&#xff0c;算术运算符包含&#xff1a;、-、*、/、% public class ArithmeticOperator { public static void main(String[] args) { int a 10; // 定义了一个整型类型的变量 a&#xff0c;它的值是 10 int b …

区块链推广海外市场怎么做,CloudNEO服务商免费为您定制个性化营销方案

随着区块链技术的不断发展和应用场景的扩大&#xff0c;区块链项目希望能够进入海外市场并取得成功已成为越来越多公司的目标之一。然而&#xff0c;要在海外市场推广区块链项目&#xff0c;需要采取有效的营销策略和措施。作为您的区块链项目营销服务商&#xff0c;CloudNEO将…

后端程序员入门react笔记(八)-redux的使用和项目搭建

一个更好用的文档 添加链接描述 箭头函数的简化 //简化前 function countIncreAction(data) {return {type:"INCREMENT",data} } //简化后 const countIncreAction data>({type:"INCREMENT",data })react UI组件库相关资料 组件库连接和推荐 antd组…