常用的损失函数

2023-05-16

pytorch的源码: torch.nn — PyTorch 1.11.0 documentation

jittor的源码:jittor.nn — Jittor 1.3.2.6 文档 (tsinghua.edu.cn)

paddle的实现:Paddle框架下常用损失函数总结和实现 - 飞桨AI Studio (baidu.com)

目录

一、回归损失函数

1.1 MSE[均方误差Mean Square Error,二次损失Quadratic Loss,L2损失L2 Loss]

1.2 MAE[平均绝对误差Mean Absolute Error,L1损失L1 Loss]   

1.3 Huber Loss[平滑的平均绝对误差]

1.4 Log-Cosh Loss[预测误差的双曲余弦的对数]

1.5 Quantile Loss[分位数损失]

二、分类损失函数

2.1  Cross Entropy Loss(CE)[Log Loss、交叉熵损失]

2.1.1 Binary Cross Entropy Loss

2.1.2  Binary Cross Entropy With Logits Loss

2.2 Focal Loss

2.3 Relative Entropy [相对熵、KL散度(Kullback-Leibler divergence)]

2.4 Exponential Loss [指数损失] 

2.5 Hinge Loss [铰链损失、合页损失]


一、回归损失函数

1.1 MSE[均方误差Mean Square Error,二次损失Quadratic Loss,L2损失L2 Loss]

调用

jittor.nn.MSELoss()

源码

class MSELoss(Module):
    def __init__(self):
        pass
    def execute(self, output, target):
        return mse_loss(output, target)

def mse_loss(output, target):
    return (output-target).sqr().mean()

自定义实现如下

def mse(true, pred): 
    return np.sum((true - pred)**2)

损失范围为0至∞

如果离群点是会影响业务、而且是应该被检测到的异常值,那么我们应该使用MSE

1.2 MAE[平均绝对误差Mean Absolute Error,L1损失L1 Loss]   

调用

jittor.nn.L1Loss()

源码

class L1Loss(Module):
    def __init__(self):
        pass
    def execute(self, output, target):
        return l1_loss(output, target)

def l1_loss(output, target):
    return (output-target).abs().mean()

自定义实现

def mae(true, pred):
    return np.sum(np.abs(true - pred))

损失范围也是0到∞    

如果我们认为离群点仅仅代表数据损坏,那么我们应该选择MAE作为损失

1.3 Huber Loss[平滑的平均绝对误差]

调用

torch.nn.functional.huber_loss(input, target, reduction='mean', delta=1.0)

自定义实现如下

def huber(true, pred, delta):
    loss = np.where(np.abs(true-pred) < delta , 0.5*((true-pred)**2), delta*np.abs(true -     
             pred) - 0.5*(delta**2))
    return np.sum(loss)

当超参数(detail)趋近于0时,Huber Loss接近MAE,

当超参数(detail)趋近于∞时,Huber Loss接近MSE。


1.4 Log-Cosh Loss[预测误差的双曲余弦的对数]

         log(cosh(x))对于小的x来说,其大约等于 (x ** 2) / 2,而对于大的x来说,其大约等于 abs(x) - log(2)。这意味着'logcosh'的作用大部分与均方误差一样。它具有Huber Loss的所有优点,和Huber Loss不同之处在于,其处处二次可导。


自定义实现

def logcosh(input, target):
    loss = np.log(np.cosh(target - input))
    return np.sum(loss)

1.5 Quantile Loss[分位数损失]

        当我们有兴趣预测一个区间而不仅仅是预测一个点时,Quantile Loss函数就很有用。

        所谓的0.9分位数回归,就是希望回归曲线之下能够包含90%的数据点(y),这也是分位数的概念,分位数回归是把分位数的概念融入到普通的线性回归而已。

调用

loss = quantile_loss(pred, gt, 0.5)

实现

import paddle.fluid as fluid

places = fluid.CPUPlace()
exe = fluid.Executor(places)

def quantile_loss(pred, label, gamma):
    dist = fluid.layers.abs(pred - label)
    cond = fluid.layers.greater_than(pred, label)
    ie = fluid.layers.IfElse(cond)
    with ie.true_block():
        loss = ie.input(dist)
        loss = (1 - gamma) * loss
        ie.output(loss)
    with ie.false_block():
        loss = ie.input(dist)
        loss = gamma * loss
        ie.output(loss)
    loss = ie()[0] # 返回的是一个list
    loss = fluid.layers.reduce_mean(loss)
    return loss

quantile_program = fluid.Program()
with fluid.program_guard(quantile_program):
    pred = fluid.data('pred', shape=[4,1], dtype='float32')
    gt = fluid.data('gt', shape=[4,1], dtype='float32')
    loss = quantile_loss(pred, gt, 0.5)

二、分类损失函数

2.1  Cross Entropy Loss(CE)[Log Loss、交叉熵损失]

        交叉熵主要是用来判定实际的输出与期望的输出的接近程度。

        信息量:它是用来衡量一个事件的不确定性的;一个事件发生的概率越大,不确定性越小,则它所携带的信息量就越小。

        熵:它是用来衡量一个系统的混乱程度的,代表一个系统中信息量的总和;信息量总和越大,表明这个系统不确定性就越大。

        也叫Log Loss,两者等价,标签为{-1, 1}时为log loss, 标签为{0, 1}时为交叉熵。在做分类(具体几类)训练的时候是非常有用的。

调用

jittor.nn.CrossEntropyLoss(weight=None, ignore_index=None)

源码

class CrossEntropyLoss(Module):
    def __init__(self, weight=None, ignore_index=None):
        self.weight = weight
        self.ignore_index = ignore_index
        
    def execute(self, output, target):
        return cross_entropy_loss(output, target, self.weight, self.ignore_index)

def cross_entropy_loss(output, target, weight=None, ignore_index=None,reduction='sum'):
    if len(output.shape) == 4:
        c_dim = output.shape[1]
        output = output.transpose((0, 2, 3, 1))
        output = output.reshape((-1, c_dim))

    target = target.reshape((-1, ))
    target_weight = jt.ones(target.shape[0], dtype='float32')
    if weight is not None:
        target_weight = weight[target]
    if ignore_index is not None:
        target_weight = jt.ternary(
            target==ignore_index,
            jt.array(0).broadcast(target_weight),
            target_weight
        )
    
    target = target.broadcast(output, [1])
    target = target.index(1) == target
    
    output = output - output.max([1], keepdims=True)
    logsum = output.exp().sum(1).log()
    loss = (logsum - (output*target).sum(1)) * target_weight
    if reduction == 'sum':
        return loss.sum() / target_weight.sum()
    elif reduction == 'mean':
        return loss.mean() / target_weight.mean()
    else:
        return loss / target_weight

2.1.1 Binary Cross Entropy Loss

可视化理解Binary Cross-Entropy - 知乎 (zhihu.com)

调用

jittor.nn.BCELoss(weight=None, size_average=True)

源码

class BCELoss(Module):
    def __init__(self, weight=None, size_average=True):
        self.weight = weight
        self.size_average = size_average
    def execute(self, output, target):
        return bce_loss(output, target, self.weight, self.size_average)

def bce_loss(output, target, weight=None, size_average=True):
    loss = - (target * jt.log(jt.maximum(output, 1e-20)) + (1 - target) *     
             jt.log(jt.maximum(1 - output, 1e-20)))

    if weight is not None:
        loss *= weight
    
    if size_average:
        return loss.mean()
    else:
        return loss.sum()

2.1.2  Binary Cross Entropy With Logits Loss

        有一个(类)损失函数名字中带了with_logits. 而这里的logits指的是,该损失函数已经内部自带了计算logit的操作,无需在传入给这个loss函数之前手动使用sigmoid/softmax将之前网络的输入映射到[0,1]之间 

调用

jittor.nn.BCEWithLogitsLoss(weight=None, pos_weight=None, size_average=True)

torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='mean',         
                           pos_weight=None)

源码

class BCEWithLogitsLoss(Module):
    def __init__(self, weight=None, pos_weight=None, size_average=True):
        self.pos_weight = pos_weight
        self.weight = weight
        self.size_average = size_average

    def execute(self, output, target):
        return  binary_cross_entropy_with_logits(output,target,
                                                 self.weight,
                                                 self.pos_weight,
                                                 self.size_average)

def binary_cross_entropy_with_logits(output, target, weight=None, pos_weight=None,     
                                     size_average=True):
    # 将输入input张量每个元素的夹紧到区间 [min,max][min,max],并返回结果到一个新张量
    # x = x.maximum(min_v)
    max_val = jt.clamp(-output,min_v=0)
    if pos_weight is not None:
        log_weight = (pos_weight-1)*target + 1
        loss = (1-target)*output+(log_weight*(((-max_val).exp()+(-output -     
                max_val).exp()).log()+max_val))
    else:
        loss = (1-target)*output+max_val+((-max_val).exp()+(-output -max_val).exp()).log()
    if weight is not None:
        loss *=weight

    if size_average:
        return loss.mean()
    else:
        return loss.sum()

实例

loss = nn.BCEWithLogitsLoss()
input = torch.randn(3, requires_grad=True)
target = torch.empty(3).random_(2)
output = loss(input, target)
output.backward()

2.2 Focal Loss

        Focal loss的思路就是给损失加上权值,使当模型对样本的判断错误时,损失的权重更大,从而增加”困难样本“对模型的影响

#二分类情况:分别计算y_true为1处和y_true为0处的损失,相加
from keras import backend as K 
def focal_loss(gamma=2., alpha=0.25): 
    def focal_loss_fixed(y_true, y_pred): 
        pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred)) 
        pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))  
        return -K.sum(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1))-K.sum((1-alpha) * K.pow( pt_0, gamma) * K.log(1. - pt_0)) 
    return focal_loss_fixed
#多分类情况:计算y_true为1处的损失(不考虑y_true为0处的y_pred值)
from keras import backend as K 
def focal_loss(gamma=2.): 
    def focal_loss_fixed(y_true, y_pred): 
        pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred)) 
        return -K.sum( K.pow(1. - pt_1, gamma) * K.log(pt_1)) 
    return focal_loss_fixed

2.3 Relative Entropy [相对熵、KL散度(Kullback-Leibler divergence)]

        信息熵代表的是随机变量或整个系统的不确定性,熵越大,随机变量或系统的不确定性就越大。根据真实分布,我们能够找到一个最优策略,以最小的代价消除系统的不确定性,而这个代价大小就是信息熵,记住,信息熵衡量了系统的不确定性,而我们要消除这个不确定性,所要付出的【最小努力】(猜题次数、编码长度等)的大小就是信息熵。

         交叉熵,其用来衡量在给定的真实分布下,使用非真实分布所指定的策略消除系统的不确定性所需要付出的努力的大小。交叉熵越低,这个策略就越好,最低的交叉熵也就是使用了真实分布所计算出来的信息熵。因为此时交叉熵 = 信息熵。这也是为什么在机器学习中的分类算法中,我们总是最小化交叉熵,因为交叉熵越低,就证明由算法所产生的策略最接近最优策略,也间接证明我们算法所算出的非真实分布越接近真实分布。

         相对熵,其用来衡量两个取值为正的函数或概率分布之间的差异。现在,假设我们想知道某个策略和最优策略之间的差异,我们就可以用相对熵来衡量这两者之间的差异。即,相对熵 = 某个策略的交叉熵 - 信息熵(根据系统真实分布计算而得的信息熵,为最优策略)。

调用

torch.nn.KLDivLoss(size_average=None, reduce=None, reduction='mean', log_target=False)

torch.nn.functional.kl_div(input, target, size_average=None, reduce=None, reduction='mean',         
                           log_target=False)

实例

kl_loss = nn.KLDivLoss(reduction="batchmean")

# 输入应该是对数空间中的分布
input = F.log_softmax(torch.randn(3, 5, requires_grad=True))
# 对一批分布进行抽样。 通常这将来自数据集
target = F.softmax(torch.rand(3, 5))
output = kl_loss(input, target)

log_target = F.log_softmax(torch.rand(3, 5))
output = kl_loss(input, log_target, log_target=True)

2.4 Exponential Loss [指数损失] 

        对离群点、噪声非常敏感。主要用于 Adaboost 集成学习 算法,它是前向分步加法算法的特例,是一个加和模型。

        指数损失是0-1损失函数的一种代理函数。

        代码实现还未找到(待更新)。

2.5 Hinge Loss [铰链损失、合页损失]

        在机器学习中常用于"最大间隔(maximum-margin)"的分类任务中,如支持向量机SVM。尽管不可微,但它是一个凸函数,因此可以轻而易举地使用机器学习领域中常用的凸优化器。

        对于当前的一组分数,对应于不同的类别,我们希望属于真实类别的那个分数比其他的类别的分数要高,并且最好要高出一个margin,这样才是安全的。反映在这个函数中,就是0的那一项的取值范围,Syi表示的是xi样本的真实类别所得到的分数,而Sj指的是其他的类别的分数,如果真实类别的分数是最大的,且大一个margin 1,那么就表示满意,也就是说不惩罚,这一项的loss为0。如果不满足这一条件,我们用下面的一段,也就是Sj - Syi + 1, 1在这里是一个常数,可以使得函数连续起来,这个Sj - Syi表示,Syi,也就是真实样本的分数比别的少的越多,我们越不满意。

代码实现:kazuto1011/svm-pytorch: Linear SVM with PyTorch (github.com)

代码实现

output = model(x).squeeze()
weight = model.weight.squeeze()

loss = torch.mean(torch.clamp(1 - y * output, min=0))
loss += args.c * (weight.t() @ weight) / 2.0
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

常用的损失函数 的相关文章

随机推荐

  • 循环嵌套例题

    循环嵌套例题 1 例题1 span class token comment 代码 span span class token keyword for span span class token punctuation span span c
  • java实现学生信息管理(对象数组实现)

    java实现学生信息管理 xff08 对象数组实现 xff09 1 例题 实体类 学生类 id 姓名 xff0c 年龄 xff0c 性别 xff0c 成绩 需要使用数组保存学生信息 Student allStu 需要完成的方法 1 根据学生
  • java基础语法思维导图

    java从入门到放弃 简单总结之前的
  • 学生管理系统2.0 (可对学生数组扩容)

    学生管理系统2 0 可对学生数组扩容 1 用户可初始化数组长度 xff0c 不够用时可以扩充数组容量 尝试完成以下功能 实体类 学生类 id 姓名 xff0c 年龄 xff0c 性别 xff0c 成绩 需要使用数组保存学生信息 Studen
  • LinkedList和Set

    LinkedList和Set 1 LinkedList 1 1 LinkedList概述 底层存储数据是一个双向链表结构 自行车链子 就是一个生活中链表结构 xff0c 环环相扣 xff0c 替换 xff0c 拆除非常方便 1 2 Link
  • shiro与springboot整合

    Shiro 与 SpringBoot 的整合 1 创建SpringBoot工程 xff0c 导入依赖 span class token generics function span class token punctuation lt sp
  • Vue

    Author Thor Version 9 0 1 文章目录 一 Vue简介1 1 简介1 2 MVVM 模式的实现者 双向数据绑定模式1 3 其它 MVVM 实现者1 4 为什么要使用 Vue js1 5 Vue js 的两大核心要素1
  • android AudioRecord 音频录制 噪音消除

    android AudioRecord 音频录制 噪音消除 因为公司APP做适配 xff0c 一些低端机的噪音比较严重 xff0c 所以再一些低端机上做了简单除噪音功能 xff0c 1 xff0c 由于APP使用场景的限制 xff0c 所以
  • springboot 常用注解

    springboot 常用注解 在spring boot中 xff0c 摒弃了spring以往项目中大量繁琐的配置 xff0c 通过自身默认配置 xff0c 极大的降低了项目搭建的复杂度 在spring boot中 xff0c 大量注解的使
  • X86架构基本汇编指令详解

    文章目录 汇编指令伪指令1 MODEL2 STACK3 ENDP4 END 汇编指令1 MOV xff1a 将源操作数复制到目的操作数2 MOVZX 和 MOVSX3 XCHG 交换两个操作数内容4 INC 和 DEC5 ADD 和 SUB
  • 详解 C++ 对象模型

    文章目录 何为 C 43 43 对象模型 xff1f 基本 C 43 43 对象模型C 43 43 对象模型中加入单继承1 无重写的单继承2 有重写的单继承 C 43 43 对象模型中加入多继承C 43 43 对象模型中加入虚继承1 简单虚
  • Ubuntu 扩大/home磁盘分区

    在删除或重命名home目录之前 xff0c 千万确保你可以使用root账户 xff01 xff01 xff01 sudo 无用 xff01 xff01 xff01 根目录一共212G xff0c 已经使用了80 了 xff0c 其中130G
  • 正则表达式学习的个人小结

    正则表达式是对字符串的一种操作 xff0c 运用到JS中可以帮助我们去寻找符合要求的字符串 表单验证 http xff1a regexper com xff08 这个网站可以把正则表达式输入进去然后用图形显示出来 xff0c 因为是国外的网
  • ROS学习 一、Debian10安装ROS Noetic,解决rosdep update失败问题(更新一个可修改位置)

    目录 前言ROS安装1 添加ROS的apt源和key xff08 中科大源 xff09 2 apt安装ros noetic核心组件3 配置ROS的bash环境4 安装其他常用ROS依赖项5 解决python3 rosdep安装中出现的ros
  • windows动态链接库的使用,隐式调用(静态链接)和显示调用(动态链接)

    一 xff0c 动态链接库项目创建 dll工程内部架构 用VS2019创建动态链接库dll工程 初始会有如下几个文件 xff1a pch h和pch cpp与动态链接库功能无关 是用来保存多个文件时共同引用的头文件 xff0c 函数 xff
  • 在wsl2中安装CUDA

    1 先根据我之前的教程把wsl1升级到wsl2 wsl1升级到wsl2 夕阳之后的黑夜的博客 CSDN博客 2 打开Ubuntu xff0c 输入 uname r 确定内核 xff0c 安装CUDA需要内核 4 19 121 或更高 3 在
  • import torch 报错没有找到torch_python.dll

    conda install c anaconda intel openmp 运行上述代码就成功了
  • 在wsl2(Ubuntu20.04)中安装cudnn

    可以看cudnn的官方安装文档 xff1a 安装指南 NVIDIA 深度学习 cuDNN 文档 1 根据之前安装的cuda版本来下载安装对应的cudnn版本 cuDNN Archive NVIDIA Developer 2 比如我的cuda
  • 解决android opengl glReadPixels 慢的问题 三

    解决android opengl glReadPixels 慢的问题 三 使用2个pbo效率提上去了 xff0c 但是我手机分辨率是720p 或者1080p xff0c 我们手机相机使用一般是480x640 xff0c 这样通过gpu渲染到
  • 常用的损失函数

    pytorch的源码 xff1a torch nn PyTorch 1 11 0 documentation jittor的源码 xff1a jittor nn Jittor 1 3 2 6 文档 tsinghua edu cn paddl