2. 深度学习笔记--损失函数

在机器学习中,损失函数是代价函数的一部分,而代价函数则是目标函数的一种类型。

  • Loss function,即损失函数:用于定义单个训练样本与真实值之间的误差;

  • Cost function,即代价函数:用于定义单个批次/整个训练集样本与真实值之间的误差;

  • Objective function,即目标函数:泛指任意可以被优化的函数。

损失函数是用于衡量模型所作出的预测离真实值(Ground Truth)之间的偏离程度。 通常,我们都会最小化目标函数,最常用的算法便是“梯度下降法”(Gradient Descent)。俗话说,任何事情必然有它的两面性,因此,并没有一种万能的损失函数能够适用于所有的机器学习任务,所以在这里我们需要知道每一种损失函数的优点和局限性,才能更好的利用它们去解决实际的问题。损失函数大致可分为两种:回归损失(针对连续型变量)和分类损失(针对离散型变量)。

一、回归损失

在这里插入图片描述

1. L1Loss(MAE)

也称为Mean Absolute Error,即平均绝对误差(MAE),它衡量的是预测值与真实值之间距离的平均误差幅度,作用范围为0到正无穷。

  • 优点: 对离群点(Outliers)或者异常值更具有鲁棒性。
  • 缺点: 由图可知其在0点处的导数不连续,使得求解效率低下,导致收敛速度慢;而对于较小的损失值,其梯度也同其他区间损失值的梯度一样大,所以不利于网络的学习。

2. L2 Loss (MSE)

也称为Mean Squred Error,即均方差(MSE),它衡量的是预测值与真实1值之间距离的平方和,作用范围同为0到正无穷。

  • 优点: 对离群点(Outliers)或者异常值更具有鲁棒性。
  • 缺点: 由图可知其在0点处的导数不连续,使得求解效率低下,导致收敛速度慢;而对于较小的损失值,其梯度也同其他区间损失值的梯度一样大,所以不利于网络的学习。

对于L1范数和L2范数,如果异常值对于实际业务非常重要,我们可以使用MSE作为我们的损失函数;另一方面,如果异常值仅仅表示损坏的数据,那我们应该选择MAE作为损失函数。此外,考虑到收敛速度,在大多数的卷积神经网络中(CNN)中,我们通常会选择L2损失。但是,还存在这样一种情形,当你的业务数据中,存在95%的数据其真实值为1000,而剩下5%的数据其真实值为10时,如果你使用MAE去训练模型,则训练出来的模型会偏向于将所有输入数据预测成1000,因为MAE对离群点不敏感,趋向于取中值。而采用MSE去训练模型时,训练出来的模型会偏向于将大多数的输入数据预测成10,因为它对离群点异常敏感。因此,大多数情况这两种回归损失函数并不适用,能否有什么办法可以同时利用这两者的优点呢?

3. Smooth L1 Loss

即平滑的L1损失(SLL),出自Fast RCNN。SLL通过综合L1和L2损失的优点,在0点处附近采用了L2损失中的平方函数,解决了L1损失在0点处梯度不可导的问题,使其更加平滑易于收敛。此外,在|x|>1的区间上,它又采用了L1损失中的线性函数,使得梯度能够快速下降。
在这里插入图片描述
通过对这三个损失函数进行求导可以发现,L1损失的导数为常数,如果不及时调整学习率,那么当值过小时,会导致模型很难收敛到一个较高的精度,而是趋向于一个固定值附近波动。反过来,对于L2损失来说,由于在训练初期值较大时,其导数值也会相应较大,导致训练不稳定。最后,可以发现Smooth L1在训练初期输入数值较大时能够较为稳定在某一个数值,而在后期趋向于收敛时也能够加速梯度的回传,很好的解决了前面两者所存在的问题。
在这里插入图片描述

4. IoU Loss

即交并比损失,出自UnitBox,由旷视科技于ACM2016首次提出。常规的Lx损失中,都是基于目标边界中的4个坐标点信息之间分别进行回归损失计算的。因此,这些边框信息之间是相互独立的。然而,直观上来看,这些边框信息之间必然是存在某种相关性的。如下图(a)-(b)分别所示,绿色框代表Ground Truth,黑色框代表Prediction,可以看出,同一个Lx分数,预测框与真实框之间的拟合/重叠程度并不相同,显然重叠度越高的预测框是越合理的。IoU损失将候选框的四个边界信息作为一个整体进行回归,从而实现准确、高效的定位,具有很好的尺度不变性。为了解决IoU度量不可导的现象,引入了负Ln范数来间接计算IoU损失。
在这里插入图片描述

在这里插入图片描述

5. GIoU Loss

即泛化的IoU损失,全称为Generalized Intersection over Union,由斯坦福学者于CVPR2019年发表的这篇论文中首次提出。上面我们提到了IoU损失可以解决边界框坐标之间相互独立的问题,考虑这样一种情况,当预测框与真实框之间没有任何重叠时,两个边框的交集(分子)为0,此时IoU损失为0,因此IoU无法算出两者之间的距离(重叠度)。另一方面,由于IoU损失为零,意味着梯度无法有效地反向传播和更新,即出现梯度消失的现象,致使网络无法给出一个优化的方向。此外,如下图所示,IoU对不同方向的边框对齐也是一脸懵逼的,所计算出来的值都一样。
在这里插入图片描述
为了解决以上的问题,如下图公式所示,GIoU通过计算任意两个形状(这里以矩形框为例)A和B的一个最小闭合凸面C,然后再计算C中排除掉A和B后的面积占C原始面积的比值,最后再用原始的IoU减去这个比值得到泛化后的IoU值。
在这里插入图片描述
啥?
GIoU具有IoU所拥有的一切特性,如对称性,三角不等式等。GIoU ≤ IoU,特别地,0 ≤ IoU(A, B) ≤ -1, 而0 ≤ GIoU(A, B) ≤ -1;当两个边框的完全重叠时,此时GIoU = IoU = 1. 而当 |AUB| 与 最小闭合凸面C 的比值趋近为0时,即两个边框不相交的情况下,此时GIoU将渐渐收敛至 -1. 同样地,我们也可以通过一定的方式去计算出两个矩形框之间的GIoU损失,具体计算步骤也非常简单,详情参考原论文。

6. DIoU Loss

即距离IoU损失,全称为Distance-IoU loss,由天津大学数学学院研究人员于AAAI2020所发表的这篇论文[5]中首次提出。上面我们谈到GIoU通过引入最小闭合凸面来解决IoU无法对不重叠边框的优化问题。但是,其仍然存在两大局限性:边框回归还不够精确 & 收敛速度缓慢。考虑下图这种情况,当目标框完全包含预测框时,此时GIoU退化为IoU。显然,我们希望的预测是最右边这种情况。因此,作者通过计算两个边框之间的中心点归一化距离,从而更好的优化这种情况。
在这里插入图片描述
下图表示的是GIoU损失(第一行)和DIoU损失(第二行)的一个训练过程收敛情况。其中绿色框为目标边框,黑色框为锚框,蓝色框和红色框则分别表示使用GIoU损失和DIoU损失所得到的预测框。可以发现,GIoU损失一般会增加预测框的大小使其能和目标框重叠,而DIoU损失则直接使目标框和预测框之间的中心点归一化距离最小,即让预测框的中心快速的向目标中心收敛。

在这里插入图片描述
下图给出这三个IoU损失所对应的计算公式。对于DIoU来说,如图所示,其惩罚项由两部分构成:分子为目标框和预测框中心点之间的欧式距离;分母为两个框最小外接矩形框的两个对角线距离。因此, 直接优化两个点之间的距离会使得模型收敛得更快,同时又能够在两个边框不重叠的情况下给出一个优化的方向。

在这里插入图片描述

7. CIoU Loss

即完整IoU损失,全称为Complete IoU loss,与DIoU出自同一篇论文。上面我们提到GIoU存在两个缺陷,DIoU的提出解决了其实一个缺陷,即收敛速度的问题。而一个好的边框回归损失应该同时考虑三个重要的几何因素,即重叠面积(Overlap area)、中心点距离(Central point distance)和高宽比(Aspect ratio)。GIoU考虑到了重叠面积的问题,DIoU考虑到了重叠面积和中心点距离的问题,CIoU则在此基础上进一步的考虑到了高宽比的问题。
在这里插入图片描述

CIoU的计算公式如下所示,可以看出,其在DIoU的基础上加多了一个惩罚项αv。其中α为权重为正数的重叠面积平衡因子,在回归中被赋与更高的优先级,特别是在两个边框不重叠的情况下;而v则用于测量宽高比的一致性。
在这里插入图片描述

8. F-EIoU Loss

《Focal and Efficient IoU Loss》[6]是由华南理工大学学者最近提出的一篇关于目标检测损失函数的论文,文章主要的贡献是提升网络收敛速度和目标定位精度。目前检测任务的损失函数主要有两个缺点:(1)无法有效地描述边界框回归的目标,导致收敛速度慢以及回归结果不准确(2)忽略了边界框回归中不平衡的问题。

F-EIou loss首先提出了一种有效的交并集(IOU)损失,它可以准确地测量边界框回归中的重叠面积、中心点和边长三个几何因素的差异:
在这里插入图片描述
其次,基于对有效样本挖掘问题(EEM)的探讨,提出了Focal loss的回归版本,以使回归过程中专注于高质量的锚框:在这里插入图片描述
最后,将以上两个部分结合起来得到Focal-EIou Loss:
在这里插入图片描述
其中,通过加入每个batch的权重和来避免网络在早期训练阶段收敛慢的问题。

9. CDIoU Loss

《Control Distance IoU Loss》[7]是由同济大学学者提出的,文章的主要贡献是在几乎不增强计算量的前提下有效提升了边界框回归的精准度。目前检测领域主要两大问题:(1)SOTA算法虽然有效但计算成本高(2)边界框回归损失函数设计不够合理。在这里插入图片描述
文章首先提出了一种对于Region Propasl(RP)和Ground Truth(GT)之间的新评估方式,即CDIoU。可以发现,它虽然没有直接中心点距离和长宽比,但最终的计算结果是有反应出RP和GT的差异。计算公式如下:在这里插入图片描述
对比以往直接计算中心点距离或是形状相似性的损失函数,CDIoU能更合理地评估RP和GT的差异并且有效地降低计算成本。然后,根据上述的公式,CDIoU Loss可以定义为:在这里插入图片描述通过观察这个公式,可以直观地感受到,在权重迭代过程中,模型不断地将RP的四个顶点拉向GT的四个顶点,直到它们重叠为止,如下图所示。在这里插入图片描述

二、分类损失

1. CrossEntropy Loss (交叉损失函数)

交叉熵损失用于衡量两个概率分布之间的差异,特别是模型预测的概率分布与实际数据的标签(即真实概率分布)之间的差异。

Softmax与CrossEntropy Loss结合:模型的输出层通过Softmax函数转换为概率分布(每个类别的概率值,且所有类别概率之和为1),然后与真实标签(通常是one-hot编码)计算交叉熵损失。

把交叉熵表示成真实概率分布p的函数和预测概率分布q的函数:
特性与优势:

  • 优化方向明确:交叉熵损失函数的梯度直接指向了使预测概率向真实概率靠近的方向,有助于模型学习。
  • 数值稳定性好:尤其在使用softmax函数时,可以避免概率过小导致的下溢出问题。
  • 直观反映模型性能:损失值越低,说明模型的预测概率分布与真实分布越接近,分类性能越好。

在PyTorch中,可以使用nn.CrossEntropyLoss直接计算多分类的交叉熵损失,它内部隐含了Softmax转换,因此模型直接输出未归一化的logit值即可:

import torch
import torch.nn as nn

# 假设模型输出(未经Softmax处理)
outputs = torch.randn(3, 5)  # 3个样本,5分类
# 实际标签(假设为类别索引,而非one-hot)
targets = torch.tensor([1, 0, 4])  

# 初始化交叉熵损失函数
criterion = nn.CrossEntropyLoss()

# 计算损失
loss = criterion(outputs, targets)

print(loss)

2. Binary Cross Entropy Loss(二元交叉损失函数)

二元交叉熵损失函数是衡量两个概率分布差异的一种方法,特别适用于有两个可能结果的分类任务,如真(1)或假(0)。在神经网络中,它用于优化模型预测的概率分布与实际标签之间的差距。

在这里插入图片描述
PyTorch这样的深度学习框架中,你通常会这样使用二元交叉熵损失函数:

import torch
import torch.nn as nn

# 假设 outputs 是模型的预测概率(未经过sigmoid或softmax,因为 BCELoss 内部会处理)
outputs = torch.tensor([[0.6], [0.3], [0.8]], requires_grad=True)  # 预测概率
labels = torch.tensor([[1], [0], [1]])  # 实际标签

# 初始化二元交叉熵损失函数
criterion = nn.BCEWithLogitsLoss()  # 这个包含了logits的版本直接接受未经过sigmoid的输出

# 计算损失
loss = criterion(outputs, labels)

# 反向传播和优化步骤略

3. BCEWithLogitsLoss

BCEWithLogitsLoss是PyTorch中提供的一个损失函数,全称为二进制交叉熵带Logits损失(Binary Cross-Entropy Loss with Logits)。它主要用在二分类问题中,特别是神经网络的输出层直接预测的是未经过Sigmoid函数的logits值(即模型的原始输出,可以视为预测为正类的概率的对数几率),而不仅仅是概率值。

工作原理:

在传统的二元交叉熵损失函数中,通常要求模型的输出经过Sigmoid函数转换为概率(值域在0到1之间),然后再计算与实际标签之间的交叉熵。但是,BCEWithLogitsLoss将Sigmoid函数的运算合并进了损失函数内部,直接作用于未经过激活函数的网络输出(logits)。这样做有几个好处:

  • 数值稳定性:直接在logits上操作可以减少梯度消失或爆炸的风险,因为Sigmoid函数在输入值较大或较小时会导致梯度接近于0。
  • 计算效率:合并了操作减少了正向和反向传播中的步骤,提高了计算效率。
  • 简化模型定义:用户无需显式地在模型中加入Sigmoid层,简化了模型结构。
    在这里插入图片描述

在PyTorch中,使用BCEWithLogitsLoss非常直接:

import torch
import torch.nn as nn

# 假设我们的模型直接输出logits
outputs = torch.randn(3, requires_grad=True)  # 3个样本的logits输出
labels = torch.tensor([1, 0, 1], dtype=torch.float32)  # 实际标签

# 初始化损失函数
criterion = nn.BCEWithLogitsLoss()

# 计算损失
loss = criterion(outputs, labels)

# 然后进行反向传播和优化等操作
loss.backward()

4. Focal Loss

Focal Loss 是一种用于解决类别不平衡问题的损失函数,首次被提出并应用于目标检测任务中,尤其是在One-Stage检测器(如RetinaNet)中表现显著。它通过调整每个样本的损失权重来增强模型对难分类样本的关注,同时减少对易分类样本的重视,从而改善了模型的鲁棒性和精确度。

出自何凯明的《Focal Loss for Dense Object Detection》[9],出发点是解决目标检测领域中one-stage算法如YOLO系列算法准确率不高的问题。

作者认为样本的类别不均衡(比如前景和背景)是导致这个问题的主要原因。比如在很多输入图片中,我们利用网格去划分小窗口,大多数的窗口是不包含目标的。如此一来,如果我们直接运用原始的交叉熵损失,那么负样本所占比例会非常大,主导梯度的优化方向,即网络会偏向于将前景预测为背景。

即使我们可以使用OHEM(在线困难样本挖掘)算法来处理不均衡的问题,虽然其增加了误分类样本的权重,但也容易忽略掉易分类样本。而Focal loss则是聚焦于训练一个困难样本的稀疏集,通过直接在标准的交叉熵损失基础上做改进,引进了两个惩罚因子,来减少易分类样本的权重,使得模型在训练过程中更专注于困难样本。
在这里插入图片描述
在这里插入图片描述

应用

Focal Loss不仅限于目标检测,也被扩展到了图像分类、语义分割、实例分割等多种计算机视觉任务以及自然语言处理领域中,尤其适用于处理类别不平衡数据集时。

import torch
import torch.nn as nn

class FocalLoss(nn.Module):
    def __init__(self, alpha=0.25, gamma=2, logits=False, reduce=True):
        super(FocalLoss, self).__init__()
        self.alpha = alpha
        self.gamma = gamma
        self.logits = logits
        self.reduce = reduce

    def forward(self, inputs, targets):
        if self.logits:
            BCE_loss = nn.functional.binary_cross_entropy_with_logits(inputs, targets, reduce=False)
        else:
            BCE_loss = nn.functional.binary_cross_entropy(inputs, targets, reduce=False)
        
        pt = torch.exp(-BCE_loss)  # prevents nans when probability 0
        F_loss = self.alpha * (1-pt)**self.gamma * BCE_loss
        
        if self.reduce:
            return torch.mean(F_loss)
        else:
            return F_loss

# 使用示例
focal_loss = FocalLoss(alpha=0.25, gamma=2)
outputs = torch.tensor([0.9, 0.1, 0.8, 0.7], requires_grad=True)  # 假设模型输出
targets = torch.tensor([1, 0, 1, 1], dtype=torch.float32)  # 假设真实标签
loss = focal_loss(outputs, targets.unsqueeze(1))  # unsqueeze是为了形状匹配
loss.backward()

5. KL Loss

KL散度(Kullback-Leibler Divergence),也称为相对熵,是一种衡量两个概率分布之间差异的方法。在机器学习和信息论中,KL散度被用作损失函数来衡量模型预测的分布与实际数据分布之间的不一致程度,特别是在生成模型(如VAE、GANs)和强化学习等领域中应用广泛。
在这里插入图片描述

应用:

  • 信息理论:用于量化两个概率分布的信息差异。
  • 机器学习:
    • 变分自编码器(VAE):在重构损失中使用KL散度来约束编码器产生的先验分布和后验分布的差异。
    • 生成对抗网络(GANs):虽然直接使用Wasserstein距离或JS散度更常见,但KL散度的概念在理论探讨和某些变体中有所体现。
    • 强化学习:在策略迭代中,KL散度可以用来限制新旧策略之间的差异,促进探索的同时保持策略的稳定性。
  • 主题模型:如LDA(Latent Dirichlet Allocation)中,用于测量文档主题分布和模型先验的差异。

在PyTorch中,可以直接使用torch.nn.functional.kl_div或torch.distributions.kl_divergence来计算两个分布的KL散度。

import torch
import torch.nn.functional as F

# 假设P和Q是两个概率分布的张量
P = torch.tensor([0.4, 0.3, 0.3])
Q = torch.tensor([0.3, 0.4, 0.3])

# 计算KL散度,reduce='batchmean'表示求平均值,log_target=True表示在Q上取log
kl_div = F.kl_div(P.log(), Q, reduction='batchmean', log_target=True)

print("KL散度:", kl_div.item())

补充

对于交叉熵损失,除了我们在这里使用预测概率的对数(log(q(i)))外,它看起来与上面熵的方程非常相似。如果我们的预测是完美的,那就是预测分布等于真实分布,此时交叉熵就等于熵。但是,如果分布不同,则交叉熵将比熵大一些位数。交叉熵超过熵的量称为相对熵,或更普遍地称为库尔贝克-莱布里埃发散度(KL Divergence)。总结如下:
在这里插入图片描述

通常来说,一般分类损失最常用的损失函数之一便是交叉熵损失。假设我们当前做一个3个类别的图像分类任务,如猫、狗、猪。给定一张输入图片其真实类别是猫,模型通过训练用Softmax分类后的输出结果为:{“cat”: 0.3, “dog”: 0.45, “pig”: 0.25},那么此时交叉熵为:-1 * log(0.3) = 1.203。当输出结果为:{“cat”: 0.5, “dog”: 0.3, “pig”: 0.2}时,交叉熵为:-1 * log(0.5) = 0.301。可以发现,当真实类别的预测概率接近于0时,损失会变得非常大。但是当预测值接近真实值时,损失将接近0。

6. Dice Loss

Dice Loss 是一种在医学影像分割和其他计算机视觉任务中常用的损失函数,尤其是处理类别不平衡问题时(如背景像素远多于前景像素的情况)。它源于Sørensen-Dice系数,也称为Dice相似系数(Dice Similarity Coefficient, DSC),用于衡量两个样本集之间的相似度。在深度学习中,Dice Loss 被用作训练模型以优化分割预测和真实分割标签之间的重叠度。出自V-Net。
在这里插入图片描述
在这里插入图片描述
从公式右边也可以看出,其实Dice系数是等价于F1分数的,优化Dice等价于优化F1值。此外,为了防止分母项为0,一般我们会在分子和分母处同时加入一个很小的数作为平滑系数,也称为拉普拉斯平滑项。Dice损失有以下主要特性:

  • 有益于正负样本不均衡的情况,侧重于对前景的挖掘;
  • 训练过程中,在有较多小目标的情况下容易出现振荡;
  • 极端情况下会出现梯度饱和的情况。
    所以一般来说,我们都会结合交叉熵损失或者其他分类损失一同进行优化。
import torch
import torch.nn.functional as F

def dice_loss(preds, targets, eps=1e-6):
    preds = preds.sigmoid()  # 如果你的模型输出没有经过sigmoid激活,需要加上这一行
    intersection = (preds * targets).sum(dim=(2, 3))
    union = preds.sum(dim=(2, 3)) + targets.sum(dim=(2, 3))
    dice_score = (2. * intersection + eps) / (union + eps)
    return 1 - dice_score.mean()

# 假设preds和targets是形状为(N, C, H, W)的张量
preds = torch.rand(4, 1, 128, 128)  # 预测概率
targets = torch.rand(4, 1, 128, 128).round()  # 真实标签,通常是0或1
loss = dice_loss(preds, targets)
print("Dice Loss:", loss.item())

7. Tversky loss

Tversky Loss 是一种用于图像分割和目标检测任务的损失函数,特别是在处理高度不平衡数据集时。它基于经典的Sørensen-Dice系数(Dice Loss)进行了扩展,通过引入两个额外的参数来赋予错分类(False Positives和False Negatives)不同的惩罚权重,从而提供更大的灵活性以适应不同的应用场景。Tversky Loss最初由 Salehi等人在2017年提出,用于医学图像分割任务。
在这里插入图片描述

Tversky loss,发表于CVPR 2018上的一篇《Tversky loss function for image segmentation using 3D fully convolutional deep networks》文章,是根据Tversky 等人于1997年发表的《Features of Similarity》文章[11] 所提出的Tversky指数所改造的。

Tversky系数主要用于描述两个特征(集合)之间的相似度,其定义如下:在这里插入图片描述
由上可知,它是结合了Dice系数(F1-score)以及Jaccard系数(IoU)的一种广义形式,如:

  • 当 α = β = 0.5时,此时Tversky loss便退化为Dice系数(分子分母同乘于2)
  • 当 α = β = 1时,此时Tversky loss便退化为Jaccard系数(交并比)

因此,我们只需控制 α 和 β 便可以控制假阴性和假阳性之间的平衡。比如在医学领域我们要检测肿瘤时,更多时候我们是希望Recall值(查全率,也称为灵敏度或召回率)更高,因为我们不希望说将肿瘤检测为非肿瘤,即假阴性。因此,我们可以通过增大 β 的取值,来提高网络对肿瘤检测的灵敏度。其中,α + β 的取值我们一般会令其1。

import torch
import torch.nn.functional as F

def tversky_loss(preds, targets, alpha=0.3, beta=0.7, eps=1e-6):
    """
    preds: 预测概率,形状为(N, C, H, W)或(N, C, H, W, D)
    targets: 真实标签,形状为(N, H, W)或(N, H, W, D),值为0或1
    alpha, beta: 控制FP和FN的权重,默认值为0.3和0.7
    eps: 防止除以零的小常数
    """
    preds = preds.sigmoid()  # 如果模型输出没有经过sigmoid激活,需要这一步
    num_classes = preds.shape[1]
    
    # 确保targets的通道维度与preds匹配
    targets = targets.unsqueeze(1).expand(-1, num_classes, -1, -1, -1)
    
    TP = (preds * targets).sum(dim=(2, 3))  # 计算每类的真正例
    FP = (preds * (1-targets)).sum(dim=(2, 3))  # 假正例
    FN = ((1-preds) * targets).sum(dim=(2, 3))  # 假负例
    
    tversky = (TP + eps) / (TP + alpha*FP + beta*FN + eps)
    return 1 - tversky.mean()

# 示例使用
preds = torch.rand(4, 1, 128, 128)  # 预测概率
targets = torch.rand(4, 128, 128).round()  # 真实标签
loss = tversky_loss(preds, targets)
print("Tversky Loss:", loss.item())

8. Contrastive Loss

Contrastive Loss(对比损失)是一种在机器学习和深度学习领域中广泛使用的损失函数,尤其在无监督学习和半监督学习场景下,以及自监督学习中的对比学习方法里尤为重要。它的主要目的是通过最大化相似样本对之间的相似度(正样本对)和减少非相似样本对之间的相似度(负样本对),从而使得模型学习到数据的有效表示。

基本概念:

在对比学习的框架下,通常涉及到成对的数据样本,分为正样本对和负样本对:

  • 正样本对:通常指的是来自同一对象或语义相似的两个不同表示(例如,一张图片的不同视角或同一语句的不同变形)。
  • 负样本对:指来自不同对象或语义不同的表示,理论上不应该相似。

对比损失函数通过比较正负样本对之间的相似度来优化模型,鼓励学习到的特征空间中相似样本尽可能接近,而不同样本尽可能远离。

在这里插入图片描述
简化的对比损失在PyTorch中的实现示例:

import torch
import torch.nn.functional as F

def contrastive_loss(embeddings_a, embeddings_b, labels, margin=1.0, scale=10):
    # 计算嵌入间的相似度,这里使用点积
    similarities = torch.matmul(embeddings_a, embeddings_b.t())
    
    # 获取正样本对的相似度,即同一标签下的样本
    mask_pos = torch.eq(labels.expand(embeddings_a.size(0), labels.expand(embeddings_b.size(0)).t()).unsqueeze(1))
    similarities_masked = similarities.masked_select(mask_pos).view(-1)
    
    # 对正样本对计算损失,这里使用margin-based的损失简化版,实际中可能更复杂
    loss_contrastive = F.relu(margin - similarities_masked).pow(2).mean()
    
    return scale * loss_contrastive

# 示例用法
embeddings = torch.randn(4, 128)  # 假设有4个样本的128维嵌入表示
labels = torch.tensor([0, 0, 1, 1, 1])  # 假定的标签
loss = contrastive_loss(embeddings, embeddings, labels)
print("Contrastive Loss:", loss.item())

三、不同深度学习框架下的损失函数自定义方式

1. Pytorch


import torch  
import torch.nn as nn  
import torch.nn.functional as F  
  
class Loss(nn.Module):  
    def __init__(self):  
        super(Loss, self).__init__()  
        # 添加需要初始化的参数  
  
    def forward(self, inputs, targets):  
        # 添加相关的计算逻辑
        loss_output = ...
        return loss_output

2. Tensorflow


class CustomMSE(keras.losses.Loss):
    def __init__(self):
        super(CustomMSE, self).__init__()
        # 添加需要初始化的参数  

    def __call__(self, y_true, y_pred):
      # 添加相关d的计算逻辑
        loss_output = ...
        return loss_output

参考:

深度学习——损失函数
一文看尽深度学习中的各种损失函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/593272.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习和“劳动”相关的谚语,柯桥俄语培训

1. Бог труды́ лю́бит. 天道酬勤。 2. В ми́ре нет тру́дных дел, ну́жно лишь усе́рдие. 世上无难事,只怕有心人。 3. У́тро вечера мудренее. 一日之计在于晨。 4. Что посе́ешь,…

车载电子电器架构 —— 关于bus off汇总

车载电子电器架构 —— 关于bus off汇总 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明…

[Java EE] 多线程(六):线程池与定时器

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏:🍕 Collection与数据结构 (90平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 🧀Java …

语义分割——铁路轨道数据集

引言 亲爱的读者们,您是否在寻找某个特定数据集,用于研究或项目实践?欢迎您在评论区留言,或者通过公众号私信告诉我,您想要的数据集的类型主题。小编会竭尽全力为您寻找,并在找到后第一时间与您分享。 重…

NASA数据集——NOAA 气溶胶和海洋科学考察数据(AEROSE)

Saharan Dust AERosols and Ocean Science Expeditions 简介 NOAA 气溶胶和海洋科学考察(AEROSE)是一种基于测量的综合方法,用于了解热带海洋上空气溶胶长程飘移的影响(Morris 等人,2006 年;Nalli 等人&a…

直流屏整流模块HG07A220R电源模块HG10A220R

直流屏整流模块HG07A220R电源模块HG10A220R 其他同类型监控模块PM09T电源模块HG22005/S,HG22010/S,HG11010/S,HG11020/S,HG10A220Z,HG10A220F,HG05A220Z,HG07A220Z,HG10A110Z&#x…

Electron 对 SQLite 进行加密

上一篇讲了如何在 Electron使用 SQLite,如果 SQLite 中存有敏感数据,客户端采用明文存储风险很高,为了保护客户数据,就需要对数据进行加密,由于 electron 对代码并不加密,所以这里排除通过逆向工程进行数据…

从论文中看AI绘画

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 主要看是看Diffusion Models,CLIP,ControlNet,IP-Adapter这种经典论文,尝试总结论文写作的一些方式以及图像生成模型的一些内在思想. 对于其中的数学原理和代码不过深究. DDPM 使用扩散模型得到高质量图像,证明了这…

三、Linux基础命令

章节目标 了解Linux系统注意事项掌握Linux基础命令知道vmware tools的作用 一、Linux系统使用注意 1. Linux严格区分大小写 Linux 和Windows不同,Linux严格区分大小写的,包括文件名和目录名、命令、命令选项、配置文件设置选项等。例如,在…

5.3 调制与解调

信号的调制与解调是通信系统中一对基本的概念,涉及将信息(语音、视频、数据等)在发送之前进行处理以便在传输介质(如无线电波、电话线等)上有效传输,以及在接收端恢复这些信息的过程。 一、调制&#xff0…

Leetcode—289. 生命游戏【中等】

2024每日刷题&#xff08;126&#xff09; Leetcode—289. 生命游戏 算法思想 实现代码 class Solution { public:void gameOfLife(vector<vector<int>>& board) {int rows board.size();int cols board[0].size();int neighbors[3] {0, 1, -1};vector<…

spring框架学习记录(2)

文章目录 注解开发bean相关注解开发定义bean纯注解开发纯注解开发中bean的管理 依赖注入相关依赖注入第三方bean管理第三方bean依赖注入 AOP(Aspect Oriented Programming)面向切面编程AOP简介AOP核心概念AOP工作流程AOP切入点表达式通知类型AOP通知获取数据 注解开发 bean相关…

Day19 代码随想录打卡|字符串篇---反转字符串II

题目&#xff08;leecode T541&#xff09;&#xff1a; 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起&#xff0c;每计数至 2k 个字符&#xff0c;就反转这 2k 字符中的前 k 个字符。 如果剩余字符少于 k 个&#xff0c;则将剩余字符全部反转。如果剩余字符小…

OceanBase 轻量级数仓关键技术解读

码到三十五 &#xff1a; 个人主页 为了更好地聚合和治理跨域数据&#xff0c;帮助企业用较低的成本快速聚合分析&#xff0c;快速决策&#xff0c;不断的让企业积累的数据产生价值&#xff0c;从全域海量数据抓取&#xff0c;高性能流批处理&#xff0c;元数据血缘治理等等方面…

数据分析从入门到精通 1.numpy 剑客修炼

会在某一瞬间突然明白&#xff0c;有些牢笼是自己给自己的 —— 24.5.5 一、数据分析秘笈介绍 1.什么是数据分析 是把隐藏在一些看似杂乱无章的数据背后的信息提炼出来&#xff0c;总结出所研究对象的内在规律。使得数据的价值最大化 案例&#xff1a; 分析用户的消…

Kotlin: Expecting a ‘>‘

数组值为任意类型&#xff0c;声明报错: Kotlin: Expecting a > var anyArr1: Array<Any?> arrayOf("a", "b", "c", true, 34)原因是&#xff1a; // var anyArr1: Array<Any?> arrayOf("a", "b", "c…

概念解析 | 威胁建模与DREAD评估:构建安全的系统防线

注1:本文系"概念解析"系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:威胁建模和DREAD模型 概念解析 | 威胁建模与DREAD评估:构建安全的系统防线 What Is Threat Modeling? Definition, Process, Examples, and Best Practices - Spic…

蓝桥杯-路径之谜

题目描述 小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。城堡里面什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡的地面时n*n个方格。如下图所示。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或者纵向移动&#xff0c;但是不能斜着走&#x…

SpringBoot自定义定时任务

通常&#xff0c;在我们的项目中需要定时给前台发送一些提示性消息或者我们想要的定时信息&#xff0c;这个时候就需要使用定时任务来实现这一功能&#xff0c;实现也很简单&#xff0c;接下来具体来看看吧~ 简单定时任务 首先&#xff0c;你需要在你的启动类上加上开启定时任…

贪吃蛇(下)游戏的实现

感谢大佬的光临各位&#xff0c;希望和大家一起进步&#xff0c;望得到你的三连&#xff0c;互三支持&#xff0c;一起进步 个人主页&#xff1a;LaNzikinh-CSDN博客 文章目录 前言一.蛇和食物的打印二.游戏的运行逻辑三.结束游戏 &#xff08;善后工作&#xff09;四.游戏的测…
最新文章