机器学习面试题汇总与解析——损失函数

本章讲解知识点

    1. 什么是损失函数?
    1. 为什么要使用损失函数?
    1. 详细讲解损失函数


  • 本专栏适合于Python已经入门的学生或人士,有一定的编程基础。

  • 本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。

  • 本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。这才是一份面试题总结的正确打开方式。这样才方便背诵

  • 如专栏内容有错漏,欢迎在评论区指出或私聊我更改,一起学习,共同进步。

  • 相信大家都有着高尚的灵魂,请尊重我的知识产权,未经允许严禁各类机构和个人转载、传阅本专栏的内容。


  • 关于机器学习算法书籍,我强烈推荐一本《百面机器学习算法工程师带你面试》,这个就很类似面经,还有讲解,写得比较好。

  • 关于深度学习算法书籍,我强烈推荐一本《解析神经网络——深度学习实践手册》,简称 CNN book,通俗易懂。



1. 什么是损失函数?

1.1 定义

损失函数(Loss function),也称为目标函数(Objective function)、代价函数(Cost function)或误差函数(Error function),是在机器学习和优化问题中使用的一种函数。它衡量了模型预测结果与实际目标之间的差异或误差程度

损失函数的作用是量化模型的性能,指导模型参数的优化和训练过程。通过最小化损失函数,我们可以使模型在给定数据上得到更好的拟合,并提高其泛化能力。

在监督学习任务中,损失函数通常基于模型的预测输出与真实标签之间的差异来定义。具体来说,给定训练样本的输入特征和对应的目标标签,模型通过输入特征计算出预测值,然后使用损失函数来度量预测值与目标标签之间的差异。通过对所有样本计算损失函数的平均值或总和,可以得到模型在整个数据集上的损失。

1.2 常见的损失函数

  • 均方误差损失函数(Mean Squared Error, MSE):用于回归问题,计算预测值与目标值之间的平方差。
  • 交叉熵损失函数(Cross-Entropy Loss):用于分类问题,衡量预测概率分布与真实标签之间的差异。
  • 绝对值损失函数(Absolute Error Loss):也称为 L1 损失函数,计算预测值与目标值之间的绝对差值。
  • 对数损失函数(Logarithmic Loss):常用于二分类问题,用于评估二分类概率预测的质量。
  • Hinge 损失函数:用于支持向量机(SVM)中的分类问题,通过边界间隔来衡量分类错误。

选择合适的损失函数取决于具体的问题和模型类型。优化算法通过最小化损失函数来更新模型的参数,使其能够更好地拟合数据,并使损失尽可能地减少。

1.3 损失函数的分类

损失函数可以分为经验风险损失函数(empirical risk loss function)和结构风险损失函数(structural risk loss function)。

  • 经验风险损失函数:经验风险是指模型在训练数据上的平均损失(预测结果实际结果的差值)。经验风险损失函数是根据训练数据上的损失计算的,它衡量了模型在训练集上的性能。常见的经验风险损失函数包括均方误差损失函数(MSE)和交叉熵损失函数等。优化经验风险损失函数的目标是使模型在训练数据上获得较低的损失。

  • 结构风险损失函数:结构风险是指模型在训练数据上的经验风险和模型复杂度之间的权衡。结构风险损失函数考虑了模型的复杂度,并在优化过程中平衡了经验风险和模型复杂度。结构风险损失函数旨在防止过拟合(overfitting)现象,即模型在训练集上表现良好但在未见过的数据上表现较差。常见的结构风险损失函数包括正则化项(如 L1 正则化和 L2 正则化)与经验风险损失函数的组合。优化结构风险损失函数的目标是使模型在训练数据上获得较低的损失同时保持模型的泛化能力。

简单来说:损失函数分为经验风险损失函数结构风险损失函数。经验风险损失函数指预测结果实际结果的差值,结构风险损失函数是指经验风险损失函数加上正则项


2. 为什么要使用损失函数?

假设有一个农场主,他种植着各种水果,包括苹果、橙子和梨。这位农场主非常注重水果的质量,并希望能够根据水果的大小和成熟程度来预测它们的价格。他决定使用机器学习来构建一个模型,以便根据水果的特征预测它们的价格。

为了训练模型,农场主收集了大量的数据,包括水果的大小、成熟程度和对应的实际价格。他决定使用线性回归模型,因为它能够对连续值进行预测。

img

然而,农场主面临一个挑战:模型怎么知道自己的预测与实际价格之间的差异呢?必须要有一个东西来衡量预测与实际价格之间的差异,再将这个差异告诉模型,模型才知道自己预测的方向是否正确,它才能调整自己的参数,以使自己预测的更加准确。这个东西就是损失函数,衡量模型是否预测准确的指标。

农场主选择了均方误差(MSE)作为损失函数。他计算每个样本的预测价格与实际价格之间的差值的平方,并将这些差值进行求和或平均。这个损失函数表示了模型预测与真实价格之间的平均误差

通过计算损失函数,农场主能够得到模型在训练集上的损失值。他希望尽量减小这个损失值,因为这意味着模型的预测结果与实际价格更接近

农场主使用梯度下降等优化算法来最小化损失函数。他根据损失函数的梯度,调整模型的参数和权重,以减小预测与实际价格之间的差异。随着训练的进行,模型逐渐优化,损失值逐渐减小。

最终,农场主得到了一个经过训练的模型,它能够根据水果的大小和成熟程度预测它们的价格。通过使用损失函数,农场主能够衡量模型的性能并指导模型的训练过程,以使预测结果尽可能地接近实际价格。


3. 详细讲解损失函数

3.1 用于回归任务的损失函数

我们先解释一个概念,什么是回归?

回归(Regression)是一种统计学习方法,用于预测和建立变量之间的关系。它通过建立一个数学模型来描述自变量(输入)和因变量(输出)之间的关系,以便根据已知的自变量值预测未知的因变量值

在回归分析中,常见的回归模型包括线性回归、多项式回归、岭回归、Lasso 回归、逻辑回归等。这些模型使用不同的数学函数和参数来拟合数据并预测因变量的值。

回归分析的步骤通常包括:

  • 收集和整理数据集,包括自变量和因变量的观测值。
  • 选择适当的回归模型,并根据数据拟合模型的参数。
  • 评估模型的拟合程度和预测能力,可以使用各种评估指标如均方误差(Mean Squared Error)和决定系数(Coefficient of Determination)等。
  • 利用拟合好的回归模型进行预测,给定新的自变量值来估计因变量的值。

比如我们上面举的农场主买水果的例子就是典型的线性回归模型,使用机器学习来构建一个模型,以便根据水果的特征预测它们的价格

回归任务中常用的损失函数包括:

  • 均方误差(Mean Squared Error,MSE):均方误差是最常用的回归损失函数之一。它计算预测值与真实值之间的差的平方的平均值,用于衡量预测值与真实值之间的平均误差。 MSE=(1/n)Σ(yy^)2MSE = (1/n) * Σ(y - ŷ)^2。其中,nn 表示样本的数量,yy 表示真实值,y^ŷ 表示预测值。对于每个样本,计算真实值与预测值之间的差的平方,然后将所有样本的差的平方求和,并除以样本数量 nn,得到平均的差的平方值。 通过计算均方误差,可以衡量预测值与真实值之间的平均误差的大小。较小的均方误差表示预测值与真实值之间的差异较小,模型的预测性能较好。在训练过程中,目标是最小化均方误差,通过调整模型的参数来优化模型的预测能力。

  • 均绝对误差(Mean Absolute Error,MAE):均绝对误差是计算预测值与真实值之间绝对差的平均值。与均方误差不同,均绝对误差不考虑差的平方,而是直接取绝对值。 MAE=(1/n)Σyy^MAE = (1/n) * Σ|y - ŷ|。其中,nn 表示样本的数量,yy 表示真实值,y^ŷ 表示预测值。对于每个样本,计算真实值与预测值之间的绝对差,然后将所有样本的绝对差求和,并除以样本数量n,得到平均的绝对差值。 与均方误差相比,均绝对误差更加注重预测值与真实值之间的绝对差异,而不是差异的平方。均绝对误差相对于均方误差更加鲁棒,对于异常值(离群点)的影响较小。在一些需要更加关注误差的绝对值的场景中,可以使用均绝对误差作为损失函数进行模型训练和评估。

  • 对数损失(Logarithmic Loss):对数损失用于二元分类问题中,也可以用于回归问题。它基于预测值和真实值之间的对数差异来计算损失,可以惩罚预测值与真实值之间的较大差异LogarithmicLoss=(ylog(y^)+(1y)log(1y^))Logarithmic Loss = - (y * log(ŷ) + (1 - y) * log(1 - ŷ))。其中,yy 表示真实标签(取值为 0 或 1),y^ŷ 表示模型预测的概率值(取值范围为 0 到 1)。对于每个样本,计算真实标签对应的预测概率的对数值以及反向标签对应的预测概率的对数值,然后取负数求和。

3.2 用于分类任务的损失函数

分类任务,顾名思义,就是分类,比如对图片中的动物分类,区别其是狗还是猫。

在分类任务中,常用的损失函数有以下几种:

  • 0-1 损失函数(Zero-One Loss):0-1 损失函数是一种用于分类问题的损失函数,它在预测结果正确时取值为 0,预测结果错误时取值为 1。具体公式如下:

    L(y,y^)={1,yy^0,y=y^L(y,ŷ)=\begin{cases}1,\quad y\neq ŷ\\ 0, \quad y=ŷ \\ \end{cases} \\

    yy 表示真实值,y^ŷ 表示预测值。意义很清楚,预测结果等于真实结果,那么损失为 0(损失可以理解为偏差);而如果不等于,损失就为 1。 很明显,非黑即白,所以这个损失函数是比较严格的,同时需要注意的是,0-1 损失函数是一个非连续、不可导的函数,因此在实际优化算法中很少直接使用。比如在感知机用的这个损失函数。 实际上我们可以放宽条件,如下公式:

    L(y,y^)={1,yy^T0,yy^<TL(y,ŷ)=\begin{cases}1,\quad |y-ŷ|\geq T\\ 0, \quad |y-ŷ|< T \\ \end{cases} \\

    这里我们可以设置一个阈值 TT,这样就没那么严格了。

  • 对数损失(Log Loss):也称为二元交叉熵损失,用于二分类问题。衡量预测结果与真实结果之间的差异,鼓励模型对正确类别的预测概率高,对错误类别的预测概率低。具体公式如下:

    L(y,P(yx))=logP(yx)L(y,P(y|x))=-logP(y|x) \\

    对于样本 xx,其分类为 yyP(yx)P(y|x)条件概率,意思是在样本 xx 的条件下,正确分类为 yy 的概率。那我们当然希望P(yx)P(y|x)越大越好啊,因为这样模型预测越准,求得的模型参数就越符合我们样本的分布

    因为我们习惯损失函数求最小,这就是为什么要加个负号“-”P(yx)P(y|x) 越大,L(y,P(yx))L(y,P(y|x)) 越小。

    那为什么要使用对数呢?这和最大(极大)似然估计有关,对数损失是用于最大似然估计的最大似然估计,通俗理解来说,就是利用已知的样本结果信息,反推最具有可能(最大概率)导致这些样本结果出现的模型参数值

    我们假定一组参数在一堆数据(样本结果)下的似然值P(θx1,x2,...,xn)=P(x1θ)P(x2θ)...P(xnθ)P(θ|x_1,x_2,...,x_n)=P(x_1|θ)*P(x_2|θ)*...*P(x_n|θ),可以看出来,似然值等于每一条数据在这组参数下的条件概率之积。求概率是乘性,而求损失是加性,所以才需要借助 log(对数)来转积为和,另一方面也是为了简化运算。

    对数损失在逻辑回归多分类任务上广泛使用。交叉熵损失函数的标准型就是对数损失函数,本质没有区别

  • 交叉熵损失函数(Cross-Entropy Loss):用于多分类问题,衡量预测结果与真实结果之间的差异。常用于神经网络中的分类任务。具体公式如下:

    L(y,y^)=[ylny^+(1y)ln(1y^)]L(y,ŷ)=-[ylnŷ+(1-y)ln(1-ŷ)] \\

    本质上是一种对数似然函数,可用于二分类和多分类任务中。

    二分类问题中的 loss 函数(配合 sigmoid):

    L(y,y^)=[ylny^+(1y)ln(1y^)] L(y,ŷ)=-[ylnŷ+(1-y)ln(1-ŷ)] \\

    多分类问题中的loss函数(配合 softmax):

    L(y,y^)=ylny^L(y,ŷ)=-ylnŷ \\
  • 指数损失函数:指数损失函数在分类任务中常用于概率模型,它衡量了模型预测的概率与真实标签之间的差异。与交叉熵损失函数不同,指数损失函数对于误分类的样本有更大的惩罚,因此对错误分类的样本更加敏感

    L(y,y^)=exp(yy^)L(y,ŷ)=exp(-y \cdot ŷ) \\

    AdaBoost算法就是使用的指数损失函数。

    那么为什么AdaBoost算法使用指数损失函数,而不使用其他损失函数呢?

    这是因为,当前向分步算法的损失函数是指数损失函数时,其学习的具体操作等价于AdaBoost算法的学习过程。证明过程比较复杂,感兴趣的同学可以查查资料。

  • 合页损失函数(Hinge Loss):常用于支持向量机(SVM)等算法中,用于二分类问题。它基于间隔的概念,鼓励模型将正确类别的预测值与错误类别的预测值之间的间隔最大化。具体公式如下:

    L(y,y^)=max(0,1yy^)L(y,ŷ)=max(0, \quad 1-y \cdot ŷ) \\

    SVM就是使用的合页损失,还加上了正则项。公式意义是,当样本被正确分类且函数间隔大于 1 时,合页损失是 0,否则损失是 1yy^1-y \cdot ŷ

注:以上损失函数都是标准型,针对单个数据。针对所有数据还应该加和求平均

3.3 用于分割任务的损失函数

分割任务其实就是像素级的分类,所以也可以采用交叉熵损失函数,当然分割任务也有其他损失函数。

  • Jaccard coefficient(Jaccard系数):就是 IOU(Intersection over Union),交集占并集的大小。

    IOU=Jaccard=ABAB=ABA+BABIOU=Jaccard =\frac{|A\cap B|} {|A\cup B|}=\frac{|A\cap B|} {|A|+|B|-|A\cap B|} \\

    公式其实很简单,就是交集占并集的大小。

    img

    那么我们的 IOUloss=1JaccardIOUloss = 1-Jaccard

  • Dice coefficient(Dice系数):dice coefficient 源于二分类,本质上是衡量两个样本( AABB )的重叠部分。

    Dice=2ABA+BDice=\frac{2 \cdot |A\cap B|} {|A|+|B|} \\
    img

    左边代表 Jaccard,右边代表 Dice。

    那么我们的 Diceloss=1DiceDiceloss = 1-Dice

  • Tversky Loss

    TverskyLoss(p,g)=ABαAB+βBA+AB=TPTP+αFP+βFNTversky Loss(p, g)=\frac{|A\cap B|} {\alpha|A-B|+\beta|B-A|+|A\cap B|} \\ =\frac{TP}{TP + \alpha \cdot FP + \beta \cdot FN} \\

    其实就是增加权重,控制 RecallRecallPrecisionPrecision。其中,p 表示模型的预测结果,g 表示真实标签,TP 表示预测为正样本且真实为正样本的数量,FP 表示预测为正样本但真实为负样本的数量,FN 表示预测为负样本但真实为正样本的数量。α 和 β 是用于调节 FP 和 FN 的权重系数,可以根据任务需求进行调节。

    Tversky Loss主要通过在分子中引入 FP 和 FN 的权重调节系数来解决类别不平衡问题,从而平衡正负样本的重要性,同时通过 Tversky 指数的形式,可以更加关注边界不清晰的区域,提高模型对边界像素的预测能力

3.4 用于检测的损失函数

检测任务就是检测图片中的目标物体并用线框表示出来。

  • Smooth L1 Loss :Smooth L1 Loss 结合了 L1(L1(x)=xL_1(x)=|x|) 和 L2(L2(x)=x2L_2(x)=x^2) 两种损失函数。公式如下:

    smoothL1(x)={0.5x2,ifx<1x0.5,otherwisesmooth_{L_1}(x)=\begin{cases}0.5x^2,\quad if |x|<1\\ |x|-0.5, \quad otherwise \\ \end{cases} \\

    其中 xx 为预测框与 groud truth 之间 elementwise 的差异。

    在 Faster R-CNN 中,使用的是 smooth L1 loss。smooth L1 loss 可以理解为,当 |x|<1 时,为 L2 损失(即假设样本服从标准高斯分布),当 |x|>1 时,为 L1 损失(即假设样本服从拉普拉斯分布),这样的好处在于训练时 |x|>1 时快速下降,|x|<1 时精细调整

  • Focal loss

    FL={α(1p)γlog(p),ify=1 (1α)pγlog(1p),ify=0FL=\begin{cases}- \alpha(1-p)^\gamma log(p),\quad if \quad y=1 \\ \ -(1-\alpha )p^\gamma log(1-p),\quad if \quad y=0 \\ \end{cases} \\

    实验表明 γ\gamma 取 2,α\alpha 取 0.25 的时候效果最佳。

    Focal loss 针对单阶段目标检测方法中样本极端不平衡的问题提出的。思路很清晰,大量的样本其实贡献的 loss 很有限(大部分都是易学习的负样本),导致少量的正样本的 loss 难以贡献。故增加这部分少量样本的 loss 的权重(即 y=1),惩罚大量负样本的 loss 的权重。Focal Loss主要包含两个部分:调节因子 (α) 和聚焦因子 (γ)。调节因子用于平衡类别权重,使得模型更关注少数类别。聚焦因子用于调节难易样本的权重,γ 越大则对于难以分类的样本权重越大

    在 RetinaNet 网络中使用该损失函数。



面试题

1. 说一下你了解的损失函数?各自的运用场景⭐⭐⭐⭐⭐

参考回答

  1. 用于回归的损失函数

    • 绝对值损失函数

    • 平方损失函数(squared loss):针对一个数据求平方损失,而针对 n 个数据求平方损失后再加和求平均 1Nn(Yf(x))2\frac{1}{N}\sum_{n}(Y-f(x))^2,即均方误差MSE,mean squared error)。常用于线性回归。

  2. 用于分类的损失函数

    • 0-1损失函数(zero-one loss):在感知机中,使用的该损失函数。条件比较严苛,同时无法求导,其他模型中很少使用。

    • 对数损失函数(log loss):用于最大似然估计,等价于交叉熵损失函数

    • 指数损失函数(exponential loss):在 adaboost 中使用的该损失函数

    • 合页损失函数(hinge loss):在 SVM 中使用的该损失函数。公式意义是,当样本被正确分类且函数间隔大于 1 时,合页损失是 0,否则损失是 1Yf(x)1-Y \cdot f(x)

    • 交叉熵损失函数(cross-entropy loss):用于分类任务,本质和对数 loss 没有区别

  3. 用于分割的损失函数

    • IOU loss:就是交集和并集的比值,常用于分割任务、回归任务。

    • Dice loss:dice coefficient 源于二分类,本质上是衡量两个样本(AABB)的重叠部分。那么我们的 Diceloss=1DiceDiceloss = 1-Dice

    • Tversky Loss :引入 α\alphaβ\beta 来控制 RecallRecallPrecisionPrecision。更加关注边界不清晰的区域,提高模型对边界像素的预测能力。

  4. 用于检测的损失函数

    • Smooth L1 Loss :融合绝对值损失函数和平方损失函数,faster RCNN 用的该损失函数。smooth L1 loss 可以理解为,当 |x|<1 时,为 L2 损失(即假设样本服从标准高斯分布),当 |x|>1 时,为 L1 损失(即假设样本服从拉普拉斯分布),这样的好处在于训练时 |x|>1 时快速下降,|x|<1 时精细调整

    • Focal loss :用于单阶段目标检测方法中样本极端不平衡的情况。在 RetinaNet 网络中使用该损失函数。增加少量样本的 loss 的权重(即 y=1),惩罚大量负样本的 loss 的权重。

2. 说说你平时都用过什么损失函数,各自什么特点?⭐⭐⭐⭐⭐

与第一题回答类似。

3. 交叉熵函数与最大似然函数的联系和区别?⭐⭐⭐⭐⭐

参考回答

区别:交叉熵函数用来描述模型预测值真实值差距大小,越大代表越不相近;似然函数的本质是衡量在某个参数下,整体的估计真实的情况一样的概率,越大代表越相近。

联系:交叉熵函数可以由最大似然函数伯努利分布的条件下推导出来,或者说最小化交叉熵函数的本质就是对数似然函数的最大化


答案解析

  • 最大似然函数(Maximum Likelihood Function): 最大似然函数是用于估计模型参数的方法。在给定观测数据的情况下,最大似然函数旨在找到能够最大化观测数据出现的概率的模型参数值。它是一个优化问题,通过调整模型参数来使观测数据的概率最大化。

  • 交叉熵函数(Cross-Entropy Function): 交叉熵函数是衡量两个概率分布之间差异的度量。在机器学习中,交叉熵函数通常用于衡量预测结果和实际标签之间的差异。对于二分类问题,交叉熵函数可以定义为预测标签与实际标签之间的差异。

这里我们来推导一下:

设一个随机变量 XX 满足伯努利分布

P(X=1)=p,P(X=0)=1p(.)P(X=1)=p,P(X=0)=1-p \\ \tag{.}

XX概率密度函数为:

P(X)=pX(1p)1X(.)P(X)=p^X(1-p)^{1-X} \\ \tag{.}

我们通过一组数据 DD,可以统计得到 XX1X1-X 的值,但是 pp 的概率未知,接下来我们就用极大似然估计的方法来估计这个 pp 值。

对于数据集合 DD,其对数似然函数为:

img

可以看到上式和交叉熵函数的形式几乎相同,极大似然估计就是要求这个式子的最大值。而由于上面函数的值总是小于 0,一般像神经网络等对于损失函数会用最小化的方法进行优化,所以一般会在前面加一个负号,得到交叉熵函数(或交叉熵损失函数):

Loss=i[Dilogp+(1Di)ln(1p)](.)Loss=- \sum_{i}[D_ilogp+(1-D_i)ln(1-p)] \\ \tag{.}

这里我们就可以看出交叉熵函数极大似然估计的联系,最小化交叉熵函数的本质就是对数似然函数的最大化。

现在我们可以用求导得到极大值点的方法来求其极大似然估计,首先将对数似然函数对 p 进行求导,并令导数为 0,得到

i[Di1p+(1Di)11p]=0(.)\sum_{i}[D_i \frac{1}{p}+(1-D_i)\frac{1}{1-p}] =0 \\ \tag{.}

消去分母,得:

p=1NiDi(.)p=\frac{1}{N}\sum_{i}D_i \\ \tag{.}

这就是伯努利分布下最大似然估计求出的概率 pp

4. 在用 sigmoid 作为激活函数的时候,为什么要用交叉熵损失函数,而不用均方误差损失函数?⭐⭐⭐⭐⭐

参考回答

  1. 更好的收敛性:因为交叉熵损失函数可以完美解决平方损失函数权重更新过慢的问题,具有“误差大的时候,权重更新快;误差小的时候,权重更新慢”的良好性质(本质是损失函数中有对数的存在)。

  2. 凸优化性sigmoid作为激活函数的时候,如果采用均方误差损失函数,那么这是一个非凸优化问题,不宜求解。而采用交叉熵损失函数依然是一个凸优化问题,更容易优化求解。

  3. 梯度消失问题:在使用 sigmoid 作为激活函数时,它的导数在输入接近饱和区域(接近 0 或 1)时会趋近于 0。这导致在反向传播过程中,通过链式法则计算的梯度会变得非常小,进而导致梯度消失问题。均方误差损失函数对于小的梯度不敏感,因此在这种情况下,梯度可能会过小,使得网络训练变得困难。相比之下,交叉熵损失函数在输入接近边界值时的梯度变化较大,更适合用于 sigmoid 激活函数。


答案解析

我们来分析一下参数更新的过程:

对于均方误差损失函数,常常定义为:

C=12Nx(ay)2(.)C=\frac{1}{2N}\sum_{x}(a-y)^2 \\ \tag{.}

其中 yy 是我们期望的输出,aa 是神经元实际输出:

a=σ(x),z=wx+b(.)a=\sigma(x),z=wx+b \\ \tag{.}

在训练神经网络的时候我们使用梯度下降的方法来更新 wwbb,求导:

Cw=(ay)σ(z)xCb=(ay)σ(z)(.)\frac{\partial C}{\partial w}=(a-y)\sigma^{'}(z)x \\ \frac{\partial C}{\partial b}=(a-y)\sigma^{'}(z) \tag{.}

然后更新参数 wwbb

w=wηCw=wη(ay)σ(z)xb=bηCb=bη(ay)σ(z)(.)w = w^*-\eta\frac{\partial C}{\partial w}=w^*-\eta(a-y)\sigma^{'}(z)x \\ b = b^*-\eta\frac{\partial C}{\partial b}=b^*-\eta(a-y)\sigma^{'}(z) \tag{.}

η\eta 代表学习率。可以看出,参数更新和 σ(z)\sigma^{'}(z) 有关。如果这里的 σ(z)\sigma(z) 使用的是 sigmoid 函数,而我们之前讲激活函数就提到,sigmoid 函数两端梯度很小,导致参数更新缓慢。

同样的对于交叉熵损失函数,计算一下参数更新的梯度公式就会发现原因。交叉熵损失函数一般定义为:

C=1Nx[ylna+(1y)ln(1a)](.)C=-\frac{1}{N}\sum_{x}[ylna+(1-y)ln(1-a)] \\ \tag{.}

同样可以看看它的导数,a=σ(x)a=\sigma(x)

img

根据链式求导法则:

img

所以有:

img

所以参数更新公式为:

w=wηCw=wη(ay)xb=bηCb=bη(ay)(.)w = w^*-\eta\frac{\partial C}{\partial w}=w^*-\eta(a-y)x \\ b = b^*-\eta\frac{\partial C}{\partial b}=b^*-\eta(a-y) \tag{.}

可以看到参数更新公式中没有 σ(z)\sigma^{'}(z) 这一项,权重的更新受 (ay)(a-y) 影响,受到误差的影响,所以当误差大的时候,权重更新快;当误差小的时候,权重更新慢。这是一个很好的性质。

这就是为什么当使用 sigmoid 作为激活函数的时候,常用交叉熵损失函数而不用均方误差损失函数

5. 关于交叉熵损失函数(Cross-entropy)和平方损失(MSE)的区别?⭐⭐⭐⭐⭐

1.概念不一样

均方差损失函数(MSE)是求 n 个样本的 n 个输出与期望输出的差的平方的平均值。

L(Y,f(x))=1Nn(Yf(x))2(.)L(Y,f(x))=\frac{1}{N}\sum_{n}(Y-f(x))^2 \\ \tag{.}

交叉熵损失函数(cross-entropy)描述模型预测值和真实值的差距大小,越大代表越不相近。

C=1Nx[ylna+(1y)ln(1a)](.)C=-\frac{1}{N}\sum_{x}[ylna+(1-y)ln(1-a)] \\ \tag{.}

2.参数更新速度不一样

均方差损失函数受 sigmoid 函数影响,导数更新缓慢。

交叉熵损失函数参数更新只和误差有关,当误差大的时候,权重更新快;当误差小的时候,权重更新慢。这是一个很好的性质。

3.sigmoid 作为激活函数的时候,如果采用均方误差损失函数,那么这是一个非凸优化问题,不宜求解。而采用交叉熵损失函数依然是一个凸优化问题,更容易优化求解。

4.使用场景不一样

MSE 更适合回归问题交叉熵损失函数更适合分类问题

6. 推导交叉熵损失函数?⭐⭐⭐⭐⭐

参考回答

我们以偏置 bb 的梯度计算为例,推导出交叉熵代价函数。

我们假设损失函数为 CC,那么损失函数对 bb 求偏导:

Cb=Caazzb=Caσ(z)(wx+b)b=Caσ(z)=Caa(1a)(.)\frac{\partial C}{\partial b}=\frac{\partial C}{\partial a}\cdot \frac{\partial a}{\partial z}\cdot \frac{\partial z}{\partial b} \\ =\frac{\partial C}{\partial a}\cdot \sigma^{'}(z)\cdot \frac{\partial (wx+b)}{\partial b} \\ =\frac{\partial C}{\partial a}\cdot \sigma^{'}(z) =\frac{\partial C}{\partial a}\cdot a(1-a) \tag{.}

在上面,由二次代价函数推导出来的 bb 的梯度公式为:

Cb=(ay)σ(z)(.)\frac{\partial C}{\partial b}=(a-y)\sigma^{'}(z) \\ \tag{.}

为了消掉该公式中的 σ(z)\sigma^{'}(z),我们想找到一个代价函数使得:

Cb=(ay)(.)\frac{\partial C}{\partial b}=(a-y) \\ \tag{.}

即:

Caa(1a)=(ay)(.)\frac{\partial C}{\partial a}\cdot a(1-a)=(a-y) \\ \tag{.}

对两侧求积分,可得:

C=[ylna+(1y)ln(1a)]+constant(.)C=-[ylna+(1-y)ln(1-a)]+constant \\ \tag{.}

而这就是前面介绍的交叉熵代价函数。

答案解析

注:sigmoid 函数求导为:σ(z)=σ(z)(1σ(z))\sigma^{'}(z)=\sigma(z)(1-\sigma(z))

上面是一种方式。还有一种方式是通过最大似然估计的方式求得交叉熵公式,这里不再赘述。

7. 为什么交叉熵损失函数有 log 项?⭐⭐⭐⭐⭐

参考回答

这里有两种回答方式。

第一种:因为是公式推导出来的,比如第六题的推导,推导出来的有 log 项。

第二种:通过最大似然估计的方式求得交叉熵公式,这个时候引入 log 项。这是因为似然函数(概率)是乘性的,而 loss 函数是加性的,所以需要引入 log 项“转积为和”。而且也是为了简化运算

8. 说说 adaboost 损失函数⭐⭐⭐⭐

参考回答

采用的指数损失函数(exponential loss)

L(Y,f(x))=exp(Yf(x))(.)L(Y,f(x))=exp(-Y \cdot f(x)) \\ \tag{.}

AdaBoost 算法就是使用的指数损失函数。

那么为什么 AdaBoost 算法使用指数损失函数,而不使用其他损失函数呢?

这是因为,当前向分步算法的损失函数是指数损失函数时,其学习的具体操作等价于 AdaBoost 算法的学习过程。证明过程比较复杂,感兴趣的同学可以查查资料。

9. 说说 SVM 损失函数⭐⭐⭐⭐

参考回答

合页损失函数(hinge loss):常用于支持向量机(SVM)等算法中,用于二分类问题。它基于间隔的概念,鼓励模型将正确类别的预测值与错误类别的预测值之间的间隔最大化

L(Y,f(x))=max(0,1Yf(x))(.)L(Y,f(x))=max(0, \quad 1-Y \cdot f(x)) \\ \tag{.}

SVM 就是使用的合页损失,还加上了正则项。公式意义是,当样本被正确分类且函数间隔大于 1 时,合页损失是 0,否则损失是 1Yf(x)1-Y \cdot f(x)

10. 简单的深度神经网络(DNN)的损失函数是什么?⭐⭐⭐⭐

参考回答

深度神经网络(DNN)涉及到梯度消失的问题,如果使用均方误差作为损失函数配合 sigmoid 激活函数,那么参数更新缓慢。这个时候应该考虑使用交叉熵作为损失函数,可以避免参数更新缓慢的问题。

11. 说说 KL 散度⭐⭐⭐⭐

参考回答

相对熵(relative entropy),又被称为 Kullback-Leibler 散度(Kullback-Leibler divergence)或信息散度(information divergence),是两个概率分布(probability distribution)间差异的非对称性度量 。在信息理论中,相对熵等价于两个概率分布的信息熵(Shannon entropy)的差值

P(x)P(x)Q(x)Q(x) 是随机变量 XX 上的两个概率分布,则在离散和连续随机变量的情形下,相对熵的定义分别为:

KL(PQ)=P(x)logP(x)Q(x)KL(PQ)=P(x)logP(x)Q(x)dx(.)KL(P||Q)=\sum{P(x)log \frac{P(x)}{Q(x)}} \\ KL(P||Q)=\int{P(x)log \frac{P(x)}{Q(x)}dx} \\ \tag{.}

Q(x)Q(x)理论概率分布P(x)P(x) 为模型预测概率分布,而 KL 就是度量这两个分布的差异性,当然差异越小越好,所以 KL 也可以用作损失函数。

类似的还有一个JS散度,基于KL散度的变体,解决了KL散度非对称的问题GAN网络用的JS散度作为损失函数。

12. 说说 Yolo 的损失函数⭐⭐⭐⭐⭐

参考回答

Yolo 的损失函数由四部分组成:

img
  1. 对预测的中心坐标做损失
img
  1. 对预测边界框的宽高做损失
img
  1. 对预测的类别做损失
img
  1. 对预测的置信度做损失
img

我们发现每一项 loss 的计算都是 L2 loss,即使是分类问题也是。所以说 yolo 是把分类问题转为了回归问题。

Yolo v2 的损失函数延续了 yolo v1,而 yolo v3 的损失函数,其中分类部分替换成了交叉熵损失函数

yolo v4 的损失函数相比于 yolo v3 又有两个改进点:1、YOLOv4 采用了 GIoU(Generalized Intersection over Union)损失作为目标定位损失的度量指标。GIoU 不仅考虑了边界框的重叠度,还考虑了边界框的位置和大小。相比于 YOLOv3 中使用的IoU(Intersection over Union)损失,GIoU 损失能够更准确地度量边界框之间的差异,提高了目标定位的准确性。2、YOLOv4 对 Focal 损失进行了改进,使其更适用于目标检测任务。Focal 损失可以在处理大量背景框和少量正样本框时,有效地解决样本不平衡问题。

yolov5 的损失函数相比于 yolov4 又增加了 CIoU 损失:YOLOv5 采用了 GIoU(Generalized Intersection over Union)损失和 CIoU(Complete Intersection over Union)损失来替代 YOLOv4 中的 GIoU 损失。CIoU 损失进一步改进了 GIoU 损失,考虑了边界框的长宽比例差异,能够更准确地度量边界框之间的差异,提高了目标定位的准确性。

yolo 后面的系列对损失函数做了多方面的改进,IoU 演进到 GIoU、DIoU、CIoU、SIoU;Focal 损失演进到 Quality Focal Loss(QFL)、VariFocal Loss(VFL)、Poly Loss。不再赘述。

13. 交叉熵的设计思想是什么⭐⭐⭐⭐⭐

参考回答

  • 信息论的概念: 交叉熵是基于信息论中的熵和相对熵(KL散度)的概念。熵用于度量随机事件的不确定性,而相对熵用于衡量两个概率分布之间的差异。在分类任务中,我们希望通过损失函数来最小化预测结果与真实标签之间的差异,从而减少不确定性并增加对正确类别的置信度。

  • 最大似然估计: 交叉熵损失函数可以解释为最大似然估计的一种形式。最大似然估计是一种常用的参数估计方法,通过寻找能最大化给定数据样本出现概率的参数值。在分类任务中,我们可以将模型的输出看作是对样本属于各个类别的概率分布的估计,而真实标签则表示样本的真实分布。通过最大化样本真实分布的似然概率,可以得到与真实标签最匹配的模型参数,从而提高分类准确性。

  • 反映预测概率与真实标签之间的差异: 交叉熵损失函数的计算方式可以将模型的预测概率与真实标签之间的差异量化为一个标量值。具体而言,交叉熵损失函数的值越小,表示模型的预测结果与真实标签越接近,分类准确性越高。通过最小化交叉熵损失函数,模型可以进行梯度下降优化,调整参数以使预测概率更接近真实标签。

14. 说说 iou 计算⭐⭐⭐⭐⭐

参考回答

IOU(Intersection over Union),交集占并集的大小。

IOU=Jaccard=ABAB=ABA+BAB(.)IOU=Jaccard =\frac{|A\cap B|} {|A\cup B|}=\frac{|A\cap B|} {|A|+|B|-|A\cap B|} \\ \tag{.}

公式其实很简单,就是交集占并集的大小。


答案解析

def calculate_iou(box1, box2):
    """
    计算两个矩形框的IOU(Intersection over Union)
    
    参数:
    - box1: 第一个矩形框的坐标,格式为 (x_min, y_min, x_max, y_max)
    - box2: 第二个矩形框的坐标,格式为 (x_min, y_min, x_max, y_max)
    
    返回值:
    - iou: 两个矩形框的IOU值
    """
    x1_min, y1_min, x1_max, y1_max = box1
    x2_min, y2_min, x2_max, y2_max = box2
    
    # 计算矩形框的面积
    area1 = (x1_max - x1_min) * (y1_max - y1_min)
    area2 = (x2_max - x2_min) * (y2_max - y2_min)
    
    # 计算两个矩形框的交集
    intersection_x_min = max(x1_min, x2_min)
    intersection_y_min = max(y1_min, y2_min)
    intersection_x_max = min(x1_max, x2_max)
    intersection_y_max = min(y1_max, y2_max)
    intersection_area = max(0, intersection_x_max - intersection_x_min) * max(0, intersection_y_max - intersection_y_min)
    
    # 计算IOU值
    iou = intersection_area / (area1 + area2 - intersection_area)
    
    return iou

我们再拓展一下 GIoU、DIoU、CIoU、SIoU。

IoU 对于有两种场景处理不好:

1.当预测框与真实框都没有交集的时候,计算出来的 IoU 都为 0,损失都为 1,但是,从图中可以看出,预测框 1 与真实框更加接近,损失应该更小才对:

img

2.当预测框和真实框的交并比相同,但是预测框所在位置不同,因为计算出来的损失一样,所以这样并不能判断哪种预测框更加准确

img

为了解决 IoU 的第一个问题,即当预测框与真实框都没有交集的时候,计算出来的 IoU 都为 0,损失都为 1,引入了一个最小闭包区的概念,即能将预测框和真实框包裹住的最小矩形框

img

GIoU的计算公式为:

img

其中,AcA_c 为最小闭包区,UU 为预测框和真实框的并集。GIoU 的计算方式是在计算 IoU 时,同时考虑了边界框的交集和并集的面积,并通过一个惩罚项来衡量边界框的位置和大小的差异。

GIoU同样也存在一些问题,如下图:

img

这两种情况的 IoU 和 GIoU 都是一样的,但是从我们的自觉认为第一种应该更好,loss 应该更小些,为了解决这一问题,又提出了 DIoU:

img

其中,bbbgtb^{gt} 分别代表了预测框和真实框的中心点,且 ρ\rho 代表的是计算两个中心点间的欧式距离。cc 代表的是能够同时包含预测框和真实框的最小闭包区域的对角线距离。

img

DIoU的缺点:当真实框和预测框的中心点重合时,但是长宽比不同,交并比一样,如下图,计算出来的DIoU、GIoU、IoU都一样:

img

CIoU 在 DIoU 的基础上加了对长宽比的考虑,其惩罚项如下面公式:

img

其中 α\alpha 是权重函数,而 vv 用来度量长宽比的相似性,定义为:

img

当真实框和预测框的长宽比越接近,vv 越小。vv 不变时,IoU越大, α\alpha 越大,损失越大,说明高 IoU 时,更加关注长宽比,低 IoU 时,更关注 IoU。

img

完整的 CIoU 损失函数定义:

img

总结一下:

  • GIoU(Generalized Intersection over Union): GIoU是一种改进的IoU(Intersection over Union)指标,用于度量两个边界框之间的重叠度。GIoU考虑了边界框的位置和大小之间的差异,并通过一个惩罚项来衡量边界框的位置和大小的差异。GIoU可以提供更准确的目标匹配度度量。

  • DIoU(Distance Intersection over Union): DIoU在GIoU的基础上进行了进一步改进,引入了边界框之间的距离信息。DIoU在计算边界框的重叠度时,考虑了边界框中心点之间的距离,并通过一个距离项来衡量边界框的位置差异。DIoU能够更全面地描述边界框之间的匹配度。

  • CIoU(Complete Intersection over Union): CIoU是在DIoU的基础上进行了改进的指标,进一步考虑了边界框的长宽比例差异。CIoU能够更准确地衡量目标的定位准确性,综合考虑了边界框的位置、大小和长宽比例的差异。

  • SIoU(Smoothed Intersection over Union): SIoU是一种平滑的IoU指标,用于解决IoU在计算时可能出现的分母为零的问题。SIoU通过引入平滑项来处理没有交集的情况,使得在没有交集的情况下仍能够计算得到非零的匹配度值。

15. 手写 miou 计算⭐⭐⭐⭐⭐

参考回答

mIOU 一般都是基于类进行计算的,将每一类的 IOU 计算之后累加,再进行平均,得到的就是 mIOU。

16. 交叉熵为什么可以做损失函数⭐⭐⭐⭐⭐

参考回答

在机器学习中,我们希望在训练数据上模型学到的分布 𝑃(𝑚𝑜𝑑𝑒𝑙) 和真实数据的分布 𝑃(𝑟𝑒𝑎𝑙) 越接近越好,所以我们可以使其相对熵最小。但是我们没有真实数据的分布,所以只能希望模型学到的分布 𝑃(𝑚𝑜𝑑𝑒𝑙) 和训练数据的分布 𝑃(𝑡𝑟𝑎𝑖𝑛) 尽量相同。假设训练数据是从总体中独立同分布采样的,那么我们可以通过最小化训练数据的经验误差来降低模型的泛化误差。即:

  1. 希望学到的模型的分布和真实分布一致,𝑃(𝑚𝑜𝑑𝑒𝑙)≃𝑃(𝑟𝑒𝑎𝑙)

  2. 但是真实分布不可知,假设训练数据是从真实数据中独立同分布采样的,𝑃(𝑡𝑟𝑎𝑖𝑛)≃𝑃(𝑟𝑒𝑎𝑙)

  3. 因此,我们希望学到的模型分布至少和训练数据的分布一致,𝑃(𝑚𝑜𝑑𝑒𝑙)≃𝑃(𝑡𝑟𝑎𝑖𝑛)

最小化训练数据上的分布 𝑃(𝑡𝑟𝑎𝑖𝑛) 与最小化模型分布 𝑃(𝑚𝑜𝑑𝑒𝑙) 的差异等价于最小化相对熵,即 DKL(𝑃(𝑡𝑟𝑎𝑖𝑛)𝑃(𝑚𝑜𝑑𝑒𝑙))D_{KL}(𝑃(𝑡𝑟𝑎𝑖𝑛)||𝑃(𝑚𝑜𝑑𝑒𝑙))。此时, 𝑃(𝑡𝑟𝑎𝑖𝑛) 就是 DKL(𝑝𝑞)D_{KL}(𝑝||𝑞) 中的 𝑝,即真实分布,𝑃(𝑚𝑜𝑑𝑒𝑙) 就是 𝑞。又因为训练数据的分布 𝑝 是给定的,所以求 DKL(𝑝𝑞)=Ex p[logp(x)q(x)]=Ex p[logp(x)logq(x)]D_{KL}(𝑝||𝑞)=E_{x~p}[log\frac{p(x)}{q(x)}]=E_{x~p}[logp(x)-logq(x)] 等价于求交叉熵 𝐻(𝑝,𝑞)=Ex plogq(x)=H(p)+DKL(𝑝𝑞)𝐻(𝑝,𝑞)=-E_{x~p}logq(x)=H(p)+D_{KL}(𝑝||𝑞)而为了计算方便,用交叉熵取代相对熵,只需要计算Ex plogq(x)-E_{x~p}logq(x)

得证,交叉熵可以用来计算学习模型分布与训练分布之间的差异。因此交叉熵可以用作损失函数。

17. 什么是损失函数,作用是什么?⭐⭐⭐⭐⭐

损失函数是在机器学习和优化问题中使用的一种函数,用于度量模型的预测输出与真实标签之间的差异或误差。它是模型训练过程中的核心组成部分。

作用:

  1. 衡量模型的预测误差:损失函数可以量化模型在给定样本上的预测结果与真实标签之间的差异或误差。它通过计算预测值与真实值之间的差距,提供了一个衡量模型准确性的指标。
  2. 指导模型的优化:通过最小化损失函数,可以使模型调整其内部参数或权重,以减小预测值与真实值之间的差距。

18. 什么时候使用绝对值损失函数而不是均方误差损失函数?⭐⭐⭐⭐⭐

绝对值损失函数适用于回归任务,它计算预测值与真实值之间的绝对差。当存在异常值或离群点时,绝对值损失函数比均方误差损失函数更鲁棒,因为它不受异常值的影响。

19. 为什么在分类任务中使用交叉熵损失函数而不是均方误差损失函数?⭐⭐⭐⭐⭐

  1. 处理分类问题的概率分布:均方误差损失函数假设误差服从高斯分布,对异常值敏感。在分类任务中,我们更关心类别的概率分布和置信度,而不仅仅是预测结果的数值。交叉熵损失函数能够更好地处理分类问题中的概率分布,对于分类任务更合适。

  2. 避免均方误差损失函数的不适用性:均方误差损失函数(MSE)适用于回归问题,它计算预测值与真实值之间的平方差。但在分类任务中,类别之间的标签通常是以独热编码的形式表示,不是连续的数值。使用MSE损失函数会导致模型无法正确地学习到类别之间的差异,因为MSE假设连续的误差分布。

  3. 解决梯度消失问题:在使用均方误差损失函数进行反向传播时,对于预测结果接近于0或1的情况,梯度可能会变得非常小,导致梯度消失问题。交叉熵损失函数通过对预测概率进行对数变换,使得在接近0或1的情况下,仍能够保持较大的梯度,更好地支持反向传播过程。

20. 损失函数的分类⭐⭐⭐⭐⭐

损失函数可以分为经验风险损失函数(empirical risk loss function)和结构风险损失函数(structural risk loss function)。

  • 经验风险损失函数:经验风险是指模型在训练数据上的平均损失(预测结果实际结果的差值)。经验风险损失函数是根据训练数据上的损失计算的,它衡量了模型在训练集上的性能。

  • 结构风险损失函数:结构风险是指模型在训练数据上的经验风险和模型复杂度之间的权衡。常见的结构风险损失函数包括正则化项(如 L1 正则化和 L2 正则化)与经验风险损失函数的组合

简单来说:损失函数分为经验风险损失函数结构风险损失函数。经验风险损失函数指预测结果实际结果的差值,结构风险损失函数是指经验风险损失函数加上正则项

21. 目标检测和分割的 loss 有什么区别⭐⭐⭐⭐⭐

目标检测和分割是计算机视觉领域中常见的任务,它们的损失函数在目标定位和像素级预测上有所不同。

在目标检测中,常用的损失函数包括:

  • 边界框回归损失:用于预测目标边界框的位置和尺寸,常用的损失函数包括平均平方误差(MSE)损失或平滑L1损失。
  • 分类损失:用于预测目标的类别,常用的损失函数包括交叉熵损失(Cross-Entropy)或者逻辑损失(Logistic Loss)。
  • 目标置信度损失:用于判断目标是否存在,通常使用二分类损失函数,如交叉熵损失或者逻辑损失。

在分割任务中,常用的损失函数包括:

  • 像素级分类损失:用于对每个像素进行分类,常用的损失函数是交叉熵损失或者softmax损失,或者 Jaccard 和 Dice。
  • 像素级回归损失:用于预测每个像素的特定属性,如目标的边界框或者关键点位置,常用的损失函数包括平均平方误差(MSE)损失或平滑L1损失。

总体而言,目标检测的损失函数更侧重于目标的定位和分类,而分割的损失函数则更注重像素级的分类和预测。