• Pytorch模型训练实用教程学习笔记:三、损失函数汇总


    前言

    最近在重温Pytorch基础,然而Pytorch官方文档的各种API是根据字母排列的,并不适合学习阅读。
    于是在gayhub上找到了这样一份教程《Pytorch模型训练实用教程》,写得不错,特此根据它来再学习一下Pytorch。
    仓库地址:https://github.com/TingsongYu/PyTorch_Tutorial

    损失函数汇总

    Pytorch中,有下列一些损失函数.

    L1loss

    torch.nn.L1Loss(size_average=None, reduce=None)
    功能:
    计算 output 和 target 之差的绝对值,可选返回同维度的 tensor 或者是一个标量。
    计算公式:
    在这里插入图片描述
    参数:
    reduce(bool)- 返回值是否为标量,默认为 True
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。

    调用实例:

    import torch
    import torch.nn as nn
    
    # 生成网络输出 以及 目标输出
    output = torch.ones(2, 2, requires_grad=True)*0.5
    target = torch.ones(2, 2)
    
    # 设置三种不同参数的L1Loss
    reduce_False = nn.L1Loss(size_average=True, reduce=False)
    size_average_True = nn.L1Loss(size_average=True, reduce=True)
    size_average_False = nn.L1Loss(size_average=False, reduce=True)
    
    o_0 = reduce_False(output, target)
    o_1 = size_average_True(output, target)
    o_2 = size_average_False(output, target)
    
    print('\nreduce=False, 输出同维度的loss:\n{}\n'.format(o_0))
    print('size_average=True,\t求平均:\t{}'.format(o_1))
    print('size_average=False,\t求和:\t{}'.format(o_2))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    MSELoss

    torch.nn.MSELoss(size_average=None, reduce=None, reduction=‘elementwise_mean’)
    功能:
    计算 output 和 target 之差的平方,可选返回同维度的 tensor 或者是一个标量。
    计算公式:
    在这里插入图片描述
    参数:
    reduce(bool)- 返回值是否为标量,默认为 True
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。

    调用实例:

    # coding: utf-8
    
    import torch
    import torch.nn as nn
    
    # ----------------------------------- MSE loss
    
    # 生成网络输出 以及 目标输出
    output = torch.ones(2, 2, requires_grad=True) * 0.5
    target = torch.ones(2, 2)
    
    # 设置三种不同参数的L1Loss
    reduce_False = nn.MSELoss(size_average=True, reduce=False)
    size_average_True = nn.MSELoss(size_average=True, reduce=True)
    size_average_False = nn.MSELoss(size_average=False, reduce=True)
    
    
    o_0 = reduce_False(output, target)
    o_1 = size_average_True(output, target)
    o_2 = size_average_False(output, target)
    
    print('\nreduce=False, 输出同维度的loss:\n{}\n'.format(o_0))
    print('size_average=True,\t求平均:\t{}'.format(o_1))
    print('size_average=False,\t求和:\t{}'.format(o_2))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    CrossEntropyLoss

    torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-
    100, reduce=None, reduction=‘elementwise_mean’)
    功能:
    将输入经过 softmax 激活函数之后,再计算其与 target 的交叉熵损失。即该方法将nn.LogSoftmax()和 nn.NLLLoss()进行了结合。严格意义上的交叉熵损失函数应该是nn.NLLLoss()。
    计算公式:
    在这里插入图片描述
    参数:
    weight(Tensor)- 为每个类别的 loss 设置权值,常用于类别不均衡问题。weight 必须是 float类型的 tensor,其长度要于类别 C 一致,即每一个类别都要设置有 weight。
    带 weight 的计算公式:
    在这里插入图片描述
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True
    ignore_index(int)- 忽略某一类别,不计算其 loss,其 loss 会为 0,并且,在采用size_average 时,不会计算那一类的 loss,除的时候的分母也不会统计那一类的样本。

    调用实例:

    import torch
    import torch.nn as nn
    import numpy as np
    import math
    
    # ----------------------------------- CrossEntropy loss: base
    
    loss_f = nn.CrossEntropyLoss(weight=None, size_average=True, reduce=False)
    # 生成网络输出 以及 目标输出
    output = torch.ones(2, 3, requires_grad=True) * 0.5      # 假设一个三分类任务,batchsize=2,假设每个神经元输出都为0.5
    target = torch.from_numpy(np.array([0, 1])).type(torch.LongTensor)
    
    loss = loss_f(output, target)
    
    print('--------------------------------------------------- CrossEntropy loss: base')
    print('loss: ', loss)
    print('由于reduce=False,所以可以看到每一个样本的loss,输出为[1.0986, 1.0986]')
    
    
    # 熟悉计算公式,手动计算第一个样本
    output = output[0].detach().numpy()
    output_1 = output[0]              # 第一个样本的输出值
    target_1 = target[0].numpy()
    
    # 第一项
    x_class = output[target_1]
    # 第二项
    exp = math.e
    sigma_exp_x = pow(exp, output[0]) + pow(exp, output[1]) + pow(exp, output[2])
    log_sigma_exp_x = math.log(sigma_exp_x)
    # 两项相加
    loss_1 = -x_class + log_sigma_exp_x
    print('---------------------------------------------------  手动计算')
    print('第一个样本的loss:', loss_1)
    
    
    # ----------------------------------- CrossEntropy loss: weight
    
    weight = torch.from_numpy(np.array([0.6, 0.2, 0.2])).float()
    loss_f = nn.CrossEntropyLoss(weight=weight, size_average=True, reduce=False)
    output = torch.ones(2, 3, requires_grad=True) * 0.5  # 假设一个三分类任务,batchsize为2个,假设每个神经元输出都为0.5
    target = torch.from_numpy(np.array([0, 1])).type(torch.LongTensor)
    loss = loss_f(output, target)
    print('\n\n--------------------------------------------------- CrossEntropy loss: weight')
    print('loss: ', loss)  #
    print('原始loss值为1.0986, 第一个样本是第0类,weight=0.6,所以输出为1.0986*0.6 =', 1.0986*0.6)
    
    # ----------------------------------- CrossEntropy loss: ignore_index
    
    loss_f_1 = nn.CrossEntropyLoss(weight=None, size_average=False, reduce=False, ignore_index=1)
    loss_f_2 = nn.CrossEntropyLoss(weight=None, size_average=False, reduce=False, ignore_index=2)
    
    output = torch.ones(3, 3, requires_grad=True) * 0.5  # 假设一个三分类任务,batchsize为2个,假设每个神经元输出都为0.5
    target = torch.from_numpy(np.array([0, 1, 2])).type(torch.LongTensor)
    
    loss_1 = loss_f_1(output, target)
    loss_2 = loss_f_2(output, target)
    
    print('\n\n--------------------------------------------------- CrossEntropy loss: ignore_index')
    print('ignore_index = 1: ', loss_1)     # 类别为1的样本的loss为0
    print('ignore_index = 2: ', loss_2)     # 类别为2的样本的loss为0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    NLLLoss

    torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100, reduce=None,reduction=‘elementwise_mean’)
    功能:
    常用于多分类任务,但是 input 在输入 NLLLoss()之前,需要对 input 进行 log_softmax 函数激活,即将 input 转换成概率分布的形式,并且取对数。这些步骤隐含在了CrossEntropyLoss中。

    参数:
    weight(Tensor)- 为每个类别的 loss 设置权值,常用于类别不均衡问题。weight 必须是 float类型的 tensor,其长度要于类别 C 一致,即每一个类别都要设置有 weight。
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为除以权重之和的平均值;为 False 时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。
    ignore_index(int)- 忽略某一类别,不计算其 loss,其 loss 会为 0,并且,在采用
    size_average 时,不会计算那一类的 loss,除的时候的分母也不会统计那一类的样本。

    调用实例:

    # coding: utf-8
    
    import torch
    import torch.nn as nn
    import numpy as np
    
    # ----------------------------------- log likelihood loss
    
    # 各类别权重
    weight = torch.from_numpy(np.array([0.6, 0.2, 0.2])).float()
    
    # 生成网络输出 以及 目标输出
    output = torch.from_numpy(np.array([[0.7, 0.2, 0.1], [0.4, 1.2, 0.4]])).float()  
    output.requires_grad = True
    target = torch.from_numpy(np.array([0, 0])).type(torch.LongTensor)
    
    
    loss_f = nn.NLLLoss(weight=weight, size_average=True, reduce=False)
    loss = loss_f(output, target)
    
    print('\nloss: \n', loss)
    print('\n第一个样本是0类,loss = -(0.6*0.7)={}'.format(loss[0]))
    print('\n第二个样本是0类,loss = -(0.6*0.4)={}'.format(loss[1]))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    PoissonNLLLoss

    torch.nn.PoissonNLLLoss(log_input=True, full=False, size_average=None, eps=1e^8, reduce=None, reduction=‘elementwise_mean’)
    功能:
    用于 target 服从泊松分布的分类任务。
    参数:
    log_input(bool)- 为 True 时,计算公式为:loss(input,target)=exp(input) - target * input; 为 False 时,loss(input,target)=input - target * log(input+eps)
    full(bool)- 是否计算全部的 loss。例如,当采用斯特林公式近似阶乘项时,此为target*log(target) - target+0.5∗log(2πtarget)
    eps(float)- 当 log_input = False 时,用来防止计算 log(0),而增加的一个修正项。即loss(input,target)=input - target * log(input+eps)
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True

    调用实例:

    # coding: utf-8
    
    import torch
    import torch.nn as nn
    import numpy as np
    
    # ----------------------------------- Poisson NLLLoss
    
    # 生成网络输出 以及 目标输出
    log_input = torch.randn(5, 2, requires_grad=True)
    target = torch.randn(5, 2)
    
    loss_f = nn.PoissonNLLLoss()
    loss = loss_f(log_input, target)
    print('\nloss: \n', loss)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    KLDivLoss

    torch.nn.KLDivLoss(size_average=None, reduce=None, reduction=‘elementwise_mean’)

    功能:
    计算 input 和 target 之间的 KL 散度。
    参数:
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值,平均值为element-wise 的,而不是针对样本的平均;为 False 时,返回是各样本各维度的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

    注意事项:
    要想获得真正的 KL 散度,需要如下操作:

    • reduce = True ;size_average=False
    • 计算得到的 loss 要对 batch 进行求平均

    调用实例:

    # coding: utf-8
    
    import torch
    import torch.nn as nn
    import numpy as np
    
    # -----------------------------------  KLDiv loss
    
    loss_f = nn.KLDivLoss(size_average=False, reduce=False)
    loss_f_mean = nn.KLDivLoss(size_average=True, reduce=True)
    
    # 生成网络输出 以及 目标输出
    output = torch.from_numpy(np.array([[0.1132, 0.5477, 0.3390]])).float()
    output.requires_grad = True
    target = torch.from_numpy(np.array([[0.8541, 0.0511, 0.0947]])).float()
    
    loss_1 = loss_f(output, target)
    loss_mean = loss_f_mean(output, target)
    
    print('\nloss: ', loss_1)
    print('\nloss_mean: ', loss_mean)
    
    
    # 熟悉计算公式,手动计算样本的第一个元素的loss,注意这里只有一个样本,是 element-wise计算的
    
    output = output[0].detach().numpy()
    output_1 = output[0]           # 第一个样本的第一个元素
    target_1 = target[0][0].numpy()
    
    loss_1 = target_1 * (np.log(target_1) - output_1)
    
    print('\n第一个样本第一个元素的loss:', loss_1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    BCELoss

    torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction=‘elementwise_mean’)

    功能:
    二分类任务时的交叉熵计算函数。此函数可以认为是 nn.CrossEntropyLoss 函数的特例。其分类限定为二分类,y 必须是{0,1}。还需要注意的是,input 应该为概率分布的形式,这样才符合交叉熵的应用。所以在 BCELoss 之前,input 一般为 sigmoid 激活层的输出。

    计算公式:
    在这里插入图片描述

    参数:
    weight(Tensor)- 为每个类别的 loss 设置权值,常用于类别不均衡问题。
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True

    BCEWithLogitsLoss

    torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction=‘elementwise_mean’, pos_weight=None)
    功能:
    将 Sigmoid 与 BCELoss 结合,类似于 CrossEntropyLoss(将 nn.LogSoftmax()和 nn.NLLLoss()进行结合)。即 input 会经过 Sigmoid 激活函数,将 input 变成概率分布的形式。

    计算公式:
    在这里插入图片描述

    参数:
    weight(Tensor)- : 为 batch 中单个样本设置权值,If given, has to be a Tensor of size “nbatch”.
    pos_weight-: 正样本的权重, 当 p>1,提高召回率,当 P<1,提高精确度。可达到权衡召回率(Recall)和精确度(Precision)的作用。 Must be a vector with length equal to the number of classes.
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True

    MarginRankingLoss

    torch.nn.MarginRankingLoss(margin=0, size_average=None, reduce=None, reduction=‘elementwise_mean’)
    功能:
    计算两个向量之间的相似度,当两个向量之间的距离大于 margin,则 loss 为正,小于
    margin,loss 为 0。
    计算公式:
    在这里插入图片描述
    参数:
    margin(float)- x1 和 x2 之间的差异。
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

    HingeEmbeddingLoss

    torch.nn.HingeEmbeddingLoss(margin=1.0, size_average=None, reduce=None, reduction=‘elementwise_mean’)
    功能:
    折页损失的拓展,主要用于衡量两个输入是否相似。
    参数:
    margin(float)- 默认值为 1,容忍的差距。
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

    MultiLabelMarginLoss

    torch.nn.MultiLabelMarginLoss(size_average=None, reduce=None, reduction=‘elementwise_mean’)
    功能:
    用于一个样本属于多个类别时的分类任务。
    计算公式:
    在这里插入图片描述
    参数:
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False
    时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

    SmoothL1Loss

    torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction=‘elementwise_mean’)

    功能:
    计算平滑 L1 损失.
    参数:
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

    SoftMarginLoss

    torch.nn.SoftMarginLoss(size_average=None, reduce=None, reduction=‘elementwise_mean’)
    功能:
    计算二分类损失(和前面的BCELoss有什么区别未知)
    参数:
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False
    时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

    MultiLabelSoftMarginLoss

    torch.nn.MultiLabelSoftMarginLoss(weight=None, size_average=None, reduce=None, reduction=‘elementwise_mean’)
    功能:
    SoftMarginLoss 多标签版本。
    参数:
    weight(Tensor)- 为每个类别的 loss 设置权值。weight 必须是 float 类型的 tensor,其长度要于类别 C 一致,即每一个类别都要设置有 weight。

    CosineEmbeddingLoss

    torch.nn.CosineEmbeddingLoss(margin=0, size_average=None, reduce=None, reduction=‘elementwise_mean’)
    功能:
    衡量两个输入是否相似。
    参数:
    margin(float)- : 取值范围[-1,1], 推荐设置范围 [0, 0.5]
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

    MultiMarginLoss

    torch.nn.MultiMarginLoss(p=1, margin=1, weight=None, size_average=None, reduce=N
    one, reduction=‘elementwise_mean’)

    功能:
    计算多分类的折页损失。

    参数:
    p(int)- 默认值为 1,仅可选 1 或者 2。
    margin(float)- 默认值为 1
    weight(Tensor)- 为每个类别的 loss 设置权值。weight 必须是 float 类型的 tensor,其长度要于类别 C 一致,即每一个类别都要设置有 weight。
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

    TripletMarginLoss

    torch.nn.TripletMarginLoss(margin=1.0, p=2, eps=1e-06, swap=False, size_average=None,reduce=None, reduction=‘elementwise_mean’)

    功能:
    计算三元组损失,人脸验证中常用。
    参数:
    margin(float)- 默认值为 1
    p(int)- The norm degree ,默认值为 2
    swap(float)–是否swap
    size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
    reduce(bool)- 返回值是否为标量,默认为 True。

  • 相关阅读:
    iptables规则表及规则链及语法
    【分布式锁篇】Redisson详解
    关于SSA算法中矩阵的3种运算:转置、求逆、相乘
    【深度学习 AIGC】stable diffusion webUI 使用过程,参数设置,教程,使用方法
    Kafka Stream 学习笔记-5 process api
    阿里云容器镜像服务的运维总结
    21.6 Python 构建ARP中间人数据包
    家政按摩预约小程序app应用场景功能介绍
    ue5打包失败与优化项目
    文件操作 和 IO
  • 原文地址:https://blog.csdn.net/qq1198768105/article/details/126102014