Crossentropyloss与 BCELoss差异
python报错:
1only batches of spatial targets supported (non-empty 3D tensors) but got targets of size
因为在使用Crossentropyloss作为损失函数时,output=net(input)的output应该是[batchsize, channel, height, weight],而label则是[batchsize, height, weight],label是单通道灰度图.
而在BCELoss中,两者都是[batchsize, channel, height, weight]。
报错是因为label本应该是一维的,我在保存的时候处理成了3维。
BCELoss
主要用于计算标签只有1或者0时的二分类损失,标签和预测值是一一对应的。需要注意的是,通过nn.BCEloss来计算损失前,需要对预测值进行一次sigmoid计算。sigmoid函数会将预测值映射到0-1之间。
如果觉得手动加sigmoid函数麻烦,可以直接调用nn.BCEwithlogitsloss。
使用nn.BCEloss计算损失
import torch
import torch.nn as nn
import torch.nn.functional as F
loss = nn.BCELoss(reduction="none")
target = torch.tensor([1,0,1], dtype=torch.float32)
predict = torch.tensor([0.8, 0.2, 0.3], dtype=torch.float32)
loss(F.sigmoid(predict), target)
#结果计算为:
tensor([0.3711, 0.7981, 0.5544])
手动实现nn.BCEloss
def myBceloss(predict, target, reduction="none"):
predict = F.sigmoid(predict)
if reduction == "none":
return -(target*torch.log(predict) + (1-target)*torch.log(1-predict))
myBceloss(predict, target)
#结果计算为:
tensor([0.3711, 0.7981, 0.5544])
Crossentropyloss
用于计算多分类任务,一个标签可能对应了预测的多个概率,例如一个任务包含了C个类别,那么预测值就有C 个。
使用nn.CrossEntropyLoss计算损失
(已经使用了softmax)
loss2 = nn.CrossEntropyLoss(reduction="none")
target2 = torch.tensor([0, 1, 2])
predict2 = torch.tensor([[0.9, 0.2, 0.8], [0.5, 0.2, 0.4], [0.4, 0.2, 0.9]])
loss2(predict2, target2)
#结果计算为:
tensor([0.8761, 1.2729, 0.7434])
手动实现nn.CrossEntropyLoss
def myCrossEntropyloss(target, predict, reduction="none"):
if reduction == "none":
predict = F.softmax(predict, dim=1)
n = torch.arange(predict.shape[0])
predict = predict[n, target]
return -torch.log(predict)
myCrossEntropyloss(target2, predict2)
#结果计算为:
tensor([0.8761, 1.2729, 0.7434])
注意
BCEWithLogitsLoss 要求它的目标是一个float 张量,而不是long。
Crossentropyloss 的标签要求是long类型
通过dtype=torch.float32指定t张量的类型
import torch
t = torch.tensor([[1, 0, 1, 1]], dtype=torch.float32).T
p = torch.rand(4,1)
loss_fn = torch.nn.BCEWithLogitsLoss()
print(loss_fn(p, t))
原文链接:https://blog.csdn.net/loki2018/article/details/127210390