• 【pytorch】Loss Function


    1 Loss 介绍

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

    Loss function,即损失函数:用于定义单个训练样本与真实值之间的误差;
    Cost function,即代价函数:用于定义单个批次/整个训练集样本与真实值之间的误差;
    Objective function,即目标函数:泛指任意可以被优化的函数。

    KL散度 = 交叉熵 - 熵

    回归损失:用于预测连续的值。如预测房价、年龄等。
    分类损失:用于预测离散的值。如图像分类,语义分割等。
    排序损失:用于预测输入数据之间的相对距离。如行人重识别。

    2 常见 Loss

    L1 loss

    L o s s ( p r e d , y ) = ∣ y − p r e d ∣ Loss( pred , y ) = | y - pred | Loss(pred,y)=ypred

    import torch
    input = torch.randn(3, 5, requires_grad=True)
    target = torch.randn(3, 5)
    mae_loss = torch.nn.L1Loss()
    output = mae_loss(input, target)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    等价于

    for i in range(3):
    	for j in range(5):
    		result += abs(input[i][j] - target[i][j])
    result /= 15
    
    • 1
    • 2
    • 3
    • 4

    L2 loss

    L o s s ( p r e d , y ) = ∑ ∣ y − p r e d ∣ 2 Loss( pred , y ) = \sum| y - pred |^2 Loss(pred,y)=ypred2

    input = torch.randn(3, 5, requires_grad=True)
    target = torch.randn(3, 5)
    mse_loss = torch.nn.MSELoss()
    output = mse_loss(input, target)
    
    • 1
    • 2
    • 3
    • 4

    等价于

    for i in range(3):
    	for j in range(5):
    		result += (input[i][j] - target[i][j])**2
    result /= 15
    
    • 1
    • 2
    • 3
    • 4

    Negative Log-Likelihood(NLL)

    它的特性是惩罚预测准确而预测概率不高的情况

    l o s s ( p r e d , y ) = − ( l o g p r e d ) loss( pred, y) = - (log pred) loss(pred,y)=(logpred)

    注:NLL 要求网络最后一层使用 softmax 作为激活函数。通过 softmax 将输出值映射为每个类别的概率值。

    # size of input (N x C) is = 3 x 5
    input = torch.randn(3, 5, requires_grad=True)
    # every element in target should have 0 <= value < C
    target = torch.tensor([1, 0, 4])
    m = torch.nn.LogSoftmax(dim=1)
    nll_loss = torch.nn.NLLLoss()
    output = nll_loss(m(input), target)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    补充

    Softmax 函数常用的用法是指定参数 dim
    1)dim=0:对每一列
    2)dim=1:对每一行

    LogSoftmax 对 softmax 的结果进行 log,即 Log(Softmax(x))

    logsoftmax 解决函数 overflow 和 underflow,加快运算速度,提高数据稳性定。
    防止溢出

    Binary Cross-Entropy

    import torch
    a = torch.randn(3,3)
    target = torch.FloatTensor([[0,1,1],
                                [0,0,1],
                                [1,0,1]])
    
    "compute torch without sigmoid"
    loss2 = torch.nn.BCEWithLogitsLoss()
    print(loss2(a, target))
    
    "compute torch with sigmoid"
    s = a.sigmoid()
    loss1 = torch.nn.BCELoss()
    print(loss1(s, target))
    
    "compute yourself"
    loss_mul = 0
    for i in range(3):
        for j in range(3):
            x = target[i][j]*torch.log(s[i][j]) + (1-target[i][j])*torch.log(1-s[i][j])
            loss_mul += x
    
    print(-loss_mul/9)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    Cross-Entropy

    交叉熵损失函数的与 logsoftmax+NLL 损失函数结果一致

    l o s s ( p r e d , y ) = − ∑ y l o g p r e d loss( pred, y) = - \sum ylogpred loss(pred,y)=ylogpred

    input = torch.randn(3, 5, requires_grad=True)
    target = torch.empty(3, dtype=torch.long).random_(5) # 0~4
    cross_entropy_loss = torch.nn.CrossEntropyLoss()
    output = cross_entropy_loss(input, target)
    
    • 1
    • 2
    • 3
    • 4

    等价于

    m = torch.nn.LogSoftmax(dim=1)
    nll_loss = torch.nn.NLLLoss()
    output = nll_loss(m(input), target)
    
    • 1
    • 2
    • 3

    Hinge Embedding

    l o s s ( p r e d , y ) = m a x ( 0 , 1 − y ∗ p r e d ) loss(pred, y) = max(0, 1 - y * pred ) loss(pred,y)=max(0,1ypred)

    其中 y 为 1 或 -1。

    应用场景:

    • 分类问题,特别是在确定两个输入是否不同或相似时。
    • 学习非线性嵌入或半监督学习任务。
    input = torch.randn(3, 5, requires_grad=True)
    target = torch.randn(3, 5)
    hinge_loss = torch.nn.HingeEmbeddingLoss()
    output = hinge_loss(input, target)
    
    • 1
    • 2
    • 3
    • 4

    Margin Ranking Loss

    l o s s ( p r e d , y ) = m a x ( 0 , − y ∗ ( p r e d 1 − p r e d 2 ) + m a r g i n ) loss(pred, y) = max(0, -y*(pred1 - pred2) + margin) loss(pred,y)=max(0,y(pred1pred2)+margin)
    标签张量 y(包含 1 或 -1)。

    当 y == 1 时,第一个输入将被假定为更大的值。它将排名高于第二个输入。如果 y == -1,则第二个输入将排名更高。

    应用场景:排名问题

    input_one = torch.randn(3, requires_grad=True)
    input_two = torch.randn(3, requires_grad=True)
    target = torch.randn(3).sign() # 1 or -1
    
    ranking_loss = torch.nn.MarginRankingLoss()
    output = ranking_loss(input_one, input_two, target)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Triplet Margin Loss

    L o s s ( a , p , n ) = m a x 0 , d ( a i , p i ) − d ( a i , n i ) + m a r g i n Loss (a, p, n) = max{0, d(ai, pi) - d(ai, ni) + margin} Loss(a,p,n)=max0,d(ai,pi)d(ai,ni)+margin

    三元组由 a (anchor),p (正样本) 和 n (负样本)组成.

    应用场景:

    • 确定样本之间的相对相似性
    • 用于基于内容的检索问题
    anchor = torch.randn(100, 128, requires_grad=True)
    positive = torch.randn(100, 128, requires_grad=True)
    negative = torch.randn(100, 128, requires_grad=True)
    triplet_margin_loss = torch.nn.TripletMarginLoss(margin=1.0, p=2)
    output = triplet_margin_loss(anchor, positive, negative)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    图片来源 一文理解Ranking Loss/Margin Loss/Triplet Loss

    KL Divergence Loss

    计算两个概率分布之间的差异。
    l o s s ( p r e d , y ) = y ∗ ( l o g y − p r e d ) loss (pred, y) = y*( log y - pred) loss(pred,y)=y(logypred)
    输出表示两个概率分布的接近程度。如果预测的概率分布与真实的概率分布相差很远,就会导致很大的损失。如果 KL Divergence 的值为零,则表示概率分布相同。

    应用场景:

    • 逼近复杂函数
    • 多类分类任务
    • 确保预测的分布与训练数据的分布相似
    input = torch.randn(2, 3, requires_grad=True)
    target = torch.randn(2, 3)
    kl_loss = torch.nn.KLDivLoss(reduction = 'batchmean')
    output = kl_loss(input, target)
    
    • 1
    • 2
    • 3
    • 4

    3 Loss 设计

    神经网络中,设计loss function有哪些技巧?

    作者:Alan Huang
    https://www.zhihu.com/question/268105631/answer/335246543

    Multi-task learning 还需要解决的是 Gradient domination 的问题。这个问题产生的原因是不同任务的 loss 的梯度相差过大, 导致梯度小的 loss 在训练过程中被梯度大的 loss 所带走。

    如果一开始就给不同的 Loss 进行加权, 让它们有相近的梯度, 是不是就能训练的好呢? 结果往往不是这样的。 不同的loss, 他们的梯度在训练过程中变化情况也是不一样的;而且不同的 loss, 在梯度值相同的时候, 它们在 task 上的表现也是不同的。在训练开始的时候,虽然 balance 了, 但是随着训练过程的进行, 中间又发生 gradient domination 了。 所以要想解决这个问题, 还是要合适地对不同 loss 做合适的均衡。

    如果A和B单独训练, 他们在收敛的时候的梯度大小分别记为 Grad_a, Grad_b, 那么我们只需要在两个任务一起训练的时候, 分别用各自梯度的倒数(1/Grad_a, 1/Grad_b)对两个任务做平衡, 然后统一乘一个scalar就可以了。(根据单任务的收敛时候的loss梯度去确定multi-task训练中不同任务的权重。)

    作者:刘诗昆
    https://www.zhihu.com/question/268105631/answer/333738561

    Gradient balancing method 一定需要建立在网络设计足够好的基础上,不然光凭平衡梯度并不会对网络泛化能力有着显著的改变。

    4 softmax 及其变体

    声明:学习笔记,摘抄来自网络

    在这里插入图片描述
    soft softmax loss

    在这里插入图片描述
    知识蒸馏里面的

    Large-Margin Softmax Loss(L-softmax)
    m是一个控制距离的变量,它越大训练会变得越困难,因为类内不可能无限紧凑
    在这里插入图片描述
    在这里插入图片描述

    作者的实现是通过一个 LargeMargin 全连接层+softmax loss来共同实现,可参考代码。

    angular softmax loss(A-softmax)

    large margin softmax loss的基础上添加了两个限制条件||W||=1和b=0,使得预测仅取决于W和x之间的角度θ

    L2-constrained softmax loss

    在这里插入图片描述

    上面式就是将其归一化到固定值α。实际训练的时候都不需要修改代码,只需要添加L2-norm层与scale层,如下图。

    在这里插入图片描述
    scale 更有利于优化

    additive margin softmax loss
    在这里插入图片描述
    在这里插入图片描述
    就是把L-Softmax的乘法改成了减法,同时加上了尺度因子s。作者这样改变之后前向后向传播变得更加简单。其中W和f都是归一化过的,作者在论文中将m设为0.35。

    argface additive angular margin

    在这里插入图片描述

    在这里插入图片描述


    hardmax 中,真正最大的那个数,一定是以1(100%) 的概率被选出来,其他的值根本一点机会没有。但是在 softmax 中,所有的值都有机会被作为最大值选出来。只不过,由于 softmax 的 “马太效应”,次大的数,即使跟真正最大的那个数差别非常少,在概率上跟真正最大的数相比也小了很多。

    “softmax 的作用是把 一个序列,变成概率。” 这个概率不是别的,而是被选为 max 的概率。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    cross entropy 是用来衡量两个概率分布之间的距离的,softmax能把一切转换成概率分布,那么自然二者经常在一起使用。但是你只需要简单推导一下,就会发现,softmax + cross entropy 就好像

    “往东走五米,再往西走十米”,

    在这里插入图片描述
    在这里插入图片描述

    cross_entropy = log_softmax + nll_loss

    在这里插入图片描述

    作者:董鑫
    链接:https://www.zhihu.com/question/294679135/answer/885285177
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    5 Loss 异常

    来自 loss问题汇总(不收敛、震荡、nan)

    在这里插入图片描述
    错误数据

    通过设置 batch_size = 1,shuffle = False 一步一步地将sample定位到了所有可能的脏数据,删掉

    弱化场景,将你的样本简化,各个学习率等参数采用典型配置,比如10万样本都是同一张复制的,让这个网络去拟合,如果有问题,则是网络的问题。否则则是各个参数的问题。

    附录A——激活函数

    A1 mish

    在这里插入图片描述
    在这里插入图片描述

    def mish(x):
        return x * torch.tanh(torch.nn.functional.softplus(x))
    x = torch.arange(start=-10, end=10, step=0.01)
    y = mish(x) 
    plt.plot(x.numpy(), y.numpy())
    plt.title("mish")
    plt.savefig("mish.png")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    机器学习 之 客户分群案例
    WireGuard简单配置
    YOLOV2详解
    【JVM】类加载的过程
    Go语言map底层分析
    STM32物联网项目-GPRS模块通信编程
    【centos7】centos7卸载gitlab
    尚医通 (六) --------- 集成 Swagger
    java正则表达式
    如何批量图片重命名不同名字?
  • 原文地址:https://blog.csdn.net/bryant_meng/article/details/126347943