embedding.d_model不是transformer_utils.py文件的源码吗,为什么说没有这个属性呢
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import math
import matplotlib.pyplot as plt
import numpy as np
import copy
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
# 构建Embedding类来实现文本嵌入层
class Embeddings(nn.Module):
def __init__(self,embedding_dim,vocab):
# embedding_dim:词嵌入的维度
# vocab:词表的大小
super(Embeddings, self).__init__()
# 定义Embedding层
self.lut=nn.Embedding(vocab,embedding_dim)
# 将参数传入类中
self.embedding_dim=embedding_dim
def forward(self, x):
# x:代表输入进模型的文本通过词汇映射后的数字张量
return self.lut(x)* math.sqrt(self.embedding_dim)
embedding_dim=512
vocab=1000
x=Variable(torch.LongTensor([[100,2,421,508],[491,998,1,221]]))
emb=Embeddings(embedding_dim,vocab)
embr=emb(x)
# print("embr:",embr)
# print(embr.shape)
# 构建位置编码器的类
class PositionalEncoding(nn.Module):
def __init__(self,embedding_dim,dropout,max_len=5000):
# embedding_dim:代表词嵌入的维度
#droput: 代表Dropout 层的置零比率
#max_len:代表每隔句子的最大长度
super(PositionalEncoding, self).__init__()
#实例化Dropout
self.dropout=nn.Dropout(p=dropout)
#初始化一个位置编码矩阵,大小是max_len*embedding_dim
pe=torch.zeros(max_len,embedding_dim)
#初始化一个绝对值矩阵,max_len*1
position=torch.arange(0.0,max_len).unsqueeze(1)
#定义一个变化矩阵div_term,跳跃式的初始化
div_term=torch.exp(torch.arange(0.0,embedding_dim,2)*-(math.log(10000.0)/embedding_dim))
#将前面定义的变化矩阵进行奇数,偶数的分别赋值
pe[:,0::2]=torch.sin(position*div_term)
pe[:,1::2]=torch.cos(position*div_term)
# 将二维张量扩充成三维张量
pe=pe.unsqueeze(0)
# 将位置编码矩阵注册成模型的buffer,这个buffer不是模型中的参数,不跟随优化器同时更新
# 注册成buffer后我们就可以在模型保存后重新加载的时候,将这个位置编码器和模型参数一同加载进来
self.register_buffer('pe',pe)
def forward(self, x):
# x:代表文本序列的词嵌入表示
# 首先明确pe的编码太长了,将第二个维度,也就是max_len对应的那个维度缩小成x的句子长度同等的长度
x=x+Variable(self.pe[:,:x.size(1)],requires_grad=False)
return self.dropout(x)
embedding_dim=512
dropout=0.1
max_len=60
x=embr
pe=PositionalEncoding(embedding_dim,dropout,max_len)
pe_result=pe(x)
# print(pe_result)
# print(pe_result.shape)
# 设置一个画布
# plt.figure(figsize=(15,5))
#
# # 实例化PositionalEncoding类对象,词嵌入维度给20,置零比率设置为0
# pe=PositionalEncoding(20,0)
# # 向pe中传入一个全零初始化的x,相当于展示pe
# y=pe(Variable(torch.zeros(1,100,20)))
# plt.plot(np.arange(100),y[0,:,4:8].data.numpy())
# plt.legend(["dim %d"%p for p in [4,5,6,7]])
# print(np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]],k=-1))
# print(np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]],k=0))
# print(np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]],k=1))
# 构建掩码张量的函数
def subsequent_mask(size):
# size:代表掩码张量后两个维度,形成一个方阵
attn_shape=(1,size,size)
# 使用np.ones()先构建一个全1的张量,然后利用np.triu()形成上三角矩阵
subsequent_mask=np.triu(np.ones(attn_shape),k=1).astype('uint8')
#使得这个三角矩阵反转
return torch.from_numpy(1-subsequent_mask)
size=5
sm=subsequent_mask(size)
# print("sm:",sm)
# plt.figure(figsize=(5,5))
# plt.imshow(subsequent_mask(20)[0])
x=Variable(torch.randn(5,5))
# print(x)
mask=Variable(torch.zeros(5,5))
# print(mask)
y=x.masked_fill(mask==0,-1e9)
# print(y)
def attention(query,key,value,mask=None,dropout=None):
# query,key,value:代表注意力的三个输入张量
# mask:掩码张量
# dropout:传入的Dropout实例化对象
# 首先将query的最后一个维度提取出来,代表的是词嵌入的维度
d_k=query.size(-1)
# 按照注意力计算公式,将query和key的转置进行矩阵乘法,然后除以缩放稀疏
scores=torch.matmul(query,key.transpose(-2,-1))/math.sqrt(d_k)
# 判断是否使用掩码张量
if mask is not None:
# 利用masked_fill方法,将掩码张量和0进行位置的意义比较,如果等于0,替换成一个非常小的数
scores=scores.masked_fill(mask == 0, -1e9)
# 对scores的最后一个维度上进行softmax操作
p_attn=F.softmax(scores,dim=-1)
# 判断是否使用dropout
if dropout is not None:
p_attn=dropout(p_attn)
# 最后一步完成p_attn和value张量的乘法,并返回query注意力表示
return torch.matmul(p_attn,value),p_attn
query=key=value=pe_result
mask=Variable(torch.zeros(2,4,4))
attn,p_attn=attention(query, key, value,mask=mask)
# print('attn:',attn)
# print(attn.shape)
# print('p_attn',p_attn)
# print(p_attn.shape)
# x=torch.randn(4,4)
# # print(x.size())
# y=x.view(16)
# # print(y.size())
# z=x.view(-1,8)
# # print(z.size())
#
# a=torch.randn(1,2,3,4)
# print(a.size())
# print(a)
# b=a.transpose(1,2)
# print(b.size())
# print(b)
# c=a.view(1,3,2,4)
# print(c.size())
# print(c)
# 首先需要定义克隆函数,因为在多头注意力机制的实现中,用到多个结构相同的线性层
# 我们将使用clone函数将他们一同初始化在一个网络层列表对象中,之后的结构中也会使用到该函数
def clones(module,N):
# module:表示要克隆的目标网络层,N代表需要克隆的数量
# 然后将其放在nn.ModuleList类型的列表中存放
return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])
#构建多头注意力机制
class MultiHeadAttention(nn.Module):
def __init__(self,head,embedding_dim,dropout=0.1):
super(MultiHeadAttention,self).__init__()
# 首先使用一个测试中常用的assert语句,判断h是否能被d_model整除
#这是因为我们之后要给每个头分配等量的词特征,也就是embedding_dim/head个
assert embedding_dim%head==0
# 得到每个头获得的分割词向量维度d_k
self.d_k=embedding_dim//head
# 传入头数h
self.head=head
self.embedding_dim=embedding_dim
# 然后获得线性层对象,通过nn的Linear实例化,它的内部变化矩阵是embedding_dim X embedding_dim
# 多头注意力中,Q,K,V各需要一个,最后拼接的矩阵还需要一个
self.linears=clones(nn.Linear(embedding_dim,embedding_dim),4)
# self.attn为none,它代表最后得到的注意力张量,现在还没有结果所以为None
self.attn=None
# 最后就是一个self.dropout对象,它通过nn中的Dropout实例化而来,置零比率为传进来的参数dropout
self.dropout=nn.Dropout(p=dropout)
def forward(self, query,key,value,mask=None):
# 最后一个是注意力机制中可能需要的mask掩码张量,默认是None
if mask is not None:
# 使用unsqueeze拓展维度,代表多头中的第n头
mask=mask.unsqueeze(1)
# 得到batch_size,它是query尺寸的第1个数字,代表有多少条样本
batch_size=query.size(0)
# 首先使用zip将网络层和输入数据连接在一起,模型的输出利用view和transpose进行维度和形状的改变
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)
# 得到没个头的计算结果是4维张量,需要进行形状的转换
# 前面已经将1,2两个维度进行过转置,在这里要重新转置回来
# 注意:经历了transpose()方法后,必须使用contiguous方法,不然无法使用view()方法
x=x.transpose(1,2).contiguous().view(batch_size,-1,self.head*self.d_k)
#最后将x输入线性层列表中的最后一个线性层中进行处理,得到最终的多头注意力结构输出
return self.linears[-1](x)
#实例化若干参数
head=8
embedding_dim=512
dropout=0.2
# 若干参数的初始化
query=key=value=pe_result
mask=Variable(torch.zeros(2,4,4))
mha=MultiHeadAttention(head,embedding_dim,dropout)
mha_result=mha(query,key,value,mask)
# print('mha_result',mha_result)
# print(mha_result.shape)
# 通过类PositionwiseFeedForward来实现前馈全连接层
class PositionwiseFeedForward(nn.Module):
def __init__(self,d_model,d_ff,dropout):
#d_model:代表词嵌入的维度,同时也是两个线性层的输入维度和输出维度
# d_ff:代表第一个线性层的输出维度和第二个线性层的输入维度
super(PositionwiseFeedForward, self).__init__()
#定义两层全连接的线性层
# 首先使用nn实例化两个线性层对象,self.w1和self.w2
# 参数分别是d_model,d_ff和d_ff,d_model
self.w1=nn.Linear(d_model,d_ff)
self.w2=nn.Linear(d_ff,d_model)
# 然后使用nn的Dropout实例化了对象的self.dropout
self.dropout=nn.Dropout(dropout)
def forward(self, x):
# 首先经过第一个线性层,然后使用Funtional中的relu函数进行激活
# 再使用dropout进行随机置0,最后通过第二个线性层w2,返回最终结果
return self.w2(self.dropout(F.relu(self.w1(x))))
d_model=512
d_ff=64
dropout=0.2
x=mha_result
ff=PositionwiseFeedForward(d_model,d_ff,dropout)
ff_result=ff(x)
# print("ff_result",ff_result)
# print(ff_result.shape)
# 通过LayerNorm实现规范化层的类
class LayerNorm(nn.Module):
def __init__(self,features,eps=1e-6):
# features:代表词嵌入的维度
# eps:一个足够小的正数,用来在规范化计算公式的分母中,防止除0操作
super(LayerNorm, self).__init__()
self.a2=nn.Parameter(torch.ones(features))
self.b2=nn.Parameter(torch.zeros(features))
self.eps=eps
def forward(self, x):
# 首先对x进行最后一个维度上的求均值操作,同时保持输出的维度和输入维度一致
mean=x.mean(-1,keepdim=True)
# 对x进行最后一个维度上的求标准差的操作,同时保持输出维度和输入维度一致
std=x.std(-1,keepdim=True)
# 按照规范化公式进行计算并返回
return self.a2*(x-mean)/(std+self.eps)+self.b2
features=d_mode=512
eps=1e-6
x=ff_result
ln=LayerNorm(features,eps)
ln_result=ln(x)
# print("ln_result",ln_result)
# print(ln_result.shape)
# 使用SublayerConnection来实现子层连接结构的类
class SublayerConnection(nn.Module):
def __init__(self,size,dropout=0.1):
# size:表示词嵌入的维度
super(SublayerConnection, self).__init__()
# 实例化sekf.norm
self.norm=LayerNorm(size)
self.dropout=nn.Dropout(p=dropout)
self.size=size
def forward(self, x,sublayer):
#因为存在跳跃连接,所以是将输入的x与dropout后的子层输出结果相加作为最终的子层连接输出
# 残差连接
return x+self.dropout(sublayer(self.norm(x)))
size=512
dropout=0.2
head=8
d_model=512
# 令x为位置编码器的输出
x=pe_result
mask=Variable(torch.zeros(2,4,4))
#假设子层中装的是多头注意力层,实例化这个类
self_attn=MultiHeadAttention(head,d_model)
#使用lambda获得一个函数的子层
sublayer=lambda x:self_attn(x,x,x,mask)
sc=SublayerConnection(size,dropout)
sc_result=sc(x,sublayer)
# print("sc_result",sc_result)
# print(sc_result.shape)
# 使用EncoderLayer类实现编码器层
class EncoderLayer(nn.Module):
def __init__(self,size,self_attn,feed_forward,dropout=0.1):
super(EncoderLayer, self).__init__()
# 首先将self_attn和feeed_forward传入其中
self.self_attn=self_attn
self.feed_forward=feed_forward
self.size = size
#编码器层有两个子层连接结构,所以使用clonees函数进行克隆
self.sublayer=clones(SublayerConnection(size,dropout),2)
def forward(self, x,mask):
# 首先通过第一个子层连接结构,其中包含多头自注意力子层
# 然后通过第二个子层连接结构,其中包含前馈全连接网络,最返回结果
x=self.sublayer[0](x,lambda x:self.self_attn(x,x,x,mask))
return self.sublayer[1](x,self.feed_forward)
size=d_model=512
head=8
d_ff=64
x=pe_result
dropout=0.2
self_attn=MultiHeadAttention(head,d_model)
ff=PositionwiseFeedForward(d_model,d_ff,dropout)
mask=Variable(torch.zeros(2,4,4))
el=EncoderLayer(size,self_attn,ff,dropout)
el_result=el(x,mask)
# print(el_result)
# print(el_result.shape)
# 使用Encoder类来实现编码器
class Encoder(nn.Module):
def __init__(self,layer,N):
# layer:表示编码器层
# N:表示编码器层的个数
super(Encoder, self).__init__()
# 首先使用clones函数克隆N个编码层放在self.layers中
self.layers=clones(layer,N)
# 再初始化一个规范化层,它将用在编码器的最后面
self.norm=LayerNorm(layer.size)
def forward(self, x,mask):
# 首先对我们克隆的编码器层进行循环,每次都会得到一个新的x
# 循环的过程相当于输出的x经过了N个编码器层的处理
# 最后通过规范化层的对象self.norm进行处理
for layer in self.layers:
x=layer(x,mask)
return self.norm(x)
#第一个实例化参数layer,它是一个编码器层的实例化对象,因此需要传入编码器层的参数
# 因为编码器层中的子层是不共享的,因此需要使用深度拷贝各个对象
size=512
head=8
d_model=512
d_ff=64
dropout=0.2
c=copy.deepcopy
attn=MultiHeadAttention(head,d_model)
ff=PositionwiseFeedForward(d_model,d_ff,dropout)
layer=EncoderLayer(size,c(attn),c(ff),dropout)
N=8
mask=Variable(torch.zeros(2,4,4))
en=Encoder(layer,N)
en_result=en(x,mask)
# print(en_result)
# print(en_result.shape)
# 使用DecoderLayer的类实现解码器层
class DecoderLayer(nn.Module):
def __init__(self,size,self_attn,src_attn,feed_forward,dropout):
# self_attn:多头自注意力对象,这个自注意力机制需要Q=K=V
# src_attn:多头注意力对象,这个自注意力机制需要Q!=K=V
super(DecoderLayer, self).__init__()
self.size=size
self.self_attn=self_attn
self.src_attn=src_attn
self.feed_forward=feed_forward
# 按照结构图使用clones函数克隆三个子层连接对象
self.sublayer=clones(SublayerConnection(size,dropout),3)
def forward(self, x,memory,source_mask,target_mask):
# 来自编码器层的语义存储变量mermory,以及源数据掩码张量和目标数据掩码张量
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)
head=8
size=d_model=512
d_ff=64
dropout=0.2
self_attn=src_attn=MultiHeadAttention(head,d_model,dropout)
ff=PositionwiseFeedForward(d_model,d_ff,dropout)
#x是来自目标数据的词嵌入表示,但形势和源数据的词嵌入表示相同
x=pe_result
# memory是来自编码器的输出
memory=en_result
#实际中source_mask和target_mask并不相同,这里为了计算方便使它们都是mask
mask=Variable(torch.zeros(2,4,4))
source_mask=target_mask=mask
dl=DecoderLayer(size,self_attn,src_attn,ff,dropout)
dl_result=dl(x,memory,source_mask,target_mask)
# print(dl_result)
# print(dl_result.shape)
# 使用类Decoder来实现解码器
class Decoder(nn.Module):
def __init__(self,layer,N):
super(Decoder, self).__init__()
# 先使用clones函数克隆N个layer,然后实例化 一个规范化层
# 因为数据走过了所有的解码器层后最后要做规范化处理
self.layers=clones(layer,N)
self.norm=LayerNorm(layer.size)
def forward(self, x,memory,source_mask,target_mask):
#对每个层进行循环,这个循环就是变量x通过每一个层的处理
#得到最后的结果,再进行一次规范化返回即可
for layer in self.layers:
x=layer(x,memory,source_mask,target_mask)
return self.norm(x)
size=d_model=512
head=8
d_ff=64
dropout=0.2
c=copy.deepcopy
attn=MultiHeadAttention(head,d_model)
ff=PositionwiseFeedForward(d_model,d_ff,dropout)
layer=DecoderLayer(d_model,c(attn),c(attn),c(ff),dropout)
N=8
x=pe_result
memory=en_result
mask=Variable(torch.zeros(2,4,4))
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)
# 将线性层和softmax计算层一起实现,因为二者的共同目标是生成最后的结构
# 因此把类的名字叫做Generator,生成器
class Generator(nn.Module):
def __init__(self,d_model,vocab_size):
super(Generator, self).__init__()
# 先使用nn中的预定义线性层进行实例化,得到一个对象self.project等待使用
# 这个线性层的参数有两个,就是初始化函数传进来的两个参数:d_model,vocab_size
self.project=nn.Linear(d_model,vocab_size)
def forward(self, x):
# 在函数中,使用上一步的得到的self.project对x进行线性变化
# 然后使用F中已经实现的log_softmax进行softmax处理
# 在这里之所以使用log_softmax是因为和pytorch版本的损失函数有关
# log_softmax就是对softmax的结果又取了对数,因为对数函数是单调递增函数
# 因此对最终我们取最大的概率值没有影响,最后返回结果即可
return F.log_softmax(self.project(x),dim=-1)
m=nn.Linear(20,30)
input=torch.randn(128,20)
output=m(input)
# print(output.size())
d_model=512
vocab_size=1000
x=de_result
gen=Generator(d_model, vocab_size)
gen_result=gen(x)
# print(gen_result)
# print(gen_result.shape)
# 使用EncoderDecoder类来实现编码器-解码器结构
class EncoderDecoder(nn.Module):
def __init__(self,encoder,decoder,source_embed,target_embed,generator):
super(EncoderDecoder, self).__init__()
self.encoder=encoder
self.decoder=decoder
self.src_embed=source_embed
self.tgt_embed=target_embed
self.generator=generator
def forward(self, source,target,source_mask,target_mask):
# 将source,source_mask传入编码函数,得到结果后
# 与source_mask,target和target_mask一起传给解码函数
return self.decode(self.encode(source,source_mask),source_mask,target,target_mask)
def encode(self,source,source_mask):
#使用src_embed对source做处理,然后和source_mask一起传给self.encoder
return self.encoder(self.src_embed(source),source_mask)
def decode(self,memory,source_mask,target,target_mask):
#使用tgt_embed对target做处理,然后和source_mask,target_mask,memory一起传给self.decoder
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(torch.LongTensor([[100,2,421,508],[491,998,1,221]]))
#假设src_mask和tgt_mask相同,实际中并不相同
source_mask=target_mask=Variable(torch.zeros(2,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)
# 模型构建
def make_model(source_vocab,target_vocab,N=6,d_model=512,d_ff=2048,head=8,dropout=0.1):
#首先使用一个深度拷贝命令,很多结构都需要进行深度拷贝
#来保证他们之间相互独立,不受干扰
c=copy.deepcopy
attn=MultiHeadAttention(head,d_model)
ff=PositionwiseFeedForward(d_model,d_ff,dropout)
#实例化前馈全连接层,得到对象position
position=PositionalEncoding(d_model,dropout)
#根据结构图,最外层是EncoderDecoder,在EncoderDecoder中,
#分别是编码器层,解码器层,源数据Embedding层和位置编码组成的有序结构
#目标数据Embedding层和位置编码组成的有序结构,以及类别生成器层
#在编码器层中有attention子层以及前馈全连接子层
#在解码器层中有两个attention子层以及前馈全连接层
model=EncoderDecoder(Encoder(EncoderLayer(d_model,c(attn),c(ff),dropout),N),
Decoder(DecoderLayer(d_model,c(attn),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))
# 模型构建完成后,接下来 就是初始化模型中的参数,比如线性层中的变化矩阵
# 这里一但判断参数的维度大于1,则会将其初始化成一个服从均匀分布的矩阵
for p in model.parameters():
if p.dim()>1:
nn.init.xavier_uniform(p)
return model
#结果服从均匀分布U(-a,a)
w=torch.empty(3,5)
w=nn.init.xavier_uniform_(w,gain=nn.init.calculate_gain('relu'))
# print(w)
source_vocab=11
target_vocab=11
N=6
#其他参数使用默认值
from pyitcast.transformer_utils import Batch
from pyitcast.transformer_utils import get_std_opt
from pyitcast.transformer_utils import LabelSmoothing
from pyitcast.transformer_utils import SimpleLossCompute
from pyitcast.transformer_utils import run_epoch
from pyitcast.transformer_utils import greedy_decode
def data_generator(V,batch_size,num_batch):
for i in range(num_batch):
#使用numpy中的random.randint()来随机生成[1,V)
#分布的形状(batch,10)
data=torch.from_numpy(np.random.randint(1,V,size=(batch_size,10)))
# 将数据的第一列全部设置为1,作为起始标志
data[:,0]=1
#因为是copy任务,所以源数据和目标数据完全一致
#设置参数requires_grad=False,样本的参数不需要参与梯度的计算
source=Variable(data,requires_grad=False)
target=Variable(data,requires_grad=False)
yield Batch(source,target)
V=11
batch_size=20
num_batch=30
# if __name__ == '__main__':
# res=make_model(source_vocab,target_vocab,N)
# print(res)
# 使用make_model()函数获得模型的实例化对象
model=make_model(V,V,N=2)
#使用工具包get_std_opt获得模型的优化器
model_optimizer=get_std_opt(model)
#使用工具包LabelSmoothing获得标签平滑对象
criterion=LabelSmoothing(size=V,padding_idx=0,smoothing=0.0)
#使用工具包SimpleLossCompute获得利用标签平滑的结果得到的损失计算方法
loss=SimpleLossCompute(model.generator,criterion,model_optimizer)
# crit=LabelSmoothing(size=5,padding_idx=0,smoothing=0.5)
#
# predict=Variable(torch.FloatTensor([[0,0.2,0.7,0.1,0],
# [0,0.2,0.7,0.1,0],
# [0,0.2,0.7,0.1,0]]))
# target=Variable(torch.LongTensor([2,1,0]))
# crit(predict,target)
# plt.imshow(crit.true_dist)
def run(model,loss,epochs=10):
for epoch in range(epochs):
# 模型进入训练模式,所有的参数将会被更新
model.train()
#训练时,传入的batch_size是20
run_epoch(data_generator(V,8,20),model,loss)
#训练结束后,进入评估模式,所有的参数固定不变
model.eval()
# 评估时,传入的batch_size是5
run_epoch(data_generator(V,8,5),model,loss)
if __name__ == '__main__':
run(model,loss)
运行之后就报错了
D:/Deep_Project/Transformer_learning/transformer.py:589: UserWarning: nn.init.xavier_uniform is now deprecated in favor of nn.init.xavier_uniform_.
nn.init.xavier_uniform(p)
Traceback (most recent call last):
File "D:\Anaconda\envs\tf1\lib\site-packages\IPython\core\interactiveshell.py", line 3343, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "", line 1, in
runfile('D:/Deep_Project/Transformer_learning/transformer.py', wdir='D:/Deep_Project/Transformer_learning')
File "C:\Program Files\JetBrains\PyCharm 2021.3.3\plugins\python\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile
pydev_imports.execfile(filename, global_vars, local_vars) # execute the script
File "C:\Program Files\JetBrains\PyCharm 2021.3.3\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "D:/Deep_Project/Transformer_learning/transformer.py", line 638, in
model_optimizer=get_std_opt(model)
File "D:\Anaconda\envs\tf1\lib\site-packages\pyitcast\transformer_utils.py", line 91, in get_std_opt
return NoamOpt(model.src_embed[0].d_model, 2, 4000,
File "D:\Anaconda\envs\tf1\lib\site-packages\torch\nn\modules\module.py", line 535, in __getattr__
type(self).__name__, name))
AttributeError: 'Embeddings' object has no attribute 'd_model'
这是什么问题,难道是版本问题吗???