报错源于张量dtype不一致:torch.tensor([1,2,3])默认int64,torch.randn(3)默认float32,相加失败;应通过print(x.dtype)定位logits(需float32)和target(分类任务需long),预处理时显式指定dtype与device。

PyTorch张量相加报错:expected scalar type Float but found Long
因为 PyTorch 的张量运算(包括 +)要求参与运算的张量 dtype 完全一致,而 torch.tensor([1, 2, 3]) 默认生成 torch.int64,torch.randn(3) 默认是 torch.float32,两者直接相加必然失败。
如何快速定位哪个张量类型错了?
别猜,直接在出错行前后加 print(x.dtype):
- 检查
model(input)输出的logits类型——必须是float32(否则和 float 权重无法运算) - 检查
target类型——分类任务中应为torch.long,但它是用来索引的,不能参与加法 - 特别注意 DataLoader 外手动构造的标签:
torch.tensor([0, 1, 1])→int64;torch.tensor([0.0, 1.0, 1.0])→float32,后者在加法中“看似能用”,但会破坏语义
为什么 .float() 和 .long() 不能乱用?
类型转换不是格式化,而是语义重解释:
-
label.long()合理:把浮点标签转为整数索引(前提是值确实是整数) -
logits.float()多余:它本来就是float32,强行调用无害但暴露逻辑漏洞 -
mask.float()常见:布尔掩码用于乘法时需float32,但mask.long()会把True→1、False→0,虽数值等价,却丢失了 bool 的语义意图 -
loss_input.long()危险:比如把交叉熵的输入 logits 转成 long,直接破坏梯度流
设备与类型要同步处理,不能只改一个
x.to('cuda') 只迁设备,不改类型;x.float() 只改类型,不迁设备。但实际训练中二者常需同时满足:
- 模型参数在 GPU 上且是
float32,输入也必须是float32+cuda - 错误写法:
x = x.cuda(); x = x.float()——顺序无关,但两次调用冗余 - 推荐写法:
x = x.to(device, dtype=torch.float32),一次到位,且device可动态切换 CPU/GPU - 尤其注意:
torch.zeros()或torch.empty()创建新张量时,务必显式传dtype和device,否则默认在 CPU 上生成float32,和 GPU 模型一加就崩
dtype,或新张量没继承上下文的 device 和 dtype。每次新建张量,都要问一句:它该在哪?它该是什么类型?Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











