本文包括:
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
结论:
单样本:
- tensor中每个元素取指数(exp);
- tensor中每个元素相加得到一个总数;
- 分别用tensor中每个元素除以这个总数,生成新的tensor(此时为softmax结果);
- 再取对数(此时为logsoftmax结果);
- 以target为索引,在张量中取值,加负号(此时为NLLLoss结果)
在单样本中,NLLLoss = cross__entropy,所以不用再往下计算
多样本:(接单样本的步骤)
- 如果是多样本,则每个样本有一个NLLLoss,所有的NLLLoss加起来除以样本数,也就是取均值
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)