分类损失函数:直觉与应用

部署运行你感兴趣的模型镜像

原文:towardsdatascience.com/classification-loss-functions-intuition-and-applications-cb75a3b03237?source=collection_archive---------3-----------------------#2024-06-27

一种更简洁的方式来理解分类损失函数的推导以及在 PyTorch 中何时/如何应用它们

https://medium.com/@rtdcunha?source=post_page---byline--cb75a3b03237--------------------------------https://towardsdatascience.com/?source=post_page---byline--cb75a3b03237-------------------------------- Ryan D’Cunha

·发布于 Towards Data Science ·阅读时间:9 分钟·2024 年 6 月 27 日

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8799dde9d8c2ba105f0d95e98464eb61.png

来源:GPT4o 生成

无论你是刚开始探索神经网络的新手,还是经验丰富的专家,这篇文章都将是一次有益的阅读,可以帮助你更好地理解损失函数。作为一个在模型训练过程中测试多种不同损失函数的人,我常常因为函数之间的小细节而卡住。我花了很多时间查阅教科书、研究论文和视频,以寻找一种直观的损失函数描述。我想与大家分享不仅是帮助我理解这些概念的推导过程,还有在 PyTorch 中使用分类损失函数时常见的陷阱和应用场景。

术语

在我们开始之前,我需要定义一些我将要使用的基本术语。

  • 训练数据集: {xᵢ, yᵢ}

  • 损失函数: L[φ]

  • 模型预测输出 f[xᵢ, φ],其中 φ 为参数

  • 条件概率: Pr(y|x)

  • 参数化分布: Pr(y|ω),其中 ω 表示网络参数,用于描述 y 上的分布

介绍

让我们首先回归基础。一个常见的想法是神经网络从模型 f[xᵢ, φ] 计算一个标量输出。然而,现在大多数神经网络被训练用来预测一个分布的参数 y。(而不是预测 y 的值)。

实际上,网络将输出一个条件概率分布 Pr(y|x),这个分布表示给定输入 x 时各个可能输出 y 的概率。换句话说,每个输入数据点都会生成一个针对每个输出的概率分布。网络的目标是学习这些概率分布的参数,并使用这些参数和分布来预测输出。

传统的损失函数定义是一个比较目标输出和预测输出的函数。但我们刚才说过,网络的原始输出是一个分布,而不是一个标量输出,那么这是如何实现的呢?

从我们刚才定义的视角来看,损失函数推动每个yᵢ在分布Pr(yᵢ|xᵢ)中具有更高的概率。需要记住的关键部分是,我们的分布用于根据模型输出的参数预测真实输出。我们不再使用输入xᵢ来表示分布*,而是可以考虑一个参数化的分布Pr(y|ω),其中ω代表概率分布的参数。我们仍然考虑输入,但每个xᵢ会有不同的ωᵢ = f[xᵢ, φ]*。

注意: 为了澄清一个容易混淆的概念,φ代表模型参数,而ω代表概率分布的参数

推导负对数似然损失

G回到传统的损失函数定义,我们需要从模型中获得一个可用的输出。从我们的概率分布来看,选择φ来产生每个xᵢ的最大概率似乎是合乎逻辑的。因此,我们需要得到在所有训练点I上产生最大概率的总体φ(所有推导都来自《理解深度学习》[1]):

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/522fceb7fdc7af4df7531a2c5537250e.png

最大化输出模型概率分布的参数 [1]

我们将每个分布生成的概率相乘,以找到产生最大概率的φ(称为最大似然)。为了做到这一点,我们必须假设数据是独立且同分布的。但现在我们遇到了一个问题:如果概率非常小怎么办?我们的乘积结果将接近于 0(类似于梯度消失问题)。此外,我们的程序可能无法处理如此小的数字。

为了解决这个问题,我们引入了对数函数!利用对数的特性,我们可以将概率相加,而不是相乘。我们知道,对数是一个单调递增的函数,因此我们的原始输出被保留并通过对数进行了缩放。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/e9d290f8114504d063ca077dce4382fa.png

使用对数加法概率 [1]

我们需要做的最后一件事是获取我们传统的负对数似然,即最小化输出。我们现在是在最大化输出,所以只需要乘以负数并取最小值(考虑一些图形示例来帮助自己理解这一点):

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/fc1c7cee0ae2ea2d49a9ef2760b133ec.png

负对数似然 [1]

仅仅通过将模型输出可视化为一个概率分布,尝试最大化生成最大概率的φ,并应用对数,我们就推导出了负对数似然损失!通过选择一个合适的概率分布,这可以应用于许多任务。下面展示了一些常见的分类示例。

如果你想知道在推断过程中,模型是如何生成标量输出的,那就是分布的最大值:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/77d8057be79a86e22f7758dac179cbec.png

从推断生成输出[1]

注意: 这只是负对数似然的推导。在实践中,损失函数中很可能还会有正则化项。

分类的损失

到目前为止,我们推导了负对数似然。虽然这很重要,但它可以在大多数教科书或在线资源中找到。现在,让我们将其应用于分类问题,以理解它的应用。

附注: 如果你对将其应用于回归感兴趣,《理解深度学习》[1]中有关于单变量回归和高斯分布推导均方误差的很好的例子。

二分类

二分类的目标是将输入x分配到两个类别标签之一,y ∈ {0, 1}。我们将使用伯努利分布作为我们选择的概率分布。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/64d8d4c8478ea774fceb1a8d84d5c783.png

伯努利分布的数学表示。图片来源:作者

这只是一个花哨的说法,表示输出为真的概率,但这个方程是推导损失函数所必需的。我们需要模型f[x, φ]输出p来生成预测的输出概率。然而,在我们将p输入到伯努利分布之前,我们需要确保它在 0 和 1 之间(因为它是一个概率)。用于此的函数是 sigmoid:σ(z)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/9716980d8305f8ba0fce144f11ee2f0d.png

来源:en.wikipedia.org/wiki/Sigmoid_function

Sigmoid 会将输出p压缩到 0 和 1 之间。因此,我们输入伯努利分布的值是p = σ(f[x, φ])。这使我们的概率分布变为:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/32e05e638cc53e6838db0a7dcaeeb77c.png

带有 Sigmoid 和伯努利分布的新概率分布。图片来源:作者

回到负对数似然,我们得到如下结果:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f2e36bf555c46b78ee8cac481211a9c6.png

二元交叉熵。图片来源:作者

看起来很熟悉吧?这就是二元交叉熵(BCE)损失函数!理解这一点的关键是理解为什么使用 sigmoid。我们有一个标量输出,它需要被缩放到 0 和 1 之间。虽然也有其他函数能做到这一点,但 sigmoid 是最常用的。

PyTorch 中的 BCE

在 PyTorch 中实现 BCE 时,需要注意一些技巧。PyTorch 中有两个不同的 BCE 函数:BCELoss()BCEWithLogitsLoss()。一个常见的错误(我也犯过)是错误地交换了它们的使用场景。

BCELoss(): 这个 torch 函数输出的是已经应用了 SIGMOID 的损失值。输出将是一个概率

BCEWithLogitsLoss(): 这个 torch 函数输出的是 logits,即模型的原始输出。没有应用 SIGMOID。当使用这个函数时,你需要对输出应用torch.sigmoid()

这对于迁移学习尤为重要,因为即使你知道模型是使用 BCE 训练的,也要确保使用正确的损失函数。如果没有这样做,可能会在 BCELoss() 后意外地应用 sigmoid,导致网络无法学习……

一旦使用任一函数计算了概率,就需要在推理过程中进行解释。这个概率是模型对结果为真的可能性的预测(类别标签为 1)。需要通过阈值来确定真实标签的截止概率。p = 0.5 是常用的阈值,但测试并优化不同的阈值概率是很重要的。一个好主意是绘制输出概率的直方图,查看输出的置信度,再决定阈值。

多类分类

多类分类的目标是将输入 x 分配给 K > 2 个类别标签 y ∈ {1, 2, …, K} 中的一个。我们将使用分类分布作为我们的概率分布选择。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0a232fbe9bf6255a4b73db74c8d240e9.png

分类分布。图片来源:作者

这只是为给定输出的每个类别分配一个概率,且所有概率的总和必须为 1。我们需要模型 f[x, φ] 输出 p,以生成预测的输出概率。和二分类一样,这里也会遇到总和问题。在将 p 输入到伯努利分布之前,我们需要确保它是一个介于 0 和 1 之间的概率。sigmoid 不再适用,因为它会将每个类别的分数缩放为一个概率,但不能保证所有概率的总和为 1。这点可能不容易发现,但可以通过一个例子来说明:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/83affdb6b334591ba290ca2a040054c9.png

Sigmoid 在多类分类中无法生成概率分布。图片来源:作者

我们需要一个函数来确保满足这两个约束条件。因此,选择了 softmax。softmax 是 sigmoid 的扩展,它会确保所有概率的总和为 1。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/94e889be5ace748c47a8fb0ce491f38a.png

Softmax 函数。图片来源:作者

这意味着概率分布是对模型输出应用的 softmax。计算标签k的似然:Pr(y = k|x) = Sₖ(f[x, φ])。

为了推导多类分类的损失函数,我们可以将 softmax 和模型输出代入负对数似然损失中:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/bfcc77f988d2af066f4750c5d37ad78d.png

多类交叉熵。图片来源:作者

这是多类别交叉熵的推导。需要记住,唯一对损失函数有贡献的项是正确类别的概率。如果你见过交叉熵,你会更熟悉一个包含 p(x)q(x) 的函数。这个公式与交叉熵损失方程是相同的,其中 p(x) = 1 表示正确类别,其他类别的值为 0。q(x) 是模型输出的 softmax。交叉熵的另一个推导来源于使用 KL 散度,你可以通过将一个项视为 Dirac delta 函数(其中包含真实输出)并将另一个项视为模型输出(应用 softmax)来推导出相同的损失函数。需要注意的是,这两种推导方式都得出相同的损失函数。

PyTorch 中的交叉熵

与二元交叉熵不同,PyTorch 中的交叉熵损失只有一个损失函数。nn.CrossEntropyLoss 返回已经应用 softmax 的模型输出。推断可以通过选择最大概率的 softmax 模型输出(选择最高概率的输出)来进行。

应用

这些是两个研究得比较深入的分类例子。对于更复杂的任务,可能需要一些时间来决定使用哪个损失函数和概率分布。有很多图表可以帮助将概率分布与目标任务匹配,但总有空间可以进一步探索。

对于某些任务,将损失函数组合起来可能会有帮助。一个常见的应用场景是在分类任务中,可能有助于将[二元]交叉熵损失与修改过的 Dice 系数损失结合使用。大多数时候,损失函数会被加在一起,并通过某个超参数进行缩放,以控制每个函数对总损失的贡献。

希望这个关于负对数似然损失及其应用的推导对你有所帮助!

参考文献

[1] Prince, Simon J.D., 理解深度学习

[2] 斯坦福 CS231n

[3] P. Bosman, D. Thierens, 负对数似然与统计假设检验作为 IDEAs 中模型选择的基础(2000 年)。

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值