原帖聊天机器人在 CrossEntropyLoss(outputs, labels) 失败;报错中的 Int 指向 int32 目标:
RuntimeError: "nll_loss_forward_reduce_cuda_kernel_2d_index" not implemented for 'Int'
Int 与 Long 在这里不是同一种整数
报错内核名已经指向分类索引损失,Int 通常对应 torch.int32,long 对应 int64。原题把标签移到 device 时没有指定 dtype,因而可能保留 NumPy 导入的 int32。应转换类别索引,词袋特征仍按模型浮点类型处理。
CUDA 上的分类索引目标需要符合该损失的类型约定。把标签移动到 GPU 不会自动把 int32 转成 long。
在损失前检查当前 batch:
print("josh050608")
print("outputs:", outputs.shape, outputs.dtype, outputs.device)
print("labels:", labels.shape, labels.dtype, labels.device)
print("range:", labels.min().item(), labels.max().item())
若 labels 确实是单标签分类的整数类别编号,取 batch 后显式转换:
labels = labels.to(device=outputs.device, dtype=torch.long)
assert labels.ndim == 1
assert 0 <= labels.min().item() and labels.max().item() < outputs.shape[1]
loss = criterion(outputs, labels)
本段需已有 import torch。更早也可以在构造数据集时把 NumPy 标签转为 int64。不要对词袋浮点特征和整个模型一起调用 .long();模型输出应保留浮点原始 logits。
原帖的缩减代码还把 X_train 展示成空数组,并省略了 Dataset 的取样方法,这不足以单独重跑完整训练。修复类型后若出现范围或空数据错误,要回到实际标签编码和数据集构造检查。
验证同一个 batch 能完成前向、loss 与 backward,再检查标签映射与 output_size=len(tags) 一致。报错消失并不保证训练数据与意图标签已经正确配对。
在数据入口固定类型,避免每批反复猜测
下面用合成词袋和意图编号完成一步训练,CPU 即可运行。它保留原题隐藏层宽度 47,类别数仅为演示设成 3,不代替真实 tags:
import numpy as np
import torch
from torch import nn
features = torch.from_numpy(np.arange(24, dtype=np.float32).reshape(4, 6) / 24)
raw_labels = np.array([0, 1, 2, 1], dtype=np.int32)
labels = torch.from_numpy(raw_labels.astype(np.int64))
model = nn.Sequential(nn.Linear(6, 47), nn.ReLU(), nn.Linear(47, 3))
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
optimizer.zero_grad()
outputs = model(features)
assert labels.dtype == torch.long and labels.shape == (4,)
assert labels.min() >= 0 and labels.max() < outputs.shape[1]
loss = nn.CrossEntropyLoss()(outputs, labels)
loss.backward()
assert model[0].weight.grad is not None
optimizer.step()
print("labels/output/loss:", labels.dtype, outputs.shape, loss.item())
真实 Dataset 最好同时返回一条词袋特征和相应类别编号,loader 打乱时仍保持配对。labels.to(device) 只改变设备;若数据入口没固定 int64,可在取 batch 时显式指定 dtype=torch.long,但要接住返回值。
原帖缩减代码中 X_train 为空,Dataset 方法也不完整,因此无法据它直接重跑全部训练。需要回到真实生成过程确认样本数量、tags 映射与 output_size;标签类型修好后出现空数据或范围错误,应继续处理,不能把类型转换当作完整训练正确性的证明。
参考:原始求助帖;技术依据:CrossEntropyLoss(2.5)、PyTorch 数据加载(2.5)。