• pytorch loss函数整理


    变量名解释

    logits:未经过normalize(未经过激活函数处理)的原始预测值,例如一个mlp将特征映射到num_target_class维的输出tensor就是logits。
    probs:probabilities的简写,例如logits经过sigmoid函数,就变成了分布在0-1之间的概率值probs。

    Binary Cross-Entropy Loss

    Binary Cross-Entropy Loss,简称为BCE loss,即二元交叉熵损失。

    二元交叉熵损失是一种用于二分类问题的损失函数。它衡量的是模型预测的概率分布与真实标签的概率分布之间的差异。在二分类问题中,每个样本的标签只有两种可能的状态,通常表示为 0(负类)和 1(正类)。

    其公式为:
    L B C E = − 1 N ∑ i = 1 N [ y i log ⁡ ( p i ) + ( 1 − y i ) log ⁡ ( 1 − p i ) ] L_{BCE}=-\frac{1}{N} \sum_{i=1}^N\left[y_i \log \left(p_i\right)+\left(1-y_i\right) \log \left(1-p_i\right)\right] LBCE=N1i=1N[yilog(pi)+(1yi)log(1pi)]

    其中:

    • N N N是数据集的样本数量。
    • y i y_i yi是第 i {i} i个样本的真实标签,取值为 0 或 1,即第 i {i} i个样本要么属于类别 0(负类),要么属于类别 1(正类)。
    • p i p_i pi是第 i {i} i个样本属于类别 1(正类)的预测概率
    • log ⁡ \log log是是自然对数。

    当真实标签 y i = 1 y_i=1 yi=1 时,损失函数的第一部分 y i log ⁡ ( p i ) y_i \log \left(p_i\right) yilog(pi) 起作用,第二部分为 0 。此时, 如果预测概率 p i p_i pi 接近 1 (接近真实标签 y i = 1 y_i=1 yi=1), 那么 log ⁡ ( p i ) \log \left(p_i\right) log(pi) 接近 0 , 损失较小;如果 p i p_i pi 接近 0 (即模型预测错误),那么 log ⁡ ( p i ) \log \left(p_i\right) log(pi) 会变得成绝对值很大的负数,导致取反后loss很大。

    当真实标签 y i = 0 y_i=0 yi=0 时,损失函数的第二部分 ( 1 − y i ) log ⁡ ( 1 − p i ) \left(1-y_i\right) \log \left(1-p_i\right) (1yi)log(1pi)起作用,第一部分为 0。此时,预测概率 p i p_i pi越接近于 0,整体loss越小。

    Pytorch手动实现

    import torch
    import torch.nn.functional as F
    
    def manual_binary_cross_entropy_with_logits(logits, targets):
        # 使用 Sigmoid 函数将 logits 转换为概率
        probs = torch.sigmoid(logits)
        # 计算二元交叉熵损失
        loss = - torch.mean(targets * torch.log(probs) + (1 - targets) * torch.log(1 - probs))
        return loss
    
    # logits和targets可以是任意shape的tensor,只要两者shape相同即可
    logits = torch.tensor([0.2, -0.4, 1.2, 0.8])
    targets = torch.tensor([0., 1., 1., 0.])
    assert logits.shape == targets.shape
    
    # 使用 PyTorch 的 F.binary_cross_entropy_with_logits 函数计算损失
    loss_pytorch = F.binary_cross_entropy_with_logits(logits, targets)
    
    # 使用手动实现的函数计算损失
    loss_manual = manual_binary_cross_entropy_with_logits(logits, targets)
    
    print(f'Loss (PyTorch): {loss_pytorch.item()}')
    print(f'Loss (Manual): {loss_manual.item()}')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    F.binary_cross_entropy 与 F.binary_cross_entropy_with_logits的区别

    F.binary_cross_entropy的输入是probs

    F.binary_cross_entropy_with_logits的输入是logits

     
     

    Dice Loss

    Dice Loss 来自文章《V-Net: Fully Convolutional Neural Networks for Volumetric Medical Image Segmentation》,它能够有效地处理图像分割任务中正负样本不平衡问题。例如,当一张图片中真实分割区域占比很小,即gt_label里的正样本像素很少。这时候如果用BCE Loss,图片里的每个像素都要去进行二分类,而绝大部分的像素都是负样本,所以会存在正负样本不平衡的问题。

    介绍Dice Loss前,需要先了解Dice系数。

    Dice系数是一种用于评估两个集合的相似性的度量函数,取值范围在0到1之间,取值越大表示越相似。定义如下:
     dice coefficient  = 2 × ∣ X ∩ Y ∣ ∣ X ∣ + ∣ Y ∣ \text { dice coefficient }=\frac{2 \times|X \cap Y|}{|X|+|Y|}  dice coefficient =X+Y2×XY

    其中 X X X Y Y Y 分别是两个样本集合, X ∩ Y X \cap Y XY 表示它们交集的大小, ∣ X ∣ |X| X ∣ Y ∣ |Y| Y分别表示 X X X Y Y Y中的样本个数。由于分子乘上了 2,Dice 系数的值在 0 到 1 之间,值越大表示相似度越高。

    而对于Dice Loss,我们的训练目的是让两个样本越来越相似,所以当 X X X Y Y Y越相似,loss值应该越小,而Dice系数的值在 0 到 1 之间,我们可以直接用1减去Dice系数来作为Dice Loss,这样就能达成两个样本越相似loss值越小的目的:
    L d i c e = 1 −  dice coefficient  L_{dice}= 1 - \text { dice coefficient } Ldice=1 dice coefficient 

    在图像分割任务中,Dice 系数计算预测分割区域和真实分割区域之间的重叠度。上述公式中的 X X X Y Y Y则分别代表预测分割区域和真实分割区域。
    I = ∑ 1 N p i y i U = ∑ 1 N ( p i + y i ) = ∑ 1 N p i + ∑ 1 N y i

    I=1NpiyiU=1N(pi+yi)=1Npi+1Nyi" role="presentation" style="position: relative;">I=1NpiyiU=1N(pi+yi)=1Npi+1Nyi
    I=1NpiyiU=1N(pi+yi)=1Npi+1Nyi

    其中:

    • N N N是一张图片里的像素数量。
    • y i y_i yi是第 i {i} i个像素的真实标签,取值为 0 或 1,即第 i {i} i个像素要么属于类别 0(非分割区域),要么属于类别 1(分割区域)。
    • p i p_i pi是第 i {i} i个像素属于类别 1(分割区域)的预测概率。
    • I I I是图像的分割区域中,每个像素的预测概率之和。 I I I代表上述公式中的 ∣ X ∩ Y ∣ |X \cap Y| XY
    • U U U是图像每个像素的真实分割概率之和(即真实分割区域的像素总数) + 每个像素的预测分割概率之和。 U U U代表上述公式中的 ∣ X ∣ + ∣ Y ∣ |X|+|Y| X+Y

    Dice Loss 为 Dice 系数的补数,即 1 减去 Dice 系数。在实际应用中,为了避免除以零的情况,通常会在分子和分母中添加一个小的平滑项 ϵ \epsilon ϵ
    L dice  = 1 − 2 I + ε U + ε L_{\text {dice }}=1-\frac{2 I+\varepsilon}{U+\varepsilon} Ldice =1U+ε2I+ε

    在许多实现中,将预测值 logits 和目标 targets 在计算Dice Loss的过程中除以一个缩放因子(如 1000 或 10000),通常是为了数值稳定性。当处理大型图像或大量数据时,像素点的总数可能非常大,这意味着求和操作可能产生非常大的值。这可能导致计算过程中出现数值不稳定性,尤其是在梯度下降和反向传播过程中。通过引入一个缩放因子,可以将这些值缩小到一个更合理的范围内,从而减少数值不稳定性的风险。

    Pytorch手动实现

    import torch
    import torch.nn.functional as F
    
    def dice_loss(
        logits: torch.Tensor,  # shape为[bs, h, w]
        targets: torch.Tensor, # shape为[bs, h, w]
        scale=1000,
        eps=1e-6,
    ):
        probs = logits.sigmoid()
        # 只对h,w这两维求和,保留bs这一维,这样每个sample都可以得到一个dice loss
        numerator = 2 * (probs / scale * targets).sum(dim=(-2, -1))
        denominator = (probs / scale).sum(dim=(-2, -1)) + (targets / scale).sum(dim=(-2, -1))
        loss = 1 - (numerator + eps) / (denominator + eps)
        return loss
    
    # 随机生成shape为(4, 480, 640)的预测值 logits 和目标 targets
    # targets要么是 0(非分割区域),要么是 1(分割区域)
    logits = torch.randn(4, 480, 640)
    targets = torch.randint(0, 2, (4, 480, 640))
    
    loss = dice_loss(logits, targets) # shape为[bs, ]
    
    print(f"Dics Loss: {loss}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    GIOU Loss

    Focal Loss

    Cross-Entropy Loss

    KLDivLoss

  • 相关阅读:
    有哪些免费的数据恢复软件?EasyRecovery免费版下载
    工会排队模式:电商新营销模式吸引消费者,提升销售!
    Unity中国、Cocos为OpenHarmony游戏生态插上腾飞的翅膀
    刘伟光:超大型金融机构国产数据库全面迁移成功实践
    SQL 语句执行过程
    K. Kingdom‘s Power,树形dp
    深⼊理解指针(5)【深入理解指针,体会大厂的笔试题】
    Java类和对象基础
    基于QT环境下,实现客户端红外采集人体向服务端通信。
    云计算与大数据第三章 云存储练习题及答案
  • 原文地址:https://blog.csdn.net/j___t/article/details/136429803