当前位置:   article > 正文

pytorch学习笔记之分类问题中常用的损失函数_pytroch多分类网络常用损失函数

pytroch多分类网络常用损失函数

pytorch中多分类问题中最常用的损失函数应该就是CrossEntropyLoss了,传闻该函数结合了LogSoftmax和NLLLoss两个函数,那么这个函数到底是什么来头呢?本文来一探究竟。

交叉熵的定义

交叉熵刻画的是实际输出的分布与期望分布的距离:如果模型输出的结果的分布和期望的分布越相似,那么交叉熵就越小。交叉熵的定义公式为 C r o s s E n t r o p y ( f ( x ) , y ) = − ∑ i = 1 n y i l o g f ( x i ) CrossEntropy(f(\textbf{x}), \textbf{y})=-\sum_{i=1}^{n}{y_ilogf(x_i)} CrossEntropy(f(x),y)=i=1nyilogf(xi),其中 n n n表示 x \textbf{x} x的维度;更一般地,假设 p p p为期望分布, q q q为输出的分布,则 p p p q q q的交叉熵就是: C r o s s E n t r o p y ( p , q ) = − ∑ x p ( x ) l o g q ( x ) CrossEntropy(p,q)=-\sum_{x}{p(x)logq(x)} CrossEntropy(p,q)=xp(x)logq(x)

举个栗子,假设在一个三分类问题中,一条数据的真实标签为 [ 0 , 0 , 1 ] [0,0,1] [0,0,1],而模型A的预测概率为 [ 0.1 , 0.1 , 0.8 ] [0.1,0.1, 0.8] [0.1,0.1,0.8],模型B的预测概率为 [ 0.2 , 0.2 , 0.6 ] [0.2,0.2,0.6] [0.2,0.2,0.6]那么模型A的输出对应的交叉熵为 C 1 = − l o g ( 0.8 ) = 0.09 C_1=-log(0.8)=0.09 C1=log(0.8)=0.09,而模型B的输出的交叉熵为 C 2 = − l o g ( 0.6 ) = 0.22 C_2=-log(0.6)=0.22 C2=log(0.6)=0.22,可见即使两个模型都能够预测正确,但是模型A的交叉熵更小,而更小的交叉熵也意味着模型A的预测概率分布与真实的概率分布更相似。

Pytorch中的CrossEntropyLoss

根据定义,Pytorch中的CrossEntropyLoss是将Softmax-log-NLLoss合并到一块的结果,也就是说CrossEntropyLoss就是我们前面所讨论的交叉熵,为什么这么说呢?看下面的推导:
在这里插入图片描述

假设一个10分类的神经网络,那么在输出层就应该有10个节点。在Pytorch中如果使用CrossEntropyLoss,这10个节点的后面将不再需要softmax,因为CrossEntropyLoss已经包含了softmax这一部分。softmax的公式为 s o f t m a x ( z j ) = e z j ∑ e z i softmax(z_j)=\frac{e^{z_j}}{\sum{e^{z_i}}} softmax(zj)=eziezj,其能够将十个节点的输出进行处理使得 ∑ s o f t m a x ( z i ) = 1 \sum{softmax(z_i)}=1 softmax(zi)=1,也就是对10个节点的输出做了一个变换,且使得其大小关系不变。

在得到softmax的结果之后再将概率值取log,并且执行后面剩下的求和计算。也就是说NLLLOSS的结果就是把取log得到的结果和真实的标签相乘并求和,之后再求均值并取反(求当前mini-batch的均值)。

结合Pytorch文档测试

来看看Pytorch文档中对CrossEntropyLoss的定义
在这里插入图片描述
在这里插入图片描述
运行下面的代码:

import torch
import torch.nn as nn
import numpy as np

loss = nn.CrossEntropyLoss()

x_input = torch.randn(3, 3)
y = torch.tensor([1,2,0])
print('x_input = ', x_input)
print('y = ', y)

softmax_func = nn.Softmax(dim=1)
softmax_output = softmax_func(x_input)
print('softmax_output = ', softmax_output)

log_output = torch.log(softmax_output)
print('log_output = ', log_output)

nllloss = nn.NLLLoss()
nllloss_output = nllloss(log_output, y)
print('nlloss_output = ', nllloss_output)

print('crossentropyloss = ', loss(x_input, y))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

得到输出为:

x_input =  tensor([[ 0.1650,  1.7421,  0.1270],
        [-0.1254, -0.7676, -0.1373],
        [ 1.3294, -0.0838, -1.2392]])
y =  tensor([1, 2, 0])
softmax_output =  tensor([[0.1470, 0.7115, 0.1415],
        [0.3977, 0.2093, 0.3930],
        [0.7576, 0.1844, 0.0581]])
log_output =  tensor([[-1.9174, -0.3404, -1.9554],
        [-0.9220, -1.5642, -0.9339],
        [-0.2777, -1.6908, -2.8462]])
nlloss_output =  tensor(0.5173)
crossentropyloss =  tensor(0.5173)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

可以看到使用softmax-log-nllloss得到的结果和直接使用CrossEntropyLoss得到的结果是完全一样的。

再去看一下NLLLoss损失函数的官方定义:

在这里插入图片描述

参考资料:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/803317
推荐阅读
相关标签
  

闽ICP备14008679号