先把当时的情况摆出来。开启半精度训练后报 RuntimeError: expected scalar type Half but found Float,位置在自定义 loss 计算里。
原因不止一个,得分开看。自定义损失函数里新建的张量默认是 float32。也可能是模型部分子模块没有跟随 half 转换。
少数情况下是标签张量是整型,与预测结果类型不一致。不容易想到的是,混合精度下 autocast 范围没有覆盖到该段代码。
先确认模型参数的实际类型
python -c "import torch;print(next(model.parameters()).dtype)"
再往下用 autocast 包住前向与损失计算
with torch.autocast('cuda', dtype=torch.float16): loss = criterion(out, y)
手工创建张量时显式指定类型
weight = torch.tensor([1.0], device='cuda', dtype=torch.float16)
等前面都确认过,再统一标签类型后再计算损失
y = y.long(); out = out.float()
同一份数据我导出了两份,一份留底,一份拿来试。
别只看报错消失,验证要多做一步。训练能正常反向传播,loss 数值稳定,不再出现类型不匹配的报错。
容易忽略的是,autocast 只自动处理已知算子,自定义函数里的常量张量不会被转换,这类报错几乎都出在自己写的计算里。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。