torch 交叉熵

1.softmax函数

对前层网络的输出si做如下变换,norms = (e^s1,e^s2,...,e^sk)/∑e^sj,

这样norms中的元素均为正值且和为1。

对应损失函数,L = -log(e^syi//∑e^sj),其中yi是样本i的标签(即样本真实类别)在类别集合中的序号。

2.onehot编码

适用于离散特征,比如color:[red,blue,green],如果给每个颜色一个对应值,便得到[0,1,2];

当然,也可以这样分配,我有red,blue,green三个类别,如果属性为red,就取[1,0,0];是blue,就取[0,1,0];依照这种思路得到的就是onehot编码。

torch中使用如下方式获得

#真实类别标签
target=torch.tensor([1,0,2])
# 对真实类别标签做 独热编码
one_hot = F.one_hot(target)

如果按照一开始的思路,得到[0,1,2],可以按照下面的方式转为对应的onehot编码。(eye(3)返回类似单位矩阵的张量)

one_hot2 = torch.eye(3)[target.long(),:]

3.多分类交叉熵

L=-1/N * ∑ ∑yic*log(pic)
第1个∑ ,1-N,N个样本;第2个∑ ,1-K,K个分类
pic是前层网络计算出来的在各个类别上的分值(经过softmax处理的);
yic是onehot编码,若第i个样本属于类别c,则对应位置的元素取1,否则取0

下面是几种计算方式:
1.分步计算交叉熵

#预测值,假设已做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)
log = torch.log(pred)#以自然对数e为底
res=-torch.sum(one_hot*log)/target.shape[0]#这里的*是张量对应元素相乘
print(res)

2.使用nll_loss计算交叉熵时,无需对标签进行onehot编码

#预测值,假设已做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])
log = torch.log(pred)
res2=F.nll_loss(log, target)
print(res2)

 3.使用log_softmax+nll_loss

#4个样本,3分类
pred=torch.rand(4,3)
#真实类别标签
target=torch.tensor([0,1,0,2])
logsoftmax = F.log_softmax(pred)
res2 = F.nll_loss(logsoftmax,target)
print(res2)

4.使用CrossEntropyLoss ,其等于softmax+log+nll_loss

#4个样本,3分类
pred=torch.rand(4,3)
#真实类别标签
target=torch.tensor([0,1,0,2])
res=F.cross_entropy(pred, target)
print(res)

 

posted @ 2022-07-02 19:31  许培风  阅读(693)  评论(0)    收藏  举报