jjzjj

损失函数(Loss Function)一文详解-分类问题常见损失函数Python代码实现+计算原理解析

fanstuck 2023-08-06 原文

目录

前言

一、损失函数概述

二、损失函数分类

1.分类问题的损失函数

1.交叉熵损失函数(Cross Entropy Loss)

2.Hinge损失函数

3.余弦相似度损失函数(Cosine Similarity Loss)

4.指数损失函数(Exponential Loss)

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢


前言

损失函数无疑是机器学习和深度学习效果验证的核心检验功能,用于评估模型预测值与实际值之间的差异。我们学习机器学习和深度学习或多或少都接触到了损失函数,但是我们缺少细致的对损失函数进行分类,或者系统的学习损失函数在不同的算法和任务中的不同的应用。因此有必要对整个损失函数体系有个比较全面的认识,方便以后我们遇到各类功能不同的损失函数有个清楚的认知,而且一般面试以及论文写作基本都会对这方面的知识涉及的非常深入。故本篇文章将结合实际Python代码实现损失函数功能,以及对整个损失函数体系进行深入了解。

博主专注建模四年,参与过大大小小数十来次数学建模,理解各类模型原理以及每种模型的建模流程和各类题目分析方法。此专栏的目的就是为了让零基础快速使用各类数学模型、机器学习和深度学习以及代码,每一篇文章都包含实战项目以及可运行代码。博主紧跟各类数模比赛,每场数模竞赛博主都会将最新的思路和代码写进此专栏以及详细思路和完全代码。希望有需求的小伙伴不要错过笔者精心打造的专栏。


一、损失函数概述

我们举一个通俗的例子:”假如你玩一个抽卡游戏,这段时间新活动刚好出了一个新的角色你想要抽到她,一般来说抽到这个角色基本都要保底,大部分人都需要一个648才能抽到,但是你的手气实在太非了,氪了两个648才抽到了,那么这和你预估的结果少了一个648的钱,也就是你大抵损失的金额。“通过上面这个例子我们再将大部分人预估抽到的金额设定为Y,而且实际用到的抽奖金额为Y',那么两者的差距|Y-Y'|就是损失函数了。

那么我们通过案例很容易明白损失函数就是用以衡量实际值和预测值在当前位置的差值或误差,这提高了一些模型的有效性,通过向模型提供反馈,使其可以调整参数以最大程度减少误差。

二、损失函数分类

 

我们知道损失函数就是衡量预测值和实际值的差量,那么根据算法需要解决的目标问题分类就可以将整个损失函数进行分类。

1.分类问题的损失函数

分类问题是机器学习领域中最为常见的问题之一。在分类问题中,我们需要根据给定的输入特征将其分为多个预定义的类别之一。分类问题的损失函数是用来评估分类器的预测值与真实标签之间的差异,从而指导分类器的训练。

1.交叉熵损失函数(Cross Entropy Loss)

交叉熵损失函数是用于度量分类问题中预测值与真实标签之间的差距,它在深度学习中得到了广泛的应用。交叉熵损失函数在多分类问题中的表现非常好,比如在图像分类、自然语言处理等领域。

假设有个类别,对于一个样本,其真实类别标签是 ,模型预测的类别概率分布为 ,其中表示样本属于第类的概率。那么交叉熵损失函数的计算公式为:

 其中,表示样本是否属于第类,表示属于,表示不属于。因为对于每个样本来说,只有一个标签是正确的,所以这个损失函数的实际含义是用正确的标签来对模型预测结果进行惩罚。

交叉熵损失函数的本质是用来度量两个概率分布之间的距离。在分类问题中,我们希望模型输出的概率分布能够与真实标签的分布尽量接近。如果预测值和真实值相同,交叉熵损失函数就趋近于。如果预测值和真实值不同,交叉熵损失函数就会变得非常大。

在Python中,可以使用TensorFlow、PyTorch等深度学习框架中提供的函数来计算交叉熵损失函数。

在TensorFlow 2.x版本中,可以使用tf.keras.losses模块提供的交叉熵损失函数来进行计算。

import tensorflow as tf

# 定义标签和预测值
y_true = [[0, 1], [0, 0]]
y_pred = [[0.6, 0.4], [0.4, 0.6]]

# 定义交叉熵损失函数
cross_entropy_loss = tf.keras.losses.CategoricalCrossentropy()

# 计算损失函数值
loss = cross_entropy_loss(y_true, y_pred)

print(loss.numpy())  # 输出损失函数值

 y_true表示真实标签,y_pred表示预测值。通过tf.keras.losses.CategoricalCrossentropy()定义交叉熵损失函数,然后调用该函数并传入真实标签和预测值即可计算损失函数值。

在PyTorch中,可以使用torch.nn.CrossEntropyLoss()函数来计算交叉熵损失函数。

import torch
# 计算交叉熵损失函数
logits = torch.tensor([[1.0, 2.0, 3.0], [2.0, 1.0, 3.0], [3.0, 2.0, 1.0]]) # 预测值
labels = torch.tensor([2, 1, 0]) # 真实值
criterion = torch.nn.CrossEntropyLoss()
loss = criterion(logits, labels)

print(loss.item())

 

2.Hinge损失函数

Hinge损失函数是一种常用于支持向量机(SVM)的损失函数,用于解决分类问题。

假设有训练集,其中为输入特征向量,为输出标签。分类问题的目标是在训练集上学习一个线性分类器,使得预测标签和真实标签的误差最小。

Hinge损失函数的定义如下:

 其中,为真实标签,为预测标签。如果预测正确,则误差为0;如果预测错误,则误差为。这里的表示真实标签和预测标签之间的乘积。

对于线性分类器,我们可以用决策函数来表示。其中,为权重向量,为偏置项。我们希望找到一个最优的,使得在训练集上的损失函数最小化。

Hinge损失函数的优化目标是:

 为了优化Hinge损失函数,我们可以使用梯度下降算法来求解最优的权重向量和偏置项。具体来说,对于第个样本,其梯度为:

 在每一轮迭代中,我们随机选择一个样本,并更新权重向量和偏置项:

 其中,为学习率。这样不断地迭代,直到达到收敛条件为止。

在Python中,可以使用NumPy库实现Hinge损失函数的计算。

import numpy as np

def hinge_loss(y_true, y_pred):
    # 计算每个样本的Hinge损失
    loss = np.maximum(0, 1 - y_true * y_pred)
    # 计算所有样本的平均损失
    avg_loss = np.mean(loss)
    return avg_loss

 其中,y_true是真实标签,y_pred是模型的预测输出。这个函数返回的是所有样本的平均Hinge损失。如果想要计算单个样本的Hinge损失,可以直接使用np.maximum(0, 1 - y_true * y_pred)

3.余弦相似度损失函数(Cosine Similarity Loss)

余弦相似度(Cosine Similarity)是一种常用的相似度度量方法,通常用于计算两个向量之间的相似程度。在神经网络中,可以使用余弦相似度损失函数来度量模型输出的向量与标签向量之间的相似程度。其计算原理如下:

假设模型输出的向量为 ,标签向量为 ,则余弦相似度可以表示为它们之间的夹角余弦值:

 其中, 表示 的内积,分别表示的模长。由于余弦相似度的取值范围之间,因此可以使用作为损失函数,使得损失函数的取值范围在 之间。

的夹角较小时,它们的余弦相似度较大,损失函数的取值较小,表示模型的输出与标签的相似度较高;当 较大时,它们的余弦相似度较小,损失函数的取值较大,表示模型的输出与标签的相似度较低。

因此,使用余弦相似度损失函数可以促进模型输出向量与标签向量之间的相似程度的提高。

余弦相似度损失函数的计算过程比较简单,可以直接使用NumPy实现。假设有两个向量,则余弦相似度损失函数的计算方法如下:

import numpy as np

def cosine_loss(x, y):
    # 计算向量x和y的余弦相似度
    cosine_sim = np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y))
    # 将余弦相似度转化为损失
    loss = 1 - cosine_sim
    return loss

 其中,np.dot(x, y)表示向量的点积,np.linalg.norm(x)表示向量的范数,1 - cosine_sim表示余弦相似度损失函数的值。

4.指数损失函数(Exponential Loss)

指数损失函数(Exponential Loss)是一种二分类损失函数,通常用于概率估计问题。

假设有一组数据 ,其中 是一个 维特征向量,是一个二分类的标签,表示样本属于哪一类。对于一个给定的模型,它可以计算每个样本属于正类的概率 ,则指数损失函数可以表示为:

 其中 是样本的真实标签,是样本属于正类的预测概率。指数损失函数的含义是:如果样本的真实标签为 ,但是模型预测其属于负类的概率 较高,那么指数损失函数的值将会非常大;反之,如果样本的真实标签为 ,但是模型预测其属于正类的概率 较高,那么指数损失函数的值也会非常大。

对于一组数据 ,假设模型的参数为,则该数据集上的指数损失函数可以表示为:

 

其中是数据集的大小。对于一个二分类问题,表示样本 属于正类的概率,可以通过模型输出的概率值计算得到。

模型的训练目标是最小化所有样本的指数损失函数之和,即:

 

可以使用梯度下降等优化算法求解上述问题。

需要注意的是,指数损失函数对异常值比较敏感,因此需要注意数据的预处理和模型的选择。

import numpy as np

def exponential_loss(y_true, y_pred):
    """
    计算指数损失函数
    :param y_true: 真实标签,形状为(n_samples, )
    :param y_pred: 模型预测概率,形状为(n_samples, )
    :return: 指数损失值,标量
    """
    loss = np.exp(-y_true * y_pred)
    return np.mean(loss)

 对于二分类问题,真实标签通常为1或-1,模型的预测概率通常为一个实数,可以通过sigmoid函数将其转换为0到1之间的概率值。对于多分类问题,可以使用softmax函数将模型的输出转换为概率分布。

那么分类问题常见损失函数就已经差不多了,下一章我将详细对回归问题的损失函数进行讲解。


点关注,防走丢,如有纰漏之处,请留言指教,非常感谢

以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见。

有关损失函数(Loss Function)一文详解-分类问题常见损失函数Python代码实现+计算原理解析的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  6. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  7. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  8. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  9. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  10. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

随机推荐