基于copy任务测试Transformer运行时的两项报错

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_pembedself.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  # 修改这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值