import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
torch.manual_seed(7)
要求预测的输出是概率
样本 | $y_i$ | $p_i$ |
---|---|---|
样本1 | 1 | 0.8 |
样本2 | 0 | 0.2 |
样本3 | 0 | 0.4 |
# 按公式计算
Loss = -((1*np.log(0.8)+(1-1)*np.log(1-0.8)) + (0*np.log(0.2)+(1-0)*np.log(1-0.2)) + (0*np.log(0.4)+(1-0)*np.log(1-0.4))) / 3
Loss
# BCELoss
bce_loss = nn.BCELoss()
pred = torch.tensor([0.8, 0.2, 0.4], dtype=torch.float)
label = torch.tensor([1, 0, 0], dtype=torch.float)
print(bce_loss(pred, label))
相比于BCELoss,预测输出不要求预测值是概率,可以是实数域内任意值。
BCELossWithLogits = BCELoss + Sigmoid
pred = torch.randn(4,2) # 预测值
target = torch.rand(4).random_(0,2) # 真实类别标签
print(pred)
print(target)
# 将target进行独热编码
onehot_target = torch.eye(2)[target.long(), :]
print(onehot_target)
bce_logits = nn.BCEWithLogitsLoss()
loss = bce_logits(pred, onehot_target)
loss
sigmoid = nn.Sigmoid()
sigmoid_pred = sigmoid(pred)
sigmoid_pred
[target.long()]
bce_loss = nn.BCELoss()
bce_loss(sigmoid_pred, onehot_target)
假设N=2, K=3,即总共3个样本,3个类别,样本的数据如下:
. | $y_{i1}$ | $y_{i2}$ | $y_{i3}$ | $p_{i1}$ | $p_{i2}$ | $p_{i3}$ |
---|---|---|---|---|---|---|
第1个样本 | 0 | 1 | 0 | 0.2 | 0.3 | 0.5 |
第2个样本 | 1 | 0 | 0 | 0.3 | 0.2 | 0.5 |
第3个样本 | 0 | 0 | 1 | 0.4 | 0.4 | 0.2 |
需要注意,$p_{i c}$之和应为1,即预测结果要经过softmax处理!
#预测值,假设已做softmax
pred=torch.tensor([[0.2,0.3,0.5],[0.3,0.2,0.5],[0.4,0.4,0.2]])
#真实类别标签
target=torch.tensor([1,0,2])
# 对真实类别标签做 独热编码
one_hot = F.one_hot(target).float()
"""
one_hot:
tensor([[0., 1., 0.],
[1., 0., 0.],
[0., 0., 1.]])
"""
#对预测值取log
log = torch.log(pred)
#计算最终的结果
res = -torch.sum(one_hot*log)/target.shape[0]
print(res)# tensor(1.3391)
不需要对真实标签做one-hot处理,但是预测值要进行log_softmax操作
#预测值,已做softmax
pred=torch.tensor([[0.2,0.3,0.5],[0.3,0.2,0.5],[0.4,0.4,0.2]])
#真实类别标签,此时无需再做one_hot,因为nll_loss会自动做
target=torch.tensor([1,0,2])
#对预测值取log
log=torch.log(pred)
#计算最终的结果
res=F.nll_loss(log, target)
print(res)# tensor(1.3391)
log_softmax + nll_loss
torch.manual_seed(7) #cpu
# 4个样本,3分类
pred=torch.rand(4,3)
# 真实类别标签
target=torch.tensor([0,1,0,2])
# 需要对预测值进行 log_softmax操作
logsoftmax = F.log_softmax(pred, dim=1)
print(logsoftmax)
res = F.nll_loss(logsoftmax,target)
print()
print('log_softmax + nll_loss:')
print(res)
print('直接使用CrossEntropyLoss:')
res=F.cross_entropy(pred, target)
print(res)