transformer--transformer模型构建和测试

前面几节进行了各种组件的学习和编码,本节将组件组成transformer,并对其进行测试 

EncoderDecoder 编码器解码器构建

使用EnconderDecoder实现编码器-解码器结构

 # 使用EncoderDeconder类实现编码器和解码器class EncoderDecoder(nn.Module):def __init__(self, encoder, decoder, sourc_embed, target_embed, generator) -> None:"""encoder: 编码器对象decoder: 解码器对象sourc_embed: 源数据嵌入函数target_embed: 目标数据嵌入函数generator: 输出部分的类别生成器"""super(EncoderDecoder,self).__init__()self.encoder = encoderself.decoder = decoderself.src_embed = sourc_embedself.tgt_embed = target_embedself.generator = generatordef encode(self,source, source_mask):"""source: 源数据source_mask: 源数据的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)def forward(self,source, target, source_mask, target_mask):return self.decode(self.encode(source, source_mask), source_mask,target,target_mask)

测试代码放在最后,测试结果如下:

ed_result.shape:  torch.Size([2, 4, 512])
ed_result:  tensor([[[ 2.2391, -0.1173, -1.0894,  ...,  0.9693, -0.9286, -0.4191],[ 1.4016,  0.0187, -0.0564,  ...,  0.9323,  0.0403, -0.5115],[ 1.3623,  0.0854, -0.7648,  ...,  0.9763,  0.6179, -0.1512],[ 1.6840, -0.3144, -0.6535,  ...,  0.7420,  0.0729, -0.2303]],[[ 0.8726, -0.1610, -0.0819,  ..., -0.6603,  2.1003, -0.4165],[ 0.5404,  0.8091,  0.8205,  ..., -1.4623,  2.5762, -0.6019],[ 0.9892, -0.3134, -0.4118,  ..., -1.1656,  1.0373, -0.3784],[ 1.3170,  0.3997, -0.3412,  ..., -0.6014,  0.7564, -1.0851]]],grad_fn=<AddBackward0>)

Transformer模型构建

# Tansformer模型的构建过程代码
def make_model(source_vocab, target_vocab, N=6,d_model=512, d_ff=2048, head=8, dropout=0.1):"""该函数用来构建模型,有7个参数,分别是源数据特征(词汇)总数,目标数据特征(词汇)总数,编码器和解码器堆叠数,词向量映射维度,前馈全连接网络中变换矩阵的维度,多头注意力结构中的多头数,以及置零比率dropout"""c = copy.deepcopy#实例化多头注意力attn = MultiHeadedAttention(head, d_mode)# 实例化前馈全连接层 得到对象ffff = PositionalEncoding(d_mode, dropout)# 实例化位置编码类,得到对象positionposition = PositionalEncoding(d_mode,dropout)# 根据结构图,最外层是EncoderDecoder,在EncoderDecoder中,# 分别是编码器层,解码器层,源数据Embedding层和位置编码组成的有序结构# 目标数据Embedding层和位置编码组成的有序结构,以及类别生成器层。在编码器层中有attention子层以及前馈全连接子层,# 在解码器层中有两个attention子层以及前馈全连接层model  =EncoderDecoder(Encoder(EncoderLayer(d_mode, c(attn), c(ff), dropout),N),Decoder(DecoderLayer(d_mode, c(attn), c(attn),c(ff),dropout),N),nn.Sequential(Embeddings(d_mode,source_vocab), c(position)),nn.Sequential(Embeddings(d_mode, target_vocab), c(position)),Generator(d_mode, target_vocab))# 模型结构完成后,接下来就是初始化模型中的参数,比如线性层中的变换矩阵,这里一但判断参数的维度大于1,# 则会将其初始化成一个服从均匀分布的矩阵for p in model.parameters():if p.dim()>1:nn.init.xavier_uniform(p)return model

测试代码

 
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 encoder 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 layer 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)# 使用EncoderDeconder类实现编码器和解码器class EncoderDecoder(nn.Module):def __init__(self, encoder, decoder, sourc_embed, target_embed, generator) -> None:"""encoder: 编码器对象decoder: 解码器对象sourc_embed: 源数据嵌入函数target_embed: 目标数据嵌入函数generator: 输出部分的类别生成器"""super(EncoderDecoder,self).__init__()self.encoder = encoderself.decoder = decoderself.src_embed = sourc_embedself.tgt_embed = target_embedself.generator = generatordef encode(self,source, source_mask):"""source: 源数据source_mask: 源数据的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)def forward(self,source, target, source_mask, target_mask):return self.decode(self.encode(source, source_mask), source_mask,target,target_mask)# Tansformer模型的构建过程代码
def make_model(source_vocab, target_vocab, N=6,d_model=512, d_ff=2048, head=8, dropout=0.1):"""该函数用来构建模型,有7个参数,分别是源数据特征(词汇)总数,目标数据特征(词汇)总数,编码器和解码器堆叠数,词向量映射维度,前馈全连接网络中变换矩阵的维度,多头注意力结构中的多头数,以及置零比率dropout"""c = copy.deepcopy#实例化多头注意力attn = MultiHeadedAttention(head, d_mode)# 实例化前馈全连接层 得到对象ffff = PositionalEncoding(d_mode, dropout)# 实例化位置编码类,得到对象positionposition = PositionalEncoding(d_mode,dropout)# 根据结构图,最外层是EncoderDecoder,在EncoderDecoder中,# 分别是编码器层,解码器层,源数据Embedding层和位置编码组成的有序结构# 目标数据Embedding层和位置编码组成的有序结构,以及类别生成器层。在编码器层中有attention子层以及前馈全连接子层,# 在解码器层中有两个attention子层以及前馈全连接层model  =EncoderDecoder(Encoder(EncoderLayer(d_mode, c(attn), c(ff), dropout),N),Decoder(DecoderLayer(d_mode, c(attn), c(attn),c(ff),dropout),N),nn.Sequential(Embeddings(d_mode,source_vocab), c(position)),nn.Sequential(Embeddings(d_mode, target_vocab), c(position)),Generator(d_mode, target_vocab))# 模型结构完成后,接下来就是初始化模型中的参数,比如线性层中的变换矩阵,这里一但判断参数的维度大于1,# 则会将其初始化成一个服从均匀分布的矩阵for p in model.parameters():if p.dim()>1:nn.init.xavier_uniform(p)return modelif __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)# encoderdeconder 测试vocab_size = 1000d_mode = 512encoder = endecoder= desource_embed = nn.Embedding(vocab_size, d_mode)target_embed = nn.Embedding(vocab_size, d_mode)generator = gensource = target = torch.LongTensor([[100,2,321,508],[321,234,456,324]])source_mask = target_mask = 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.shape: ", ed_result.shape)print("ed_result: ", ed_result)# transformer 测试source_vocab = 11target_vocab = 11N=6# 其他参数使用默认值res = make_model(source_vocab, target_vocab,6)print(res)

打印模型层结构:

EncoderDecoder((encoder): Encoder((layers): ModuleList((0): EncoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(1): EncoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(2): EncoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(3): EncoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(4): EncoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(5): EncoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False)))))(norm): LayerNorm())(decoder): Decoder((layers): ModuleList((0): DecoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(src_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(2): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(1): DecoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(src_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(2): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(2): DecoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(src_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(2): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(3): DecoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(src_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(2): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(4): DecoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(src_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(2): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))))(5): DecoderLayer((self_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(src_attn): MultiHeadedAttention((linears): ModuleList((0): Linear(in_features=512, out_features=512, bias=True)(1): Linear(in_features=512, out_features=512, bias=True)(2): Linear(in_features=512, out_features=512, bias=True)(3): Linear(in_features=512, out_features=512, bias=True))(dropout): Dropout(p=0.1, inplace=False))(feed_forward): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False))(sublayer): ModuleList((0): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(1): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False))(2): SublayerConnection((norm): LayerNorm()(dropout): Dropout(p=0.1, inplace=False)))))(norm): LayerNorm())(src_embed): Sequential((0): Embeddings((lut): Embedding(11, 512))(1): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False)))(tgt_embed): Sequential((0): Embeddings((lut): Embedding(11, 512))(1): PositionalEncoding((dropout): Dropout(p=0.1, inplace=False)))(generator): Generator((project): Linear(in_features=512, out_features=11, bias=True))
)

测试Transformer运行

我们将通过一个小的copy任务完成模型的基本测试工作

copy任务介绍:

任务描述:

        针对数字序列进行学习,学习的最终目标是使输出与输入的序列相同.如输入[1,5,8,9,3],输出也是[1,5,8,9,3].

任务意义:

copy任务在模型基础测试中具有重要意义,因为copy操作对于模型来讲是一条明显规律,因此模型能否在短时间内,小数据集中学会它,可以帮助我们断定模型所有过程是否正常,是否已具备基本学习能力.

使用copy任务进行模型基本测试的四步曲:

第一步: 构建数据集生成器
第二步: 获得Transformer模型及其优化器和损失函数
第三步: 运行模型进行训练和评估
第四步: 使用模型进行贪婪解码

code

from transformer import make_model
import torch
import numpy as npfrom pyitcast.transformer_utils import Batch# 第一步: 构建数据集生成器
def data_generator(V, batch, num_batch):# 该函数用于随机生成copy任务的数据,它的三个输入参数是V:随机生成数字的最大值+1,# batch:每次输送给模型更新一次参数的数据量,num_batch:-共输送num_batch次完成一轮for i in range(num_batch):data = torch.from_numpy(np.random.randint(1,V, size=(batch,10),dtype="int64"))data[:,0]=1source = torch.tensor(data,requires_grad=False)target = torch.tensor(data, requires_grad=False)yield Batch(source, target)# 第二步: 获得Transformer模型及其优化器和损失函数
# 导入优化器工具包get_std_opt,该工具用于获得标准的针对Transformer模型的优化器
# 该标准优化器基于Adam优化器,使其对序列到序列的任务更有效
from pyitcast.transformer_utils import get_std_opt
# 导入标签平滑工具包,该工具用于标签平滑,标签平滑的作用就是小幅度的改变原有标签值的值域
# 因为在理论上即使是人工的标注数据也可能并非完全正确,会受到一些外界因素的影响而产生一些微小的偏差
# 因此使用标签平滑来弥补这种偏差,减少模型对某一条规律的绝对认知,以防止过拟合。通过下面示例了解更清晰
from pyitcast.transformer_utils import LabelSmoothing
# 导入损失计算工具包,该工具能够使用标签平滑后的结果进行损失的计算,
# 损失的计算方法可以认为是交叉熵损失函数。
from pyitcast.transformer_utils import SimpleLossCompute# 将生成0-10的整数
V = 11
# 每次喂给模型20个数据进行更新参数
batch = 20
# 连续喂30次完成全部数据的遍历,也就是一轮
num_batch = 30# 使用make_model构建模型
model = make_model(V,V,N=2)
print(model.src_embed[0])
# 使用get_std_opt获得模型优化器
model_optimizer = get_std_opt(model)
# 使用labelSmoothing获得标签平滑对象
# 使用LabelSmoothing实例化一个crit对象。
# 第一个参数size代表目标数据的词汇总数,也是模型最后一层得到张量的最后一维大小
# 这里是5说明目标词汇总数是5个,第二个参数padding_idx表示要将那些tensor中的数字
# 替换成0,一般padding_idx=0表示不进行替换。第三个参数smoothing,表示标签的平滑程度
# 如原来标签的表示值为1,则平滑后它的值域变为[1-smoothing,1+smoothing].
criterion = LabelSmoothing(size=V, padding_idx=0, smoothing=0.0)
# 使用SimpleLossCompute获取到标签平滑结果的损失计算方法
loss = SimpleLossCompute(model.generator,criterion,model_optimizer)# 第三步: 运行模型进行训练和评估
from pyitcast.transformer_utils import run_epochdef run(model, loss, epochs=10):for epoch in range(epochs):# 进入训练模式,所有参数更新model.train()# 训练时batchsize是20run_epoch(data_generator(V,8,20),model,loss)model.eval()run_epoch(data_generator(V,8,5),model,loss)if __name__ == "__main__":# 将生成0-10的整数V = 11# 每次喂给模型20个数据进行更新参数batch = 20# 连续喂30次完成全部数据的遍历,也就是一轮num_batch = 30res = data_generator(V,batch, num_batch)run(model, loss)

如果直接跑上面的可能会报错,报错的主要原因是 pyitcast主要是针对pytorch 的版本很低,但是好像这个库也不升级了,所以你如果想要跑通,就需要修改下面两个地方:

第一个错误:'Embeddings' object has no attribute 'd_model'

 从上面可以看到,get_std_opt需要用到嵌入向量的维度,但是没有这个值,这个时候可以从两个地方修改,一个是我们embeding的类增加这个属性即:

第二种方法,直接进入 get_std_opt函数里面,修改这个参数

以上两个都可以解决问题 

第二个问题:RuntimeError: scatter(): Expected dtype int64 for index

这个属于数据类型的问题,主要是在生成训练数据时的问题,如下修改:

这样就可以正常训练了 

输出:

Epoch Step: 1 Loss: 3.169641 Tokens per Sec: 285.952789
Epoch Step: 1 Loss: 2.517479 Tokens per Sec: 351.509888
Epoch Step: 1 Loss: 2.595001 Tokens per Sec: 294.475616
Epoch Step: 1 Loss: 2.108872 Tokens per Sec: 476.050293
Epoch Step: 1 Loss: 2.229053 Tokens per Sec: 387.324188
Epoch Step: 1 Loss: 1.810681 Tokens per Sec: 283.639557
Epoch Step: 1 Loss: 2.047313 Tokens per Sec: 394.773773
Epoch Step: 1 Loss: 1.724596 Tokens per Sec: 415.394714
Epoch Step: 1 Loss: 1.850358 Tokens per Sec: 421.050873
Epoch Step: 1 Loss: 1.668582 Tokens per Sec: 368.275421
Epoch Step: 1 Loss: 2.005047 Tokens per Sec: 424.458466
Epoch Step: 1 Loss: 1.632835 Tokens per Sec: 408.158966
Epoch Step: 1 Loss: 1.698805 Tokens per Sec: 441.689392
Epoch Step: 1 Loss: 1.567691 Tokens per Sec: 392.488251
Epoch Step: 1 Loss: 1.765411 Tokens per Sec: 428.815796
Epoch Step: 1 Loss: 1.492155 Tokens per Sec: 426.288910
Epoch Step: 1 Loss: 1.541114 Tokens per Sec: 411.078918
Epoch Step: 1 Loss: 1.469818 Tokens per Sec: 454.231476
Epoch Step: 1 Loss: 1.677189 Tokens per Sec: 431.382690
Epoch Step: 1 Loss: 1.377327 Tokens per Sec: 433.725250

 

引入贪婪解码,并进行了训练测试

from transformer import make_model
import torch
import numpy as npfrom pyitcast.transformer_utils import Batch# 第一步: 构建数据集生成器
def data_generator(V, batch, num_batch):# 该函数用于随机生成copy任务的数据,它的三个输入参数是V:随机生成数字的最大值+1,# batch:每次输送给模型更新一次参数的数据量,num_batch:-共输送num_batch次完成一轮for i in range(num_batch):data = torch.from_numpy(np.random.randint(1,V, size=(batch,10),dtype="int64"))data[:,0]=1source = torch.tensor(data,requires_grad=False)target = torch.tensor(data, requires_grad=False)yield Batch(source, target)# 第二步: 获得Transformer模型及其优化器和损失函数
# 导入优化器工具包get_std_opt,该工具用于获得标准的针对Transformer模型的优化器
# 该标准优化器基于Adam优化器,使其对序列到序列的任务更有效
from pyitcast.transformer_utils import get_std_opt
# 导入标签平滑工具包,该工具用于标签平滑,标签平滑的作用就是小幅度的改变原有标签值的值域
# 因为在理论上即使是人工的标注数据也可能并非完全正确,会受到一些外界因素的影响而产生一些微小的偏差
# 因此使用标签平滑来弥补这种偏差,减少模型对某一条规律的绝对认知,以防止过拟合。通过下面示例了解更清晰
from pyitcast.transformer_utils import LabelSmoothing
# 导入损失计算工具包,该工具能够使用标签平滑后的结果进行损失的计算,
# 损失的计算方法可以认为是交叉熵损失函数。
from pyitcast.transformer_utils import SimpleLossCompute# 将生成0-10的整数
V = 11
# 每次喂给模型20个数据进行更新参数
batch = 20
# 连续喂30次完成全部数据的遍历,也就是一轮
num_batch = 30# 使用make_model构建模型
model = make_model(V,V,N=2)# 使用get_std_opt获得模型优化器
model_optimizer = get_std_opt(model)
# 使用labelSmoothing获得标签平滑对象
# 使用LabelSmoothing实例化一个crit对象。
# 第一个参数size代表目标数据的词汇总数,也是模型最后一层得到张量的最后一维大小
# 这里是5说明目标词汇总数是5个,第二个参数padding_idx表示要将那些tensor中的数字
# 替换成0,一般padding_idx=0表示不进行替换。第三个参数smoothing,表示标签的平滑程度
# 如原来标签的表示值为1,则平滑后它的值域变为[1-smoothing,1+smoothing].
criterion = LabelSmoothing(size=V, padding_idx=0, smoothing=0.0)
# 使用SimpleLossCompute获取到标签平滑结果的损失计算方法
loss = SimpleLossCompute(model.generator,criterion,model_optimizer)# 第三步: 运行模型进行训练和评估
from pyitcast.transformer_utils import run_epochdef run(model, loss, epochs=10):for epoch in range(epochs):# 进入训练模式,所有参数更新model.train()# 训练时batchsize是20run_epoch(data_generator(V,8,20),model,loss)model.eval()run_epoch(data_generator(V,8,5),model,loss)# 引入贪婪解码
# 导入贪婪解码工具包greedy_decode,该工具将对最终结进行贪婪解码贪婪解码的方式是每次预测都选择概率最大的结果作为输出,
# 它不一定能获得全局最优性,但却拥有最高的执行效率。
from pyitcast.transformer_utils import greedy_decode     def run_greedy(model, loss, epochs=10):for epoch in range(epochs):# 进入训练模式,所有参数更新model.train()# 训练时batchsize是20run_epoch(data_generator(V,8,20),model,loss)model.eval()run_epoch(data_generator(V,8,5),model,loss)model.eval()# 假定输入张量source = torch.LongTensor([[1,8,3,4,10,6,7,2,9,5]])# 定义源数据掩码张量,因为元素都是1,在我们这里1代表不遮掩因此相当于对源数据没有任何遮掩.source_mask = torch.ones(1,1,10)# 最后将model,src,src_mask,解码的最大长度限制max_len,默认为10# 以及起始标志数字,默认为1,我们这里使用的也是1result = greedy_decode(model, source, source_mask, max_len=10,start_symbol=1)print(result)if __name__ == "__main__":# # 将生成0-10的整数# V = 11# # 每次喂给模型20个数据进行更新参数# batch = 20# # 连续喂30次完成全部数据的遍历,也就是一轮# num_batch = 30# res = data_generator(V,batch, num_batch)# run(model, loss)run_greedy(model, loss,50)

输出部分结果:

Epoch Step: 1 Loss: 0.428033 Tokens per Sec: 389.530670
Epoch Step: 1 Loss: 0.317753 Tokens per Sec: 399.060852
Epoch Step: 1 Loss: 0.192723 Tokens per Sec: 387.384308
Epoch Step: 1 Loss: 0.257650 Tokens per Sec: 379.354736
Epoch Step: 1 Loss: 0.487521 Tokens per Sec: 410.506714
Epoch Step: 1 Loss: 0.136969 Tokens per Sec: 388.222687
Epoch Step: 1 Loss: 0.119838 Tokens per Sec: 375.405731
Epoch Step: 1 Loss: 0.250391 Tokens per Sec: 408.776367
Epoch Step: 1 Loss: 0.376862 Tokens per Sec: 419.787231
Epoch Step: 1 Loss: 0.163561 Tokens per Sec: 393.896088
Epoch Step: 1 Loss: 0.303041 Tokens per Sec: 395.884857
Epoch Step: 1 Loss: 0.126261 Tokens per Sec: 386.709167
Epoch Step: 1 Loss: 0.237891 Tokens per Sec: 376.114075
Epoch Step: 1 Loss: 0.139017 Tokens per Sec: 405.207336
Epoch Step: 1 Loss: 0.414842 Tokens per Sec: 389.219666
Epoch Step: 1 Loss: 0.207141 Tokens per Sec: 392.840820
tensor([[ 1,  8,  3,  4, 10,  6,  7,  2,  9,  5]])

从上面的代码可以看出测试输入的 是 source = torch.LongTensor([[1,8,3,4,10,6,7,2,9,5]])

推理出来的结果是完全正确的,因为我把epoch设置为50了,如果是10就会有错误的情况,大家可以尝试

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

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

相关文章

飞书文档批量导出

背景需求 最近所参与的项目即将结项&#xff0c;需要将飞书中的产品需求文档&#xff08;PRD&#xff09;交付给甲方&#xff0c;由于文档较多&#xff0c;大概有两百多个&#xff0c;一个一个的下载导出&#xff0c;太麻烦了&#xff08;PS&#xff1a;本人比较懒&#xff09;…

【MySQL】表的约束——空属性、默认值、列描述、zerofill、主键、自增长、唯一键、外键

文章目录 MySQL表的约束1. 空属性2. 默认值3. 列描述4. zerofill5. 主键6. 自增长7. 唯一键8. 外键 MySQL 表的约束 MySQL中的表的约束是一种规则&#xff0c;用于限制或保护表中数据的完整性和合法性。约束可以确保数据在插入、更新或删除时满足特定的条件&#xff0c;从而维护…

MySQL相关问题

MySQL相关问题 一、MySQL支持哪些存储引擎&#xff1f;二、MySQL是如何执行一条SQL的&#xff1f;三、MySQL数据库InnoDB存储引擎是如何工作的&#xff1f;四、如果要对数据库进行优化&#xff0c;该怎么优化&#xff1f;五、MySQL如何定位慢查询&#xff1f;六、如何分析MySQL…

揭秘App访问量背后的秘密:数据统计与分析

在移动互联网时代&#xff0c;App已成为人们日常生活的重要组成部分。对于App运营者来说&#xff0c;了解用户的访问量、行为习惯等数据至关重要。本文将深入探讨如何精准统计App访问量&#xff0c;为运营者提供有价值的数据支持。 一、App访问量统计的重要性 访问量是衡量A…

计算机专业必看的十部电影

计算机专业必看的十部电影 1. 人工智能2. 黑客帝国3. 盗梦空间4. 社交网络5. Her6. 模仿游戏7. 斯诺登8. 头号玩家9. 暗网10. 网络迷踪 计算机专业必看的十部电影&#xff0c;就像一场精彩盛宴&#xff01; 《黑客帝国》让你穿越虚拟世界&#xff0c;感受高科技的魅力《模仿游戏…

公网IP怎么获取?

公网IP是网络中设备的唯一标识符&#xff0c;用于在Internet上进行通信和定位。对于普通用户来说&#xff0c;了解如何获取自己的公网IP是很有必要的&#xff0c;本文将介绍几种获取公网IP的方法。 方法一&#xff1a;通过路由器查询 大多数家庭和办公室使用的路由器都会有一个…

深入解析Mybatis-Plus框架:简化Java持久层开发(七)

&#x1f340; 前言 博客地址&#xff1a; CSDN&#xff1a;https://blog.csdn.net/powerbiubiu &#x1f44b; 简介 本章节介绍如何通过Mybatis-Plus删除数据库中的数据。 本章节不需要前置准备&#xff0c;继续使用之前的测试类&#xff0c;数据库表进行操作。 &#x1f4…

day03_Vue_Element

文章目录 01.Ajax1.1 Ajax 概述1.2 同步异步1.3 原生Ajax 2. Axios2.1 Axios的基本使用2.2 Axios快速入门2.3请求方法的别名2.4 案例 3 前后台分离开发3.1 前后台分离开发介绍 04 YAPI4.1 YAPI介绍4.2 接口文档管理 05 前端工程化5.1 前端工程化介绍5.2 前端工程化入门5.2.1 环…

【Python】变量的引用

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

2024.3.4 作业

1、流式域套接字 1>tcp服务端实现 #include<myhead.h> int main(int argc, const char *argv[]) {//1、创建套接字int sfd socket(AF_UNIX, SOCK_STREAM, 0);if(sfd -1){perror("socket error");return -1;}//2、判断套接字文件是否存在&#xff0c;如果…

5G工业智能网关保障煤矿安全生产

随着物联网技术发展与煤矿需求的持续激增&#xff0c;矿山矿井的分布范围广泛、户外环境恶劣等管理问题急需解决&#xff0c;而物联网网关工业级设计能够无惧恶劣环境干扰&#xff0c;轻松解决户外网络部署问题。 工业网关通过采集矿井内的各类传感器数据对矿井进行远程监控&a…

【NR 定位】3GPP NR Positioning 5G定位标准解读(五)

前言 3GPP 标准网址&#xff1a;Directory Listing /ftp/ 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;一&#xff09;-CSDN博客 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;二&#xff09;-CSDN博客 【NR 定位】3GPP NR Positioning 5G定位…

[GYCTF2020]EasyThinking --不会编程的崽

看标题就知道&#xff0c;这大概率是关于thinkphp的题目。先尝试错误目录使其报错查看版本号 thinkphp v6.0.0&#xff0c;在网上搜索一下&#xff0c;这个版本有一个任意文件上传漏洞。参考以下文章。 https://blog.csdn.net/god_zzZ/article/details/104275241 先注册一个账…

VL53L8CX驱动开发(1)----驱动TOF进行区域检测

VL53L8CX驱动开发----1.驱动TOF进行区域检测 概述视频教学样品申请源码下载主要特点硬件准备技术规格系统框图应用示意图区域映射生成STM32CUBEMX选择MCU 串口配置IIC配置LPn 设置X-CUBE-TOF1串口重定向代码配置Tera Term配置演示结果 概述 VL53L8CX是一款8x8多区域ToF测距传感…

STM32(6)中断

1.中断 1.1 中断的概念 STM32的中断&#xff1a; 1.2 中断优先级 用数字的大小表示中断优先级的高低&#xff0c;数字的范围&#xff1a;0000--1111&#xff08;二进制&#xff09;&#xff0c;即0-15&#xff0c;共16级优先级。 进一步对这4位二进制数进行划分&#xff0c;可…

demo型xss初级靶场

一、环境 XSS Game - Ma Spaghet! | PwnFunction 二、开始闯关 第一关 看看代码 试一下直接写 明显进来了为什么不执行看看官方文档吧 你不执行那我就更改单标签去使用呗 ?somebody<img%20src1%20onerror"alert(1)"> 防御&#xff1a; innerText 第二关…

分账系统哪个好 盘点2024年好用的四款分账系统

分账系统在现代商业活动中扮演着至关重要的角色&#xff0c;为企业提供了高效、准确的分账管理。那么&#xff0c;你知道2024年哪几款分账系统最好用呢&#xff1f;跟着小编的脚步去看看吧&#xff01; 一、商淘云 商淘云是广州商淘信息科技有限公司旗下品牌&#xff0c;它提…

ShardingJdbc分库分表-浅谈分表原理

文章目录 为什么要分库分表一、分库分表二、不停机分库分表数据迁移 为什么要分库分表 一般的机器&#xff08;4核16G&#xff09;&#xff0c;单库的MySQL并发&#xff08;QPSTPS&#xff09;超过了2k&#xff0c;系统基本就完蛋了。最好是并发量控制在1k左右。这里就引出一个…

matplotlib从起点出发(14)_Tutorial_imshow_origin_extent

0 总述 imshow()允许你将图像&#xff08;将进行颜色映射——基于norm和cmap——的2D数组或将按原样使用的3D RGB(A)的数组&#xff09;渲染到数据空间中的矩形区域。最终渲染中图像的方向由原点和范围关键字参数&#xff08;以及生成的AxesImage实例上的属性&#xff09;和Ax…

一.数据分析简介

目录 一、了解数据分析 1.1 什么是数据分析 1.2 数据分析的重要性 1.3 数据分析的基本流程 数据获取 数据处理 1.4 数据分析的应用场景 客户分析 营销分析 二、数据分析工具 jupyter 2.1 编辑器安装 2.2 Jupyter快捷使用 一、了解数据分析 学习数据分析&#xff0…