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.pswp.cn/news/719269.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/719269.shtml
英文地址,請注明出處:http://en.pswp.cn/news/719269.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

飛書文檔批量導出

背景需求 最近所參與的項目即將結項&#xff0c;需要將飛書中的產品需求文檔&#xff08;PRD&#xff09;交付給甲方&#xff0c;由于文檔較多&#xff0c;大概有兩百多個&#xff0c;一個一個的下載導出&#xff0c;太麻煩了&#xff08;PS&#xff1a;本人比較懶&#xff09;…

ROS create_wall_timer/create_timer函數區別

在ROS&#xff08;Robot Operating System&#xff09;中&#xff0c;create_wall_timer 和 create_timer 是用于創建定時器的兩個不同的函數&#xff0c;它們在使用上有一些區別&#xff1a; Clock Type: create_wall_timer: 創建的定時器是基于Wall clock的&#xff0c;這意…

軟考筆記--結構化分析方法

結構化分析&#xff08;SA&#xff09;方法的基本思想是自定向下&#xff0c;逐層分解&#xff0c;把一個大問題分解成若干個小問題&#xff0c;每一個小問題再分解成若干個更小的問題。經過逐層分解&#xff0c;每個最低層的問題都是足夠簡單、容易解決的。 SA方法分析模型的…

78. 子集(力扣LeetCode)

文章目錄 78. 子集題目描述回溯算法 78. 子集 題目描述 給你一個整數數組 nums &#xff0c;數組中的元素 互不相同 。返回該數組所有可能的子集&#xff08;冪集&#xff09;。 解集 不能 包含重復的子集。你可以按 任意順序 返回解集。 示例 1&#xff1a; 輸入&#xff…

selenium高亮元素

def set_high_light_elment(self, element): """高亮web元素。 Args: element: WebElement:web元素 """ element_styleelement.get_attribute(style) self.mark_dom_text(element_s…

【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…

一文詳解mysql 的鎖

MySQL鎖是用于管理數據庫中的并發操作的一種機制&#xff0c;它可以確保數據的一致性和完整性。 按范圍劃分&#xff1a;包括全局鎖、表級鎖、頁級鎖和行級鎖。 按類型劃分&#xff1a;包括間隙鎖、臨鍵鎖和記錄鎖。 按級別劃分&#xff1a;包括共享鎖&#xff08;S鎖&#xff…

如何在Windows輕量應用服務器上安裝和配置SSH?

如何在Windows輕量應用服務器上安裝和配置SSH&#xff1f; 檢查OpenSSH的可用性&#xff1a;首先&#xff0c;需要以管理員身份打開PowerShell并運行命令Get-WindowsCapability - Online | Where-Object Name - like OpenSSH*來檢查OpenSSH服務是否可用。如果服務未啟動或不可…

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…

MySQL中的大表優化方案

當MySQL單表記錄數過大時&#xff0c;數據庫的CRUD性能會明顯下降&#xff0c;一些常見的優化措施如下&#xff1a; 1&#xff1a;限定數據的范圍 務必禁止不帶任何限制數據范圍條件的查詢語句。比如&#xff1a;我們當用戶在查詢訂單歷史的時候&#xff0c;我們可以控制在一個…

【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 先注冊一個賬…