当我使用 BCELoss
作为神经网络的损失函数时,遇到了 ValueError: Target and input must have the same number of elements
错误。
这是我测试阶段的代码(这是一个相当典型的测试阶段代码):
network.eval()test_loss = 0correct = 0with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = network(data) output = output.to(device) test_loss += loss_function(output, target).item() # 错误发生在这里 _, predicted = torch.max(output.data, 1) correct += (predicted == target).sum().item()
变量 output
的形状是 [1000, 10]
,因为有 10
个目标类别(在 MNIST 数据集中),变量 target
的形状是 [1000]
,因为它包含了测试批次的目标类别(测试的批次大小设置为 10
)。那么,问题是如何将 BCELoss
应用于 CNN
网络的损失函数?
p.s. 我使用的数据集是 torchvision
库提供的 MNIST 数据集。
p.s. 这里提供的类似问题的答案 并没有为我的情况提出解决方案。
回答:
你声称的 答案 实际上确实解决了你的问题:
你的目标不完整!如果有多个类别,你应该使用
torch.nn.CrossEntropyLoss
而不是torch.nn.BCELoss()
总结一下,torch.nn.BCELoss()
旨在用于对每个输入示例分类 c
个 独立 的二进制属性。你所面临的任务是将每个输出分类为 互斥的 c
个类别之一。对于这个任务,你需要一个不同的损失函数,torch.nn.CrossEntropyLoss()
。
不同的任务,由不同的损失函数代表,需要不同的监督(标签)。如果你想将每个示例分类为 c
个互斥类别之一,你只需要为每个示例提供一个整数标签(就像你在 mnist 示例中所做的那样)。然而,如果你想将每个示例分类为 c
个独立的二进制属性,你需要为每个示例提供 c
个二进制标签——这就是为什么 pytorch 会给你一个错误的原因。