softmax交叉熵损失函数深入理解(二)

article/2025/9/10 3:42:12

0、前言

        前期博文提到经过两步smooth化之后,我们将一个难以收敛的函数逐步改造成了softmax交叉熵损失函数,解决了原始的目标函数难以优化的问题。Softmax 交叉熵损失函数是目前最常用的分类损失函数,本博文继续学习Softmax 交叉熵损失函数的改进,详细的理论参考论文《基于深度学习的人脸认证方法研究》,这篇论文真的太棒了,是我见过最优秀的专门针对损失函数进行深入研究的杰作。

1、Softmax 交叉熵损失函数

 (1)Softmax 交叉熵损失函数表达

        将样本分为 C 个类别,在使用 Softmax 交叉熵损失时,需要将神经网络的最后一层输出设置为 C。设置理想向量q=[q_{1},q_{2},...,q_{c}], Softmax 交叉熵损失函数表示如下:

\l _{s}=-\sum q_{i}logp_{i}

其中:P_{i}=\frac{e^{z_{i}}}{\sum(e^{z_{i}})}

Softmax 交叉熵损失函数实际上分为两步:

1)求 Softmax : 得到当前样本属于某类别的概率P_{i}=\frac{e^{z_{i}}}{\sum(e^{z_{i}})}

2)求交叉熵损失

       将1)计算所得概率与理想向量求交叉熵:

       ①如果理想向量为 One-hot 向量,即仅在第 y 个位置为 1,其他部分为 0,所以最终只保留了第 y 个位置的交叉熵。此时的Softmax 交叉熵损失函数表示为:

\l _{s}=-logp_{y}

 梯度为:

        ②如果理想分布不再是 One-hot 向量,而是一组其他概率值时q=[q_{1},q_{2},...,q_{c}],交叉熵损失函数为:

\l _{s}=-\sum q_{i}logp_{i}

       梯度为:

       可以看到梯度形式非常简单 ,也更容易实现。 由于最小化Softmax 交叉熵损失会让可以Softmax 概率无限尝试逼近 1 ,这有可能会带来过拟合效应。由1中分析可知,当理想分布不再是 One-hot 向量,而是一组其他概率值时q=[q_{1},q_{2},...,q_{c}],交叉熵损失函数的梯度更简单,因此可以考虑标签柔化(Label Smoothing)即将理想分布的 One-hot 向量柔化为如下形式:

        此时的理想向量并不是0、1组合,最小值小于1,最小值大于0。此外,模型蒸馏法将一个大模型输出的概率值进行柔化来作为理想分布优化小模型,这样可以使得小模型能够得到更多的信息来进行训练,而不只是简单地去学习 0和 1。 

(2)Softmax 交叉熵损失函数训练得到的特征分布

        下图为在 MNIST 数据集上,使用 Softmax 交叉熵损失函数训练得到的二维特征分布,这是欧氏距离下该模型判别失败的例子(图中f_{1},f_{2},f_{3}表示三个样本的二维特征向量,可以看出基于欧式距离相似度量方法,D_{s}(f_{1},f_{2})<D_{s}(f_{2},f_{3}),即f_{1}f_{2}属于一个类别可能性更高,但实际上f_{2}f_{3}才同属一个簇,因此在 Softmax 交叉熵损失函数训练得到的特征空间下采用欧式距离度量有可能失败!)

        下图为在 MNIST 数据集上,使用 Softmax 交叉熵损失函数训练得到的二维特征分布,这是内积相似度下该模型判别失败的例子(图中f_{1},f_{2},f_{3}表示三个样本的二维特征向量,可以看出基于内积相似度量方法,r(f_{1},f_{2})< r(f_{2},f_{3}),即f_{2},f_{3}属于一个类别可能性更高,但实际上f_{1},f_{2}才同属一个簇,因此在 Softmax 交叉熵损失函数训练得到的特征空间下采用内积度量有可能失败!)

         从上面两个图可以看出:Softmax 交叉熵损失函数训练出来的特征呈辐射状分布,在这种分布下,特征向量的长度(模的大小)改变将不影响该特征的类别判定而不同类之间的区别主要由角度来决定因此内积、欧氏距离这些与幅度相关的相似性度量的效果就不如余弦这种与幅度无关的相似性度量。至于 Softmax 交叉熵损失函数训练出的特征分布为什么呈辐射型,是因为如果将特征幅度(模的大小)放大或缩小,那样本特征向量与各类别权重之间的内积相似度也会同时放大或缩小,这时最大的相似度仍旧还是最大的,不会对该特征被归到的类别产生影响。

        上述分析可以看出,传统的 Softmax 交叉熵损失函数并不是很适合人脸认证这一度量学习任务,需要进行改进。因此论文《基于深度学习的人脸认证方法研究》在深入分析传统的 Softmax 交叉熵损失函数用在人脸认证这样的度量学习上的一些特性基础上,对Softmax 交叉熵损失函数进行改进。

        

2、人脸认证损失函数存在的不足

        深度神经网络在多项计算机视觉任务,尤其是图像分类上取得了令人瞩目的成绩。对于人脸认证任务,基于深度学习的方法也已经在多个数据集上超过了人类,然而之前的大多数方法采用的损失函数仍然存在着一些缺陷。当今的人脸认证损失函数分为两大类:基于分类的损失函数和基于度量学习的损失函数,基于分类的损失函数在训练与测试过程中的不匹配问题,基于度量学习的损失函数又存在着难以找到合适的采样方法的问题,这些问题在以往的工作中往往被一笔带过,没有做过详细的分析,不过这也给后面的研究者留下了很多研究的空间。

 (1)基于分类的损失函数在训练与测试过程中的不匹配问题

        一个典型的基于分类的方法在训练和测试中的流程图下图所示:

         这一类的方法通常在训练时使用内积相似度,而在测试时使用余弦相似度来比对两张人脸图像的特征,这就产生了训练与测试之间不匹配的问题。

        内积相似度与余弦相似度之间的区别在于余弦相似度多了一步特征归一化的操作,不加这个归一化操作,模型的识别率会有显著的下降。

        既然在测试时加和不加特征归一化的区别这么明显,那如果在训练的时候也加入特征归一化操作,使得训练与测试时使用的相似度相吻合,相信也能使模型的性能得到提升。这种使训练与测试匹配的策略在深度学习领域叫作端到端学习,让神经网络直接对测试时的指标进行优化,往往能得到更好的结果。

        论文《基于深度学习的人脸认证方法研究》分析了传统的 Softmax 交叉熵损失函数用在度量学习上的一些特性以及产生的一系列问题(博客第1节内容),可以看到,传统的 Softmax 交叉熵损失函数并不是很适合人脸认证这一度量学习任务,因此论文使用 Softmax 交叉熵损失函数优化余弦相似度,提出了余弦 Softmax 交叉损失函数,使得其适用于人脸认证这一度量学习任务.

余弦 Softmax 交叉损失函数

 (2)基于度量学习的损失函数难以找到合适的采样方法的问题

        深度度量学习,通常需要输入一对或者一组样本,在经过一系列的特征变换后输出这些样本之间的距离,使得同样类别的样本之间的距离较小而不同类样本之间的距离较大。相比于基于分类的损失函数,度量学习的损失函数看起来更加适合人脸认证任务,因为人脸认证在测试时也是输入两张图像输出其相似度,这与度量学习的目标函数一致。

        然而在实际的训练过程中,度量学习的损失函数普遍存在难调参、难收敛的情况,这其中一部分原因是度量学习损失只关心局部,而丢弃掉了全局监督信号;另一部分原因是训练度量学习损失模型通常需要采样样本对或样本组来训练,而目前人脸识别的数据规模较大,通常达到百万到上亿量级。度量学习损失往往无法采样完全,比如说如果使用 Contrastive 损失则需要采样O(N^{2}) 个样本组合,使用 Triplet损失则需要采样 O(N^{3})个样本组合,这在目前的大型数据库下几乎是不可能实现的任务,这样庞大的样本组合内其实也有大量的样本组是已经满足了度量学习要求的,不需要再次进行训练。所以研究者们提出要使用难例挖掘的办法来进行采样,而这一过程往往需要引入一些超参数也需要很多技巧。

        而基于分类的损失函数只需要不断地将样本输入进网络即可,其样本复杂度只有 O(N),而且一般也不需要难例挖掘。论文《基于深度学习的人脸认证方法研究》直接提出将度量学习的损失函数改造成为分类损失函数,以降低其对样本采样的要求。论文提出了“类代理”的概念,通过给每个类别分配一个类代理,就可以将多样本之间距离度量的学习转换为一个样本对多个类代理之间
距离度量的学习,从而避免了样本采样带来的问题。

        最常用的深度度量学习方法有 Contrastive 损失:

        和 Triplet 损失:

        其中这两个 m 都表示类间间隔。这两个方法都是在优化归一化后的两个特征向量的欧氏距离,注意到归一化后的欧氏距离与余弦距离之间有如下关系:

        利用这个公式,将前文的余弦 Softmax 损失函数改写为优化归一化后的欧氏距离的形式:

        在使用了类代理(用一个类似于权重的向量,来代替各类样本)之后,就可以得到分类版本的Contrastive 损失( C-Contrastive 损失):

 

和 分类版本的Triplet 损失( C-Triplet 损失):

 C-Contrastive 损失函数在两类、三维球面情况下,类代理与类中心之间关系的示意图如下:

(a) m = 0 时的情况;(b)m = 1 时的情况(可变类间间隔 m)

 

 

       

 

 

 

        


http://chatgpt.dhexx.cn/article/FkAv63N0.shtml

相关文章

史上最全交叉熵损失函数详解

在我们自学神经网络神经网络的损失函数的时候会发现有一个思路就是交叉熵损失函数&#xff0c;交叉熵的概念源于信息论&#xff0c;一般用来求目标与预测值之间的差距。比如说我们在人脑中有一个模型&#xff0c;在神经网络中还有一个模型&#xff0c;我们需要找到神经网络模型…

交叉熵损失函数原理详解

交叉熵损失函数原理详解 之前在代码中经常看见交叉熵损失函数(CrossEntropy Loss)&#xff0c;只知道它是分类问题中经常使用的一种损失函数&#xff0c;对于其内部的原理总是模模糊糊&#xff0c;而且一般使用交叉熵作为损失函数时&#xff0c;在模型的输出层总会接一个softm…

损失函数——交叉熵损失函数

一篇弄懂交叉熵损失函数 一、定义二、交叉熵损失函数&#xff1a;知识准备&#xff1a;1、信息熵&#xff1a;将熵引入到信息论中&#xff0c;命名为“信息熵”2、 KL散度&#xff08;相对熵&#xff09;&#xff1a; 交叉熵&#xff1a;结论&#xff1a; Softmax公式Sigmoid常…

交叉熵损失函数详解

我们知道&#xff0c;在二分类问题模型&#xff1a;例如逻辑回归「Logistic Regression」、神经网络「Neural Network」等&#xff0c;真实样本的标签为 [0&#xff0c;1]&#xff0c;分别表示负类和正类。模型的最后通常会经过一个 Sigmoid 函数&#xff0c;输出一个概率值&am…

交叉熵损失函数(CrossEntropy Loss)(原理详解)

监督学习主要分为两类&#xff1a; 分类&#xff1a;目标变量是离散的&#xff0c;如判断一个西瓜是好瓜还是坏瓜&#xff0c;那么目标变量只能是1&#xff08;好瓜&#xff09;,0&#xff08;坏瓜&#xff09;回归&#xff1a;目标变量是连续的&#xff0c;如预测西瓜的含糖率…

nn.CrossEntropyLoss()交叉熵损失函数

1、nn.CrossEntropyLoss() 在pytorch中nn.CrossEntropyLoss()为交叉熵损失函数&#xff0c;用于解决多分类问题&#xff0c;也可用于解决二分类问题。在使用nn.CrossEntropyLoss()其内部会自动加上Sofrmax层 nn.CrossEntropyLoss()的计算公式如下&#xff1a; 其中&#xff0c…

损失函数——交叉熵损失函数(CrossEntropy Loss)

损失函数——交叉熵损失函数&#xff08;CrossEntropy Loss&#xff09; 交叉熵函数为在处理分类问题中常用的一种损失函数&#xff0c;其具体公式为&#xff1a; 1.交叉熵损失函数由来 交叉熵是信息论中的一个重要概念&#xff0c;主要用于度量两个概率分布间的差异性。首先…

损失函数——交叉熵损失(Cross-entropy loss)

交叉熵损失&#xff08;Cross-entropy loss&#xff09;是深度学习中常用的一种损失函数&#xff0c;通常用于分类问题。它衡量了模型预测结果与实际结果之间的差距&#xff0c;是优化模型参数的关键指标之一。以下是交叉熵损失的详细介绍。 假设我们有一个分类问题&#xff0…

【Pytorch】交叉熵损失函数 CrossEntropyLoss() 详解

文章目录 一、损失函数 nn.CrossEntropyLoss()二、什么是交叉熵三、Pytorch 中的 CrossEntropyLoss() 函数参考链接 一、损失函数 nn.CrossEntropyLoss() 交叉熵损失函数 nn.CrossEntropyLoss() &#xff0c;结合了 nn.LogSoftmax() 和 nn.NLLLoss() 两个函数。 它在做分类&a…

一文读懂交叉熵损失函数

进行二分类或多分类问题时&#xff0c;在众多损失函数中交叉熵损失函数较为常用。 下面的内容将以这三个问题来展开 什么是交叉熵损失以图片分类问题为例&#xff0c;理解交叉熵损失函数从0开始实现交叉熵损失函数 1&#xff0c;什么是交叉熵损失 交叉熵是信息论中的一个重…

交叉熵损失函数

目录 一、交叉熵损失函数含义 二、交叉熵损失函数定义为&#xff1a;​ 三、交叉熵损失函数计算案例 一、交叉熵损失函数含义 交叉熵是一个信息论中的概念&#xff0c;它原来是用来估算平均编码长度的。给定两个 概率分布p和q&#xff0c;通过q来表示p的交叉熵为 交叉熵刻画…

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

基础不牢&#xff0c;地动山摇&#xff0c;读研到现在有一年多了&#xff0c;发现自己对很多经常打交道的知识并不了解&#xff0c;仅仅是会改一改别人的代码&#xff0c;这使我感到非常焦虑&#xff0c;自此开始我的打基础之路。如果博客中有错误的地方&#xff0c;欢迎大家评…

js遍历数组中的对象并拿到值

拿到一组数组&#xff0c;数组中是对象&#xff0c;想拿到这个对象里面的某个值&#xff0c;可以参考以下例子&#xff1a; 这样就拿到所有n1的值. 想拿到这个对象里面所有对应的值如下&#xff1a; 也可以这样取值&#xff1a; 往数组里面push多个值&#xff1a; js中!!用法 …

js遍历数组以及获取数组对象的key和key的值方法

数组&#xff1a; let arr [{ appendData: { "Expiration Date mm- dd - yyyy(2D)": "03-04-2025" }},{appendData: { "Manufacturer(21P)": "MURATA" }}]arr.forEach((value,i)>{ //数组循环for(var pl in value){ //数组对象遍…

javascript遍历数组的方法总结

一、for循环 var arr[javascript,jquery,html,css,学习,加油,1,2]; for(var i0;i<arr.length;i){console.log(输出值,arr[i]); } 二、for...in 遍历的是key 适合遍历对象 var arr[javascript,jquery,html,css,学习,加油,1,2]; for(var i in arr){ console.log(输出值---…

html函数参数数组遍历,JavaScript foreach遍历数组

JavaScript forEach遍历数组教程 JavaScript forEach详解 定义 forEach() 方法为每个数组元素调用一次函数(回调函数)。 语法 array.forEach(function(currentValue, index, arr), thisValue); 参数 参数 描述 function(currentValue, index, arr) 必须。数组每个元素需要执行的…

js中遍历数组加到新数组_js数组遍历:JavaScript如何遍历数组?

什么是数组的遍历? 操作数组中的每一个数组元素。 使用for循环来遍历数组 因为数组的下标是连续的&#xff0c;数组的下标是从0开始。 我们也可以得到数组的长度。 格式&#xff1a;for(var i0;i 数组变量名[i] } 注意&#xff1a;条件表达式的写法 i i<数组的长度-1 // 数…

html页面遍历数组,javascript如何遍历数组?

作为一个程序员对于数组遍历大家都不是很陌生&#xff0c;在开发中我们也经常要处理数组。这里我们讨论下JavaScript中常用的数组遍历方法。 数组中常用的遍历方法有四种&#xff0c;分别是&#xff1a;for for-in forEach for-of (ES6) 1、第一种for循环var arr [1, 2, 3, 4]…

JavaScript遍历数组,附5个案例

先给大家分享一些JavaScript的相关资料&#xff1a; 认识JavaScript到初体验JavaScript 注释以及输入输出语句JavaScript变量的使用、语法扩展、命名规范JavaScript数据类型简介以及简单的数据类型JavaScript获取变量数据类型JavaScript 运算符&算数运算符JavaScript递增和…

1.9 JavaScript 遍历数组

遍历数组 数组的长度 使用 “数组名.length” 可以访问数组元素的数量&#xff08;数组长度&#xff09; a.length 动态监测数组元素的个数 案例 请将 [“关羽”, “张飞”, “赵云”,“小脆筒”], 将数组里的元素依次打印到控制台 代码实现 <!DOCTYPE html> <html&…