在pytorch中和keras不同的是如果使用torch.nn.CrossEntropyLoss()交叉熵作为损失函数,并不需要我们进行one-hot编码,因为已经替我们执行了这一操作,只需要我们传入的label是longtensor即可。
- input : 模型输出,包含每个类的得分,2-D tensor,shape为 batch * n类
- target: 大小为 n 的 1—D tensor,包含类别的索引(0到 n-1)。
注意CrossEntropyLoss()的target输入也是类别值,不是one-hot编码格式
import numpy as np
import torch
import torch.nn.functional as F
# 比如这是一个模型的输出,本案例为一个三类别的分类,共有四组样本,如下:
pred_y = np.array([[ 0.30722019 ,-0.8358033 ,-1.24752918],
[ 0.72186664 , 0.58657704 ,-0.25026393],
[ 0.16449865 ,-0.44255082 , 0.68046693],
[-0.52082402 , 1.71407838 ,-1.36618063]])
pred_y=torch.from_numpy(pred_y)
# 真实的标签如下所示
true_y = np.array([[ 1 , 0 , 0],
[ 0 , 1 , 0],
[ 0 , 1 , 0],
[ 0 , 0 , 1]])
true_y=torch.from_numpy(true_y)
target = np.argmax(true_y, axis=1) #(4,) #其实就是获得每一给类别的整数值,这个和tensorflow里面不一样哦 内部会自动转换为one-hot形式
target = torch.LongTensor(target) #(4,)
print(target) # tensor([0,1,1,2])
print("-----------------------------------------------------------")
# 第一步:使用激活函数softmax进行缩放
print("第一步:使用激活函数softmax进行缩放")
pred_y = F.softmax(pred_y,dim=1)
print(pred_y)
print('-----------------------------------------------------------')
# 第二步:对每一个缩放之后的值求对数log
print("第二步:对每一个缩放之后的值求对数log")
pred_y=torch.log(pred_y)
print(pred_y)
print('-----------------------------------------------------------')
# 第三步:求交叉熵损失
loss=F.nll_loss(pred_y,target)
print(loss) # 最终的损失为:tensor(1.5929, dtype=torch.float64)
print('-----------------------------------------------------------')
print("两部实现交叉熵")
# 第一步:直接使用log_softmax,相当于softmax+log
pred_y=F.log_softmax(pred_y,dim=1)
print(pred_y)
print('-----------------------------------------------------------')
# 第二步:求交叉熵损失
loss=F.nll_loss(pred_y,target)
print(loss) # tensor(1.5929, dtype=torch.float64)
print('-----------------------------------------------------------')
print("一步实现")
# 第一步:求交叉熵损失一步到位
loss=F.cross_entropy(pred_y,target)
print(loss)
print('-----------------------------------------------------------')
# https://blog.csdn.net/qq_29631521/article/details/104907401
# https://www.cnblogs.com/cxq1126/p/13794877.html
import torch
import torch.nn as nn
import torch.nn.functional as F
m = nn.Sigmoid()
loss_f1 = nn.BCELoss()
loss_f2 = nn.BCEWithLogitsLoss()
loss_f3 = nn.CrossEntropyLoss()
logits = torch.randn(3, 2)
labels = torch.FloatTensor([[0, 1], [1, 0], [1, 0]])
print(loss_f1(m(logits), labels)) #tensor(0.9314),注意logits先被激活函数作用
print(loss_f2(logits, labels)) #tensor(0.9314)
label2 = torch.LongTensor([1, 0, 0])
print(loss_f3(logits, label2)) #tensor(1.2842)
# 如果label2也想变成labels,然后通过BCELoss进行计算的话,可以先转变成独热编码的形式:
encode = F.one_hot(label2, num_classes = 2)
print("encode: ",encode) #encode的值和labels一样,但是类型是LongTensor
print(loss_f1(m(logits), encode.type(torch.float32))) #tensor(0.9314)
参考:https://www.cnblogs.com/marsggbo/p/10401215.html
https://segmentfault.com/a/1190000023336609?utm_source=tag-newest