原帖用 [[1,0]] 作为占位标签,组批后又 squeeze,但仍将一整行类别向量传给旧版交叉熵:
RuntimeError: multi-target not supported at /pytorch/aten/src/THCUNN/generic/ClassNLLCriterion.cu:15
两列 one-hot 不是可被 squeeze 删除的单例维
原题用 [1,0] 当占位标签,组批后每样本仍有两个值。维度长度为 2 时 squeeze(1) 不做任何改变。若每样本只属于一个类别,应还原类别索引;若真正允许多个正类,则不能用 argmax 丢失信息。
squeeze(1) 只能删除长度为 1 的维度,不能把 [N,2] 的 one-hot 自动变成 [N] 类别编号。
在损失前检查 target 的实际维数:
print("josh050608")
print("output:", output.shape, output.dtype)
print("target:", target.shape, target.dtype)
print("example:", target[:2])
若确认每行恰有一个 1、表示互斥类别,可以先去掉原题多余的单例维,再按类别轴取索引:
one_hot = target.squeeze(1) if target.ndim == 3 else target
assert one_hot.ndim == 2 and one_hot.shape[1] == output.shape[1]
assert ((one_hot == 0) | (one_hot == 1)).all()
assert (one_hot.sum(dim=1) == 1).all()
class_ids = one_hot.argmax(dim=1).long()
loss = criterion(output, class_ids)
更直接是在 Dataset 中为每张图返回单个类别编号,DataLoader 会组成 [N]。真正的多标签任务不能用 argmax 丢掉其他正类,应改用相应的 BCE 目标。
原帖输出已经 log_softmax,可改为原始 logits 配 CrossEntropyLoss,或保留 log_softmax 配 NLLLoss。现代交叉熵支持同形状浮点软目标,但原帖历史接口与整型 one-hot 不能据此视为有效输入。
另外,HWC 图像变 CHW 应交换轴,不能用 reshape 重排颜色。占位标签只能验证流程,不代表模型学到了真实类别。验证目标形状、标签语义与一个训练 step 后,再换真实标注训练。
用合法 one-hot 验证转换,再拒绝多正类
下面是 CPU 合成分类例子,明确检查每行只有一个 1,再得到 [N] long 目标;不使用原题的占位标注训练真实模型:
import torch
from torch import nn
one_hot = torch.tensor([[1, 0], [0, 1], [1, 0]], dtype=torch.long)
assert one_hot.ndim == 2 and one_hot.shape[1] == 2
assert ((one_hot == 0) | (one_hot == 1)).all()
assert (one_hot.sum(dim=1) == 1).all()
class_ids = one_hot.argmax(dim=1).long()
head = nn.Linear(4, 2)
logits = head(torch.randn(3, 4))
loss = nn.CrossEntropyLoss()(logits, class_ids)
loss.backward()
assert head.weight.grad is not None
assert class_ids.tolist() == [0, 1, 0]
multi_label = torch.tensor([[1, 1]])
assert not bool((multi_label.sum(dim=1) == 1).all())
print("class IDs/loss:", class_ids, loss.item())
若真实标注是一张图片多个类别,保留 [N,C] 浮点目标,按多标签任务选择 BCEWithLogitsLoss,并使用逐类阈值预测。不能仅为让旧 NLL 接口接受而 argmax 成单类。
数据集直接返回类别编号通常更清楚,loader 会自然组为 [N]。原题占位标签全部相同,只能用于管线测试;训练准确率即使上升,也无法说明学会了真实类别。
历史接口与现代软目标支持需按版本区分。无论选哪条路线,都要确认输出原始 logits 或对数概率与损失匹配,并验证输入图片 HWC→CHW 用换轴完成,避免标签错误消失后还保留图像布局错误。
参考:原始求助帖;技术依据:CrossEntropyLoss(2.5)、NLLLoss(2.5)、BCEWithLogitsLoss(2.5)、PyTorch 数据加载(2.5)。