import torch.nn.functional as F
常用的函数有: log_softmax,nll_loss, cross_entropy
1.
log_softmax
, 就是log和softmax合并在一起执行
2.
nll_loss
,函数全称是negative log likelihood loss, 函数表达式为
例如:假设x=[1,2,3], class=2, 则
3.
cross_entropy
交叉熵的计算公式为
其中p表示真实值,在这个公式中是one-hot形式,q是预测值,在这里假设是经过softmax后的结果了。
仔细观察可知,因为p的元素不是0就是1,而且又是乘法,所以很自然地,如果我们知道1所对应的index,那么就不用做其他无意义的运算了。所以在pytorch代码中
target不是以one-hot形式表示的,而是直接用scalar表示
,所以交叉熵的公式(m表示真实类别)可变形为
仔细看看,就是等同于log_softmax和nll_loss两个步骤
所以pytorch中的F.cross_entropy会自动调用上面介绍的log_softmax和nll_loss来计算交叉熵,其计算方式如下:
import torch
import torch.nn.functional as F
import torchsnooper
@torchsnooper.snoop() #用于调试,观察哪里会出错误
def main():
input=torch.from_numpy(np.array([[-0.0979, -0.3264, -0.1561, 0.2403, -0.4000],
[-1.6561, 0.9922, -0.2922, 0.4640, -0.6327],
[-0.3424, 1.3673, 0.8343, -0.1376, 1.7234]]))
target=torch.from_numpy(np.array([2, 2, 4]))
#方法一, 直接调用cross_entropy 计算损失函数
loss = F.cross_entropy(input, target)#直接调用函数进行计算tensor(1.5196, dtype=torch.float64)
print(loss)
#方法二, 分步骤计算损失函数
#step1: 先计算softmax()
probability=F.softmax(input,dim=1)#shape [num_samples,num_classes]
#step2 计算预测值的对数
log_P=torch.log(probability)
'''对输入的target标签进行 one-hot编码,使用_scatter方法'''
one_hot=torch.zeros(probability.shape,dtype=float).scatter_(1,torch.unsqueeze(target,dim=1),1)
#根据交叉熵公式loss=-target*log(predict)
loss3=-one_hot*log_P
loss3=loss3.sum()
loss3/=probability.shape[0]
print('loss3',loss3) # 1.5196与第一种方法结果是一样的
#方法三, 借助于log_softmax
logsoftmax=F.log_softmax(input)
loss4=-one_hot*logsoftmax
loss4=loss4.sum()
loss4/=probability.shape[0]
print('loss4',loss4) #1.5196
#方法四, 借助于nllloss
nllloss=F.nll_loss(logsoftmax,target)
print('nllloss',nllloss)
if __name__ == '__main__':
main()
import torch.nn.functional as F常用的函数有: log_softmax,nll_loss, cross_entropy1.log_softmax, 就是log和softmax合并在一起执行2. nll_loss ,函数全称是negative log likelihood loss, 函数表达式为 例如:假设x=[1,2,3], class=2...
F.nll_loss计算方式是下式,在函数内部不含有提前使用softmax转化的部分;
nn.CrossEntropyLoss内部先将输出使用softmax方式转化为概率的形式,后使用F.nll_loss函数计算交叉熵。
CrossEntropyLoss()=log_softmax() + NLLLoss()
两个函数的输入分别是input和target,
input是网络预测的输出,形状为(batch_size, pro),其中pro为class的个数;
target是标签,不
常用于多分类任务,NLLLoss 函数输入 input 之前,需要对 input 进行 log_softmax 处理,即将 input 转换成概率分布的形式,并且取对数,底数为 e
class torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100,
reduce=None, reduction='...
# 随机新建3个样例数据,每个样例数据包含4个属性特征
input = torch.randn(3,4)
tensor([[ 0.0054, -0.8030, -0.5758, -0.6518],
[-0.5518, 0.3904, 0.5296, 0.4973],
[ 0.1608, 0.5822, 0.9536, -0.3173