Pytorch 计算Logsoftmax + NLLLoss + CrossEntropy

Pytorch 计算Logsoftmax + NLLLoss + CrossEntropy,第1张

Pytorch 计算Logsoftmax + NLLLoss + CrossEntropy

本文包括:
1、单样本三分类为例,讲解 cross__entropy 的详细计算过程,包括手算,以及直接调用函数的计算结果对比;
2、十六样本(batch = 16)五分类为例,讲解 cross__entropy 的详细计算过程
3、给出结论(如果不想看代码,可以直接看结论)

#  单样本三分类
import torch

# 从softmax开始讲起,到最后的 cross_entropy ( softmax ——> log_softmax --> NLLLOSS--> cross_entropy)

# torch.softmax 原理: 1、所有值取指数  2、每个值分别除以总数(三个值相加),得到的三个值相加为一,构造类似概率
x = torch.tensor([-3,1.5,2.7])

so = torch.exp(x)

so_list = so.numpy().tolist()  # 将 tensor 转换为 list

j = 0
for i in so_list:
    j += i  # 得到三个值的和

p = []
for t in so_list:
    p.append(t / j)  # 得到三个值与总和的比值

b = torch.tensor(p)  # 手算得到的值

d = torch.softmax(x,dim=0)  # softmax 得到的值,0 - 1 之间



# torch.logsoftmax

c1 = torch.log(b)  # 给每个元素取对数
c2 = torch.log_softmax(x,dim=0)  # 一定为负值

# torch.NLLLoss

f = torch.tensor([1])  # 标签

jk = - c1[f.item()]
xe = torch.nn.NLLLoss()

gh = torch.unsqueeze(c2,dim = 0)
jhf = torch.unsqueeze(x,dim=0)  # NLLLoss 和 CROSS_entropy 都是以batch,也就是以四维输入的

afd = xe(gh,f)

jkx = torch.nn.CrossEntropyLoss()
ad = jkx(jhf,f)

print("手算结果:{}".format(b),"softmax结果{}".format(d))  # 验证 torch.softmax 计算过程
print("手算结果:{}".format(c1), "log_softmax结果{}".format(c2))  # 验证 torch.log_softmax 计算过程
print("手算结果:{}".format(jk), "NLLLoss结果{}".format(afd))  # 验证 torch.log_softmax 计算过程
print("CrossEntropyLoss:{}".format(ad), "NLLLoss结果{}".format(afd))  # 验证 torch.CrossEntropyLoss 计算过程




###  打印结果
手算结果:tensor([0.0026, 0.2309, 0.7666]) softmax结果tensor([0.0026, 0.2309, 0.7666])
手算结果:tensor([-5.9659, -1.4659, -0.2659]) log_softmax结果tensor([-5.9659, -1.4659, -0.2659])
手算结果:1.465850591659546 NLLLoss结果1.465850591659546
CrossEntropyLoss:1.465850591659546 NLLLoss结果1.465850591659546

# 这里以五分类,batch = 16 为例
import torch
import torch.nn as nn

x = torch.tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
y = torch.tensor([[-0.0299,  0.3996,  0.4132,  0.3828, -0.3578],
        [ 0.0384,  0.5070,  0.2784,  0.3086, -0.1736],
        [-0.1219,  0.5358,  0.6176,  0.2804, -0.0186],
        [ 0.1153,  0.5508,  0.2899,  0.3709, -0.1514],
        [-0.2253,  0.2107,  0.4944,  0.1685, -0.2234],
        [ 0.0670,  0.3559,  0.2721,  0.4018, -0.2393],
        [-0.0943,  0.4430,  0.6774,  0.3513,  0.0197],
        [-0.1786,  0.4166,  0.4601,  0.5448, -0.1473],
        [-0.0938,  0.5514,  0.2839,  0.2177, -0.1892],
        [-0.2615,  0.5100,  0.5620,  0.6361, -0.0498],
        [-0.0679,  0.4000,  0.2917,  0.4411, -0.3760],
        [-0.1139,  0.3442,  0.4538,  0.4446, -0.2071],
        [-0.4183,  0.4170,  0.7693,  0.6503, -0.1554],
        [ 0.0608,  0.4094,  0.3131,  0.2778, -0.1750],
        [-0.0332,  0.4247,  0.4322,  0.4355, -0.2383],
        [-0.0277,  0.1793,  0.4213,  0.3589, -0.2416]]
       )

d = torch.exp(y)

d1 = torch.softmax(y,dim=1)

log_d1 = torch.log(d1)

nl = torch.nn.NLLLoss(reduction="mean")

NLLL_log_d1 = nl(log_d1,x)
cross = torch.nn.CrossEntropyLoss()
ad = cross(y,x)

nll_i = []
for i in range(y.shape[0]):
    y_i = log_d1[i, :]
    x_i = torch.unsqueeze(x[i],dim=0)
    y_ii = torch.unsqueeze(y_i,dim=0)
    nl_i = nl(y_ii,x_i)
    nll_i.append(nl_i)

j = 0
for i in nll_i:
    j += i
js = j / 16


print("CrossEntropyLoss:{}".format(ad), "softmax + log + 平均{}".format(js), "softmax + log + NLLLoss{}".format(NLLL_log_d1))  # 验证 torch.CrossEntropyLoss 计算过程


###  打印结果
CrossEntropyLoss:1.9328043460845947
softmax + log + 平均1.9328042268753052
softmax + log + NLLLoss1.9328041076660156

结论:

单样本:

  1. tensor中每个元素取指数(exp);
  2. tensor中每个元素相加得到一个总数;
  3. 分别用tensor中每个元素除以这个总数,生成新的tensor(此时为softmax结果);
  4. 再取对数(此时为logsoftmax结果);
  5. 以target为索引,在张量中取值,加负号(此时为NLLLoss结果)

在单样本中,NLLLoss = cross__entropy,所以不用再往下计算

多样本:(接单样本的步骤)

  1. 如果是多样本,则每个样本有一个NLLLoss,所有的NLLLoss加起来除以样本数,也就是取均值

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5651672.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存