这个报错是你做单输出二分类的时候,损失函数要求 target 标签是 long 类型,但你的标签现在是 float 类型,而且你用的是 CrossEntropyLoss,单输出(N,1)的结构本身和 CrossEntropyLoss 设计就不匹配,很多人只想单纯改标签类型来解决,这里要先说清楚:只改标签类型大概率没法彻底跑通,要先分清损失函数对应的标签格式,CrossEntropyLoss 做二分类一般要求输出是 2 个通道,标签 long;而单输出二分类标准搭配是 BCEWithLogitsLoss,它反而要求标签是 float,这就是这个坑最容易踩的地方,报错文字提示要 Long,是因为当前代码里写的损失函数是 CrossEntropyLoss,不是 BCE 系列损失。
一、报错根源清单
- 损失函数和模型输出不匹配:模型最后一层只输出 1 个值(单输出二分类),但是 loss 用了 CrossEntropyLoss,CrossEntropyLoss 默认期待类别索引 long 标签
- 标签 dtype 不对:传给 CrossEntropyLoss 的 target 是 float,触发 Expected scalar type Long 提示
- 形状问题:标签 shape 是 (N,1) 二维,CrossEntropyLoss 的类别索引标签一般要求一维 (N,)
- 混淆两套二分类写法:一套是 2 路输出 + CrossEntropyLoss+long 标签;一套是单路输出 + BCEWithLogitsLoss+float 标签,两套不能混用
二、两种修复方案(包含只改标签类型的方案)
方案 1:保留 CrossEntropyLoss,只改标签类型 + 调整输出(对应报错提示的 long 要求)
- 标签转 long:target = target.long ()
- 标签压平一维:target = target.squeeze (-1)
- 模型输出改成 2 通道,比如最后一层 nn.Linear (hidden_dim,2)
缺点:改动了模型输出层,不是纯单输出写法
方案 2:维持单输出二分类(推荐,不用改模型输出)
- 损失函数换成 BCEWithLogitsLoss
- 标签改成 float:target = target.float ()
- 保证标签 shape 和模型输出 shape 一致,都是 (N,1)
这个就是标准单输出二分类写法,不会出现这个 Long 报错
三、两种写法对照表格
| 方案 | 模型输出 shape | 损失函数 | target 要求类型 | target 形状 | 是否会报这个 Long 错误 |
|---|---|---|---|---|---|
| 二分类两路输出 | (batch,2) | CrossEntropyLoss | long | (batch,) | 修复后不报 |
| 单输出二分类 | (batch,1) | BCEWithLogitsLoss | float | (batch,1) | 不会报 |
| 错误混用 | (batch,1) | CrossEntropyLoss | float | (batch,1) | 直接触发该报错 |
四、校验步骤
- 打印信息确认:print (output.shape, target.shape, target.dtype),看清楚输出、标签形状和类型
- 如果你坚持只改标签为 long、不改模型输出,就算类型不报错,后面会出现 IndexError,因为类别数只有 1,标签 1 越界
- 优先推荐单输出搭配 BCEWithLogitsLoss,这才是单输出二分类原生写法,不用强行适配 CrossEntropyLoss
五、总结
报错文字只是告诉你 CrossEntropyLoss 需要 long 标签,但单输出二分类场景下,单纯把标签改成 long 是治标不治本,还会引出索引越界的新报错;想要保留单输出结构,核心是更换损失函数为 BCEWithLogitsLoss,再把标签转为 float;只有模型输出改成两个类别通道的时候,才适合把标签转 long 继续用 CrossEntropyLoss。
【相关 FAQ】
问题 1:Expected scalar type Long for argument 2 target,单输出二分类只改标签类型能修好吗?
回答 1:Expected scalar type Long for argument 2 target 这个报错,单输出二分类只把标签改成 long,只能消除类型报错,大概率会出现标签索引越界,因为 CrossEntropyLoss 不适合单输出的结构,不推荐只改标签类型。
问题 2:单输出二分类遇到 Expected scalar type Long for argument 2 target,BCEWithLogitsLoss 标签要 long 还是 float?
回答 2:单输出二分类搭配 BCEWithLogitsLoss 时,遇到 Expected scalar type Long for argument 2 target,标签不能用 long,标签必须是 float 类型,和模型输出 shape 对齐。
问题 3:CrossEntropyLoss 报 Expected scalar type Long for argument 2 target,二分类标签 long 之后还要调整什么?
回答 3:CrossEntropyLoss 报 Expected scalar type Long for argument 2 target,标签转 long 之后,二分类模型输出要改成 2 个 logit 通道,标签 shape 压缩成一维,标签值只能是 0 和 1。
【参考资料】
[2026-01-16](RuntimeError Expected object of scalar type Long but got scalar type Float PyTorch BCELoss)CodeGenes
[2025-11-24](PyTorch 二元分类损失 BCEWithLogitsLoss 常见陷阱)Runebook
[2023-07-20](Replacing CrossEntropyLoss with BCEWithLogitsLoss)PyTorch 论坛
[2022-02-04](RuntimeError 0D or 1D target tensor expected)PyTorch 论坛
【免责声明】
本文内容仅针对 PyTorch 该标签类型报错场景提供调试方案,不同 PyTorch 版本、自定义数据集、Trainer 封装代码存在差异,标签类型、损失函数搭配方案仅供调试参考,不保证适配全部训练代码,因修改标签类型、更换损失函数造成的训练不收敛、梯度异常等问题自行承担风险。
本文来自作者[零矢映象使]投稿,不代表乌兰科技网立场,如若转载,请注明出处:https://www.wlcbnews.com/rgzn/202611/630.html
评论列表(4条)
我是乌兰科技网的签约作者“零矢映象使”!
希望本篇文章《Expected scalar type Long for argument 2 target 单输出二分类标签类型报错修复》能对你有所帮助!
本站[乌兰科技网]内容主要涵盖:互联网行业的追踪与探索
本文概览:这个报错是你做单输出二分类的时候,损失函数要求 target 标签是 long 类型,但你的标签现在是 float 类型,而且你用的是 CrossEntropyLoss,单输出(N,1)的结构本身和 CrossEntropyLoss 设计就不匹配,很多人只想单纯改标签类型来解决,这里要先说清楚:只改标签类型大概率没法彻底跑通,要先分清损失函数对应的标签格式,CrossEntropyLoss 做二分类一般要求输出是 2 个通道,标签 long;而单输出二分类标准搭配是 BCEWithLogitsLoss,它反而要求标签是 float,这就是这个坑最容易踩的地方,报错文字提示要 Long,是因为当前代码里写的损失函数是 CrossEntropyLoss,不是 BCE 系列损失。