1.get_std_opt
函数显示没有某些属性
Traceback (most recent call last):
File "H:\basetransformer\structure.py", line 557, in <module>
model_optimizer = get_std_opt(model)
^^^^^^^^^^^^^^^^^^
File "H:\anaconda3\envs\pytorch\Lib\site-packages\pyitcast\transformer_utils.py", line 91, in get_std_opt
return NoamOpt(model.src_embed[0].d_model, 2, 4000,
^^^^^^^^^^^^^^^
File "H:\anaconda3\envs\pytorch\Lib\site-packages\torch\nn\modules\module.py", line 1931, in __getattr__
raise AttributeError(
AttributeError: 'EncoderDecoder' object has no attribute 'src_embed'. Did you mean: 'source_pembed'?
EncoderDecoder' object has no attribute 'src_embed'. Did you mean: 'source_pembed'?
从错误信息来看,get_std_opt
函数仍然尝试访问 model.src_embed
,但你的 EncoderDecoder
类中没有定义 src_embed
属性
解决方法:
①修改 get_std_opt
调用:如果 get_std_opt
是第三方库提供的函数,无法修改其内部逻辑,可以通过动态调整属性名来适配你的模型结构。
# 获取 d_model
if hasattr(model, 'source_pembed'):
d_model = model.source_pembed[0].embedding_dim # 从 source_pembed 中获取 d_model
else:
raise AttributeError("Model does not have 'source_pembed' or 'src_embed' attribute.")
# 自定义 NoamOpt 优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0, betas=(0.9, 0.98), eps=1e-9)
model_optimizer = NoamOpt(d_model, 2, 4000, optimizer)
②修改 EncoderDecoder
类:如果 get_std_opt
是必须使用的函数,可以在 EncoderDecoder
类中添加一个 src_embed
属性,指向 source_pembed
。self.src_embed = source_pembed # 添加 src_embed 属性
class EncoderDecoder(nn.Module):
def __init__(self, encoder, decoder, source_pembed, target_pembed):
super(EncoderDecoder, self).__init__()
self.encoder = encoder
self.decoder = decoder
self.source_pembed = source_pembed
self.target_pembed = target_pembed
self.src_embed = source_pembed # 添加 src_embed 属性
def forward(self, source, target, source_mask, target_mask):
return self.decode(self.encode(source, source_mask), source_mask, target, target_mask)
def encode(self, source, source_mask):
return self.encoder(self.source_pembed(source), source_mask)
def decode(self, memory, source_mask, target, target_mask):
return self.decoder(self.target_pembed(target), memory, source_mask, target_mask)
2.RuntimeError: scatter(): Expected dtype int64 for index
解决方法:在生成训练数据时将dtype='int64'
def data_generator(V, batch, num_batch):
# 该函数用于随机生成数据,三个输入分别为:随机生成的数的最大值+1,batch是每次输送给模型更新参数的量,num_batch是一共输送多少次完成一轮
# 用for循环遍历num_batch
for i in range(num_batch):
# 先随机生成分布在(batch, 10)形状矩阵中的[1,V)的整数,在吧numpy形式的数据转成torch中tensor的形式
data = torch.from_numpy(np.random.randint(1, V, size=(batch, 10), dtype="int64"))
# 使data中第一列数字都为1,意为起始标志列,是为使解码器第一次解码时从该列开始
data[:, 0] =1
# copy任务时,源域和目标域数据一致,且不需要求梯度
source = Variable(data, requires_grad=False)
target = Variable(data, requires_grad=False)
# 使用Batch对source和target进行对应批次的掩码张量,使用yield返回
yield Batch(source, target)
3.IndexError: invalid index of a 0-dim tensor. Use `tensor.item()` in Python or `tensor.item<T>()` in C++ to convert a 0-dim tensor to a number”
解决方法:
修改 SimpleLossCompute
的 __call__
方法
打开 transformer_utils.py
文件,找到 SimpleLossCompute
类的 __call__
方法,将 loss.data[0]
修改为 loss.item()
。
class SimpleLossCompute:
def __init__(self, generator, criterion, opt=None, reduction='mean'):# 添加reduction
self.generator = generator
self.criterion = criterion
self.opt = opt
self.reduction = reduction # 添加reduction
def __call__(self, x, y, norm):
x = self.generator(x)
loss = self.criterion(x.contiguous().view(-1, x.size(-1)),
y.contiguous().view(-1))
loss = loss / norm
if self.opt is not None:
loss.backward()
self.opt.step()
self.opt.optimizer.zero_grad()
return loss.item() * norm # 修改这里