第一次用的损失函数是均方误差MSELoss
程序正常运行没有遇到问题,但当换成CrossEntropyLoss
后会报如下错误:
RuntimeError: Expected object of scalar type Long but got scalar type Float for argument #2 'target' in call to _thnn_nll_loss_forward
搜了很多博客都没有找到答案,这篇博客中说到:
交叉熵需要传入一个output和一个target。nn.CrossEntropyLoss(output, target)
。
其中:
output.dtype : torch.FloatTorch
target.dtype : torch.LongTorch
我的预测数据output和标签数据target都是torch.float32数据类型,所以我在将array数据类型转换成tensor数据类型时做了如下操作:
x = torch.from_numpy(x).float()
target = torch.from_numpy(target).long()
其中float是float32类型,long是int64类型,但是问题依然存在。
在pytorch的官方论坛里有一个人也遇到了同样的问题,他把nn.CrossEntropyLoss()
换成了nn.MultiLabelSoftMarginLoss()
就不再报错了。但是经过实验发现,这个损失函数的效果非常差,远不如MSELoss
。
最终,我找到了一篇运用交叉熵损失函数的多分类代码一步步检查发现了报错的原因:
在多分类问题中,当损失函数为nn.CrossEntropyLoss()
时,它会自动把标签转换成onehot形式。例如,MNIST数据集的标签为0到9的数字,有100个标签,则标签的形状为[100],而我们的模型的输出则为onehot形式,其形状为[100, 10]。所以,我们在运用交叉熵损失函数时不必将标签也转换成onehot形式。问题成功解决。(target仍然需要为int64类型)