首页 > 其他分享 >深入理解交叉熵损失 CrossEntropyLoss - CrossEntropyLoss

深入理解交叉熵损失 CrossEntropyLoss - CrossEntropyLoss

时间:2024-06-09 10:32:11浏览次数:11  
标签:log nn 交叉 0.1 0.2 CrossEntropyLoss 深入 exp

深入理解交叉熵损失 CrossEntropyLoss - CrossEntropyLoss

flyfish

本系列的主要内容是在2017年所写,GPT使用了交叉熵损失函数,所以就温故而知新,文中代码又用新版的PyTorch写了一遍,在看交叉熵损失函数遇到问题时,可先看链接提供的基础知识,可以有更深的理解。

深入理解交叉熵损失 CrossEntropyLoss - one-hot 编码
深入理解交叉熵损失 CrossEntropyLoss - 对数
深入理解交叉熵损失 CrossEntropyLoss - 概率基础
深入理解交叉熵损失 CrossEntropyLoss - 概率分布
深入理解交叉熵损失 CrossEntropyLoss - 损失函数
深入理解交叉熵损失 CrossEntropyLoss - 归一化
深入理解交叉熵损失 CrossEntropyLoss - 信息论(交叉熵)
深入理解交叉熵损失 CrossEntropyLoss - Softmax
深入理解交叉熵损失 CrossEntropyLoss - nn.LogSoftmax

深入理解交叉熵损失 CrossEntropyLoss - 似然
深入理解交叉熵损失CrossEntropyLoss - 乘积符号在似然函数中的应用

深入理解交叉熵损失 CrossEntropyLoss - nn.NLLLoss
深入理解交叉熵损失 CrossEntropyLoss - nn.CrossEntropyLoss

深入理解交叉熵损失CrossEntropyLoss


在 PyTorch 中, torch.nn.CrossEntropyLoss 是一个常用的 损失函数,主要用于多分类任务。它结合了 nn.LogSoftmaxnn.NLLLoss,并且内部进行了优化以避免 数值稳定性问题。

具体来说,torch.nn.CrossEntropyLoss 计算的是预测值与目标值之间的交叉熵损失。对于多分类问题,交叉熵损失是最常用的损失函数,因为它直接衡量了两个概率分布(预测概率分布和实际分布)之间的差异。

LogSoftmax和 NLLLoss两者的结合,对比立使用CrossEntropyLoss

nn.CrossEntropyLoss 在内部已经包含了 LogSoftmax 和 NLLLoss 的操作。
编写代码验证,分别是 LogSoftmax和 NLLLoss两者的结合,对比立使用CrossEntropyLoss。

import torch
import torch.nn as nn

# 输入张量 (batch_size=2, num_classes=3)
input_tensor = torch.tensor([[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]])
# 目标张量 (batch_size=2)
target_tensor = torch.tensor([2, 0])

# 使用 nn.LogSoftmax 和 nn.NLLLoss
log_softmax = nn.LogSoftmax(dim=1)
log_probs = log_softmax(input_tensor)
nll_loss = nn.NLLLoss()
loss = nll_loss(log_probs, target_tensor)
print(f'Loss using LogSoftmax and NLLLoss: {loss.item()}')

# 使用 nn.CrossEntropyLoss
cross_entropy_loss = nn.CrossEntropyLoss()
loss_ce = cross_entropy_loss(input_tensor, target_tensor)
print(f'Loss using CrossEntropyLoss: {loss_ce.item()}')

输出结果
Loss using LogSoftmax and NLLLoss: 1.4076058864593506
Loss using CrossEntropyLoss: 1.4076058864593506

解释

对于单个样本,交叉熵损失的定义如下:

CrossEntropyLoss = − ∑ i = 1 C y i log ⁡ ( y ^ i ) \text{CrossEntropyLoss} = -\sum_{i=1}^{C} y_i \log(\hat{y}_i) CrossEntropyLoss=−i=1∑C​yi​log(y^​i​)

其中:

  • C C C 是类别的数量。
  • y i y_i yi​ 是真实标签的一个one-hot编码(若样本属于类别 i i i,则 y i = 1 y_i = 1 yi​=1,否则 y i = 0 y_i = 0 yi​=0)。
  • y ^ i \hat{y}_i y^​i​ 是模型预测的第 i i i 类的概率。

直观解释 Softmax和负对数似然

交叉熵损失结合了两个概念:

  1. Softmax
    首先将模型输出的原始分数(logits)通过 softmax 函数转换成概率分布,Softmax 函数将 logits 转换为概率分布。对于一个有 C C C 个类别的分类问题,Softmax 公式如下:

y ^ i = exp ⁡ ( z i ) ∑ j = 1 C exp ⁡ ( z j ) \hat{y}_i = \frac{\exp(z_i)}{\sum_{j=1}^{C} \exp(z_j)} y^​i​=∑j=1C​exp(zj​)exp(zi​)​

其中 z i z_i zi​ 是第 i i i 类的 logit。

  1. 负对数似然
    计算这些概率分布与真实标签之间的负对数似然。在获得概率分布后,交叉熵损失计算真实标签的负对数概率。如果真实标签对应的类别概率很高,损失就小;如果概率很低,损失就大。这驱动模型在训练过程中提高真实标签类别的预测概率。

以下是一个简单的示例,展示如何计算交叉熵损失:

import torch
import torch.nn as nn

# 假设我们有两个样本,每个样本属于3个类别中的一个
logits = torch.tensor([[2.0, 1.0, 0.1], [0.5, 2.0, 0.3]])
# 真实标签
labels = torch.tensor([0, 1])

# 使用 nn.CrossEntropyLoss 计算损失
criterion = nn.CrossEntropyLoss()
loss = criterion(logits, labels)
print(f'Cross Entropy Loss: {loss.item()}')

Cross Entropy Loss: 0.37882310152053833
在这个示例中:

  • logits 是模型输出的原始分数。
  • labels 是真实的类别标签。
  • nn.CrossEntropyLoss 会先将 logits 转换为概率分布,然后计算真实标签的负对数似然损失。

二分类问题

二分类交叉熵损失的公式为:

CrossEntropyLoss = − ( y log ⁡ ( y ^ ) + ( 1 − y ) log ⁡ ( 1 − y ^ ) ) \text{CrossEntropyLoss} = - (y \log(\hat{y}) + (1 - y) \log(1 - \hat{y})) CrossEntropyLoss=−(ylog(y^​)+(1−y)log(1−y^​))

手动计算步骤

  1. 计算 Sigmoid 激活值

假设:

  • 真实标签 y = 1 y = 1 y=1
  • 模型输出的logits为 z = 1.5 z = 1.5 z=1.5
    计算过程:
    σ ( z ) = 1 1 + exp ⁡ ( − 1.5 ) \sigma(z) = \frac{1}{1 + \exp(-1.5)} σ(z)=1+exp(−1.5)1​

我们使用更高精度来计算:
exp ⁡ ( − 1.5 ) ≈ 0.22313016014842982 \exp(-1.5) \approx 0.22313016014842982 exp(−1.5)≈0.22313016014842982
σ ( z ) = 1 1 + 0.22313016014842982 ≈ 1 1.22313016014842982 ≈ 0.8175744761936437 \sigma(z) = \frac{1}{1 + 0.22313016014842982} \approx \frac{1}{1.22313016014842982} \approx 0.8175744761936437 σ(z)=1+0.223130160148429821​≈1.223130160148429821​≈0.8175744761936437

  1. 计算交叉熵损失

CrossEntropyLoss = − ( y log ⁡ ( σ ( z ) ) + ( 1 − y ) log ⁡ ( 1 − σ ( z ) ) ) \text{CrossEntropyLoss} = - (y \log(\sigma(z)) + (1 - y) \log(1 - \sigma(z))) CrossEntropyLoss=−(ylog(σ(z))+(1−y)log(1−σ(z)))
CrossEntropyLoss = − log ⁡ ( 0.8175744761936437 ) \text{CrossEntropyLoss} = - \log(0.8175744761936437) CrossEntropyLoss=−log(0.8175744761936437)
log ⁡ ( 0.8175744761936437 ) ≈ − 0.2014132779827524 \log(0.8175744761936437) \approx -0.2014132779827524 log(0.8175744761936437)≈−0.2014132779827524
CrossEntropyLoss ≈ 0.2014132779827524 \text{CrossEntropyLoss} \approx 0.2014132779827524 CrossEntropyLoss≈0.2014132779827524

代码实现

import torch
import torch.nn as nn
import math

# 真实标签和 logits
labels = torch.tensor([1.0])
logits = torch.tensor([1.5])

# 使用 BCEWithLogitsLoss
criterion = nn.BCEWithLogitsLoss()
loss = criterion(logits, labels)
print(f'Binary Classification Cross Entropy Loss: {loss.item()}')

# 手动计算 sigmoid 和交叉熵损失
sigmoid = 1 / (1 + math.exp(-1.5))
manual_loss = - (1 * math.log(sigmoid) + (1 - 1) * math.log(1 - sigmoid))
print(f'Manually Computed Cross Entropy Loss: {manual_loss}')

输出结果

Binary Classification Cross Entropy Loss: 0.20141397416591644
Manually Computed Cross Entropy Loss: 0.2014132779827524

多分类问题

假设有3个类别:

  • 真实标签为第3类,所以one-hot编码 y = [ 0 , 0 , 1 ] y = [0, 0, 1] y=[0,0,1]。
  • 模型预测的logits为 logits = [ 0.1 , 0.2 , 0.7 ] \text{logits} = [0.1, 0.2, 0.7] logits=[0.1,0.2,0.7]。

手动计算步骤

  1. 计算Softmax
    y ^ i = exp ⁡ ( z i ) ∑ k = 1 C exp ⁡ ( z k ) \hat{y}_i = \frac{\exp(z_i)}{\sum_{k=1}^{C} \exp(z_k)} y^​i​=∑k=1C​exp(zk​)exp(zi​)​

具体计算:

y ^ 1 = exp ⁡ ( 0.1 ) exp ⁡ ( 0.1 ) + exp ⁡ ( 0.2 ) + exp ⁡ ( 0.7 ) \hat{y}_1 = \frac{\exp(0.1)}{\exp(0.1) + \exp(0.2) + \exp(0.7)} y^​1​=exp(0.1)+exp(0.2)+exp(0.7)exp(0.1)​
y ^ 2 = exp ⁡ ( 0.2 ) exp ⁡ ( 0.1 ) + exp ⁡ ( 0.2 ) + exp ⁡ ( 0.7 ) \hat{y}_2 = \frac{\exp(0.2)}{\exp(0.1) + \exp(0.2) + \exp(0.7)} y^​2​=exp(0.1)+exp(0.2)+exp(0.7)exp(0.2)​
y ^ 3 = exp ⁡ ( 0.7 ) exp ⁡ ( 0.1 ) + exp ⁡ ( 0.2 ) + exp ⁡ ( 0.7 ) \hat{y}_3 = \frac{\exp(0.7)}{\exp(0.1) + \exp(0.2) + \exp(0.7)} y^​3​=exp(0.1)+exp(0.2)+exp(0.7)exp(0.7)​

计算得到:

exp ⁡ ( 0.1 ) ≈ 1.1052 \exp(0.1) \approx 1.1052 exp(0.1)≈1.1052
exp ⁡ ( 0.2 ) ≈ 1.2214 \exp(0.2) \approx 1.2214 exp(0.2)≈1.2214
exp ⁡ ( 0.7 ) ≈ 2.0138 \exp(0.7) \approx 2.0138 exp(0.7)≈2.0138

总和:

exp ⁡ ( 0.1 ) + exp ⁡ ( 0.2 ) + exp ⁡ ( 0.7 ) ≈ 1.1052 + 1.2214 + 2.0138 = 4.3404 \exp(0.1) + \exp(0.2) + \exp(0.7) \approx 1.1052 + 1.2214 + 2.0138 = 4.3404 exp(0.1)+exp(0.2)+exp(0.7)≈1.1052+1.2214+2.0138=4.3404

各个概率:

y ^ 1 = 1.1052 4.3404 ≈ 0.2546 \hat{y}_1 = \frac{1.1052}{4.3404} \approx 0.2546 y^​1​=4.34041.1052​≈0.2546
y ^ 2 = 1.2214 4.3404 ≈ 0.2814 \hat{y}_2 = \frac{1.2214}{4.3404} \approx 0.2814 y^​2​=4.34041.2214​≈0.2814
y ^ 3 = 2.0138 4.3404 ≈ 0.4639 \hat{y}_3 = \frac{2.0138}{4.3404} \approx 0.4639 y^​3​=4.34042.0138​≈0.4639

  1. 计算交叉熵损失
    CrossEntropyLoss = − ( 0 ⋅ log ⁡ ( 0.2546 ) + 0 ⋅ log ⁡ ( 0.2814 ) + 1 ⋅ log ⁡ ( 0.4639 ) ) \text{CrossEntropyLoss} = - (0 \cdot \log(0.2546) + 0 \cdot \log(0.2814) + 1 \cdot \log(0.4639)) CrossEntropyLoss=−(0⋅log(0.2546)+0⋅log(0.2814)+1⋅log(0.4639))
    CrossEntropyLoss = − log ⁡ ( 0.4639 ) ≈ 0.769 \text{CrossEntropyLoss} = - \log(0.4639) \approx 0.769 CrossEntropyLoss=−log(0.4639)≈0.769

代码验证

import torch
import torch.nn as nn
import torch.nn.functional as F

# 模拟输入的 logits 和真实标签
logits = torch.tensor([[0.1, 0.2, 0.7]], requires_grad=True)
labels = torch.tensor([2])

# 使用 CrossEntropyLoss
criterion = nn.CrossEntropyLoss()
loss = criterion(logits, labels)
print(f'Computed Cross Entropy Loss (using nn.CrossEntropyLoss): {loss.item()}')

# 手动计算 softmax 和交叉熵损失
softmax_probs = F.softmax(logits, dim=1)
manual_loss = -torch.log(softmax_probs[0, labels])
print(f'Manually Computed Cross Entropy Loss: {manual_loss.item()}')

输出结果

Computed Cross Entropy Loss (using nn.CrossEntropyLoss): 0.7679495811462402
Manually Computed Cross Entropy Loss: 0.7679495811462402

注意在多分类问题的代码中,我们提供了logits而不是softmax后的概率,因为nn.CrossEntropyLoss会在内部应用softmax。

在二分类问题中,我们可以使用 nn.BCEWithLogitsLoss,它会在内部应用 Sigmoid 激活函数,并计算二分类的交叉熵损失。
在多分类问题中,我们可以使用 nn.CrossEntropyLoss,它会在内部应用 Softmax 激活函数,并计算多分类的交叉熵损失

标签:log,nn,交叉,0.1,0.2,CrossEntropyLoss,深入,exp
From: https://blog.csdn.net/flyfish1986/article/details/139558520

相关文章

  • 深入浅出,解析ChatGPT背后的工作原理
    自ChatGPT发布以来,已经吸引了无数人一探究竟。但ChatGPT实际上是如何工作的?尽管它内部实现的细节尚未公布,我们却可以从最近的研究中一窥它的基本原理。ChatGPT是OpenAI发布的最新语言模型,比其前身GPT-3有显著提升。与许多大型语言模型类似,ChatGPT能以不同样式、不......
  • 深入解析:MySQL连接超时问题排查与优化策略
    引言​在现代企业应用中,数据库的稳定性和响应速度是保证业务连续性的关键。MySQL作为广泛使用的数据库系统,其连接超时问题可能成为性能瓶颈,影响用户体验和业务效率。本文将深入探讨MySQL连接超时的原因、影响以及优化策略。超时配置详解​查看当前设置​要了解MySQL......
  • 深入解析Kafka消息丢失的原因与解决方案
    深入解析Kafka消息丢失的原因与解决方案ApacheKafka是一种高吞吐量、分布式的消息系统,广泛应用于实时数据流处理。然而,在某些情况下,Kafka可能会出现消息丢失的情况,这对于数据敏感的应用来说是不可接受的。本文将深入解析Kafka消息丢失的各种原因,包括生产者、broker和消费......
  • 深入解析Kafka消息传递的可靠性保证机制
    深入解析Kafka消息传递的可靠性保证机制Kafka在设计上提供了不同层次的消息传递保证,包括atmostonce(至多一次)、atleastonce(至少一次)和exactlyonce(精确一次)。每种保证通过不同的机制实现,下面详细介绍Kafka如何实现这些消息传递保证。1.AtMostOnce(至多一次)在这种模......
  • 深度学习 - softmax交叉熵损失
    示例代码importtorchfromtorchimportnn#多分类交叉熵损失,使用nn.CrossEntropyLoss()实现。nn.CrossEntropyLoss()=softmax+损失计算deftest1():#设置真实值:可以是热编码后的结果也可以不进行热编码#y_true=torch.tensor([[0,1,0],[0,0,1]......
  • 【算法】深入浅出爬山算法:原理、实现与应用
     人不走空                                           ......
  • 深入理解序列化:概念、应用与技术
    在计算机科学中,序列化(Serialization)是指将数据结构或对象状态转换为可存储或传输的格式的过程。这个过程允许将数据保存到文件、内存缓冲区,或通过网络传输至其他计算机环境,不受原始程序语言的限制。相对地,反序列化(Deserialization)则是将这种格式变回原来的数据结构或对象的......
  • 深入了解 C# Span:高性能内存操作的利器
    深入了解C#Span:高性能内存操作的利器在C#7.2中引入的Span<T>类型为我们提供了一种高效且安全地对内存进行操作的方式。Span<T>是一个轻量级的结构体,用于表示一段连续的内存区域,可以避免不必要的内存分配和拷贝,提高代码的性能和效率。什么是Span?Span<T>是一个用于表......
  • Java学习【深入探索包装类和泛型】
    Java学习【深入探索包装类和泛型】......
  • 深入探索Spark MLlib:大数据时代的机器学习利器
    随着大数据技术的迅猛发展,机器学习在各行各业的应用日益广泛。ApacheSpark作为大数据处理的利器,其内置的机器学习库MLlib(MachineLearningLibrary)提供了一套高效、易用的工具,用于处理和分析海量数据。本文将深入探讨SparkMLlib,介绍其核心功能和应用场景,并通过实例展示如何......