pytorch中常用损失函数总结

本文详细介绍了PyTorch中几种常见的损失函数,包括BCELoss、BCEWithLogitsLoss、多分类交叉熵损失(NLLLoss和CrossEntropyLoss)以及FocalLoss。BCELoss适用于二分类问题,BCEWithLogitsLoss则整合了sigmoid激活函数。对于多分类,可以使用NLLLoss和CrossEntropyLoss,后者更加便捷。FocalLoss通过调整权重,解决了类别不平衡的问题,尤其适合于目标检测等任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

 本文主要介绍pytorch中常用的损失函数API的使用。


1. 分类损失

1.1. nn.BCELoss()

在这里插入图片描述
 nn.BCELoss()用于计算二分类问题,使用时采用默认初始化即可,即reduction='mean’是返回loss在所有样本上的均值。在forward方法中,所接受的 input和target必须一样的shape,且target是one-hot编码,而input需提前经过sigmoid处理。

from math import log
import torch
import torch.nn as nn
import torch.nn.functional as F

# 二元交叉熵损失函数,只能处理二分类问题
# 假设处理 二分类问题,且批次=2
input = torch.Tensor([[-1,1],[1,2]]) # input: [2,2]
input = input.sigmoid()                                
# 转成one-hot
target = torch.Tensor([0,1])         # shape:[2]
onehot_target = torch.eye(2)[target.long(), :]

Loss = nn.BCELoss()                  # 采用默认初始化
loss1 = Loss(input, onehot_target)
loss2 = F.binary_cross_entropy(input, onehot_target)  # 1.0167

1.2. nn.BCEWithLogitsLoss()

 该损失函数就是集成了sigmoid的处理,即此时input是直接网络输出即可,不必人为加sigmoid处理。

from math import log
import torch
import torch.nn as nn
import torch.nn.functional as F

# 二元交叉熵损失函数,只能处理二分类问题
# 假设处理 二分类问题,且批次=2
input = torch.Tensor([[-1,1],[1,2]]) # input: [2,2]
# 转成one-hot
target = torch.Tensor([0,1])         # shape:[2]
onehot_target = torch.eye(2)[target.long(), :]

Loss = nn.BCEWithLogitsLoss()                  # 采用默认初始化
loss1 = Loss(input, onehot_target)
loss2 = F.binary_cross_entropy_with_logits(input, onehot_target)

print(loss1, loss2)   # [1.0167]

1.3. 多分类交叉熵损失函数

 1)在解决多分类问题时,公式如下:
在这里插入图片描述
 其中N是总样本个数,K是类别,pic表示第i个样本所属第c个类别。这么说比较抽象,假设现在需要手动实现上述公式的代码: 假设有3个样本(N=3),其中每个p假设经过softmax处理,概率和为1,并将label转成one-hot编码。
在这里插入图片描述
 首先不要考虑最外层的求和符号,先计算内层的求和计算:L1,L2,L3,在计算外层的求和符号即可。
在这里插入图片描述

from math import log
import torch
import torch.nn as nn
import torch.nn.functional as F

p = torch.Tensor([[0.2,0.3,0.5],[0.1,0.7,0.2],[0.4,0.5,0.1]])
label = torch.Tensor([0,1,2])
onehot = torch.eye(3)[label.long(), :]
# 分别计算每个样本的交叉熵
p = torch.log(p)            # 取对数
loss = torch.sum(onehot * p)# 对应元素相乘并求和

# 在计算外层求和符号
loss = -loss / p.shape[0]
print(loss)          # 1.4429

 2)为了简化上述流程(label需one-hot=),torch用==nn.NLLLoss()==其进行了封装,将上述代码简化:

    from math import log
    import torch
    import torch.nn as nn
    import torch.nn.functional as F

    Loss = nn.NLLLoss()

    p = torch.Tensor([[0.2,0.3,0.5],[0.1,0.7,0.2],[0.4,0.5,0.1]])
    label = torch.Tensor([0,1,2]).long()
    #onehot = torch.eye(3)[label.long(), :]
    # 分别计算每个样本的交叉熵
    p = torch.log(p)            # 取对数
    loss = Loss(p, label)
    #loss = torch.sum(onehot * p)# 对应元素相乘并求和

    # 在计算外层求和符号
    #loss = -loss / p.shape[0]
    print(loss)          # 1.4429

 3)上述过程还是不够简化,因为p需要softmax+log操作,于是,torch进一步封装,就是:
在这里插入图片描述
 先不必管参数,直接使用:

from math import log
import torch
import torch.nn as nn
import torch.nn.functional as F

p = torch.randn(4,3)   # 网络直接输出,没有经过Softmax
label = torch.Tensor([0,1,2,0]).long()  #
# 首先拿普通方法计算下
log_p = F.log_softmax(p)
Loss = nn.NLLLoss()
loss1 = Loss(log_p, label)  
# 用CrossEP计算下
Loss = nn.CrossEntropyLoss()
loss2 = Loss(p, label)
print(loss1, loss2)    #二者结果一致

简单做下总结: 交叉熵损失函数:log + softmax + one-hot的集大成者,此时pred只需是[N,C]未经Softmax处理的,label只需是[N]里面元素是正常类别标签即可。然后传入API就能得出交叉熵损失
4)当然,这里有个额外参数需注意下:ignore_index,作用是忽略某个类别的损失。比如设置为0,就是去掉0这部分的损失值,并在非0元素上做损失的平均。

    from math import log
    import torch
    import torch.nn as nn
    import torch.nn.functional as F

    p = torch.Tensor([[0.1, 0.2, 0.3],[0.4, 0.5, 0.6],[0.1,0.2,0.3]])   #[2,3]
    label = torch.Tensor([0, 1, 1]).long()                   # [2]

    # 现在假设去掉标签为0的损失
    Loss = nn.CrossEntropyLoss(ignore_index=0)
    loss3 = Loss(p, label)
    print(loss3)            # 1.1019
    print('验证ignore_index')
    p = F.softmax(p)        # 对p进行softmax
    onehot = torch.eye(3)[label.long(), :]
    # 分别计算每个样本的交叉熵
    p = torch.log(p)
    v = (onehot * p)
    loss = torch.sum(v[1:])  # 去掉标签为0的损失
    # 在计算外层求和符号
    loss = -loss / 2            # 2个非0,故/2
    print(loss)  #

1.4.Focal_loss

 介绍完交叉熵损失后,不得不介绍下常用的Focal loss。首先看下focal loss的公式:
在这里插入图片描述
在这里插入图片描述
 从公式上可以看出,实现focal loss首先实现CE(pt),即二维交叉熵损失函数,可以直接采用自带sigmoid操作的nn.BCEWithLogitsLoss(),且target需要one-hot编码。
 在有了CE后,需要单独求下pt即可,注意此处需要人为加上sigmoid! 另外,论文中alpha_t的求解和pt一样:
在这里插入图片描述

这里贴下focal loss经典实现:

import torch
from torch import nn
import torch.nn.functional as F

class FocalLoss(nn.Module):
    def __init__(self,alpha=0.25,gamma=2.0,reduce='sum'):
        super(FocalLoss,self).__init__()
        self.alpha = alpha
        self.gamma = gamma
        self.reduce = reduce

    def forward(self,classifications,targets):  
    	# classifcation:[N,K]
    	# targets: [N,K]的one-hot编码
        alpha = self.alpha
        gamma = self.gamma
        classifications = classifications.view(-1)  # 不经过sigmoid的classification;
        targets = targets.view(-1)                  # 应该是 one-hot
        # ce_loss: 对应公式中 -log(pt),也就是普通的 交叉熵损失;--> 该函数接收未经sigmoid的函数;
        ce_loss = F.binary_cross_entropy_with_logits(classifications, targets.float(), reduction="none")
        #focal loss
        p = torch.sigmoid(classifications)                # 经过sigmoid
        p_t = p * targets + (1 - p) * (1 - targets)       #  计算pt
        loss = ce_loss * ((1 - p_t) ** gamma)             # -log(pt) * (1-pt) ** ganmma
        if alpha >= 0:
        	# 对应公式中alpha_t控制损失的权重
            alpha_t = alpha * targets + (1 - alpha) * (1 - targets) # 和pt求解过程一样
            loss = alpha_t * loss                         # 最终focal loss
        if self.reduce=='sum':
            loss = loss.sum()
        elif self.reduce=='mean':
            loss = loss.mean()
        else:
            raise ValueError('reduce type is wrong!')
        return loss

2. 回归损失

<think>好的,我现在需要回答用户关于PyTorch损失函数列表及使用方法的问题。首先,我得回忆一下PyTorch损失函数相关文档和常用内容。用户提到了几个引用,其中引用[1]和[3]直接涉及损失函数,引用[2]和[4]可能涉及其他函数和可视化,但用户的问题集中在损失函数上。 首先,我应该列出常用损失函数,比如均方差损失(MSELoss)、交叉熵损失(CrossEntropyLoss)、二元交叉熵(BCELoss)、L1损失等。需要确保每个函数的使用场景和示例正确。例如,MSELoss用于回归任务,CrossEntropyLoss用于多分类,BCELoss用于二分类或概率预测。 然后要注意用户提到的内置损失函数,要说明这些函数在torch.nn模块中的位置,比如通过导入nn模块来使用。同时,可能需要提到如何调用这些函数,比如实例化损失函数对象,然后计算损失值。例如,criterion = nn.MSELoss(),然后loss = criterion(output, target)。 接下来,需要注意每个损失函数的参数,比如CrossEntropyLoss是否需要logits输入,或者是否自动应用Softmax。比如,CrossEntropyLoss的输入通常是未经归一化的原始分数(logits),而目标标签是类别索引。而BCELoss则需要输入经过Sigmoid处理后的概率值,或者结合使用BCEWithLogitsLoss来避免数值不稳定。 此外,用户可能对每个损失函数的数学表达式感兴趣,根据系统级指令,行内公式需要用$...$,独立公式用$$...$$。例如,均方差损失的公式是$\text{MSE} = \frac{1}{n}\sum_{i=1}^n(y_i - \hat{y}_i)^2$,而交叉熵的公式可能需要独立成段。 还需要检查是否有遗漏的常用损失函数,比如Huber损失(SmoothL1Loss)、KL散度损失、MarginRankingLoss、TripletMarginLoss等。这些可能在引用中没有提到,但属于PyTorch的内置函数,需要补充。 另外,用户可能关心如何选择合适的损失函数,比如分类任务用交叉熵,回归用MSE或MAE,序列生成用NLLLoss等。这部分可以作为使用建议。 同时,要注意引用用户提供的参考内容,比如引用[1]提到均方差损失函数,引用[3]补充了CrossEntropyLoss和多分类的情况,以及正则化技术,但用户的问题主要聚焦在损失函数本身,所以可能需要简要提及正则化或优化器的相关内容,但重点还是损失函数。 最后,根据系统指令,生成相关问题。可能的问题包括损失函数的选择依据、如何自定义损失函数、多标签分类用什么损失函数损失函数与优化器的关系,以及如何可视化损失函数曲线,这可以结合引用[4]提到的TensorBoard。 需要确保所有数学表达式的格式正确,比如变量用斜体,公式正确用LaTeX语法。例如,交叉熵损失函数的公式应该正确呈现,可能需要独立成段: $$L = -\sum_{c=1}^M y_c \log(p_c)$$ 其中,$y_c$是真实标签的one-hot表示,$p_c$是预测概率。 另外,要避免错误,比如混淆BCELoss和BCEWithLogitsLoss的区别,或者CrossEntropyLoss是否需要手动应用Softmax。需要确认PyTorch的文档,确保正确性。 总结步骤: 1. 分类整理常用损失函数,包括名称、用途、公式、代码示例。 2. 确保每个部分的LaTeX格式正确,行内公式用$,独立公式用$$。 3. 引用用户提供的参考文献,比如引用[1]、[3]。 4. 生成相关问题,涵盖选择、自定义、多标签、优化器和可视化等方面。 5. 检查回答结构是否清晰,是否符合用户的要求,是否真实可靠。 现在需要将这些思路组织成结构化的回答,分点列出损失函数,每个函数包含说明、公式、示例代码。然后给出使用建议和相关问题。</think>以下是PyTorch常用损失函数的列表及其使用方法,结合应用场景和代码示例说明: --- ### 一、常用损失函数列表 1. **均方差损失(MSE Loss)** - **用途**:回归任务(如预测房价、温度)。 - **公式**: $$\text{MSE} = \frac{1}{n}\sum_{i=1}^n(y_i - \hat{y}_i)^2$$ - **代码示例**: ```python criterion = nn.MSELoss() loss = criterion(output, target) ``` 2. **交叉熵损失(CrossEntropyLoss)** - **用途**:多分类任务(如图像分类)。 - **公式**: $$L = -\sum_{c=1}^M y_c \log(p_c)$$ 其中$p_c$为预测概率,$y_c$为真实标签的one-hot编码。 - **代码示例**: ```python criterion = nn.CrossEntropyLoss() # 输入为logits(无需手动Softmax) loss = criterion(output, target) # target为类别索引,非one-hot ``` 3. **二元交叉熵损失(BCELoss)** - **用途**:二分类任务(如垃圾邮件检测)。 - **公式**: $$L = -\frac{1}{n}\sum_{i=1}^n \left[y_i \log(\hat{y}_i) + (1-y_i)\log(1-\hat{y}_i)\right]$$ - **代码示例**: ```python criterion = nn.BCELoss() # 输入需经过Sigmoid probabilities = torch.sigmoid(output) loss = criterion(probabilities, target) ``` 4. **负对数似然损失(NLLLoss)** - **用途**:与LogSoftmax结合用于多分类(如语言模型)。 - **公式**: $$L = -\log(p_{y})$$ $p_{y}$为目标类别的预测概率。 - **代码示例**: ```python m = nn.LogSoftmax(dim=1) criterion = nn.NLLLoss() loss = criterion(m(output), target) ``` 5. **Huber损失(SmoothL1Loss)** - **用途**:对异常值鲁棒的回归任务。 - **公式**: $$L = \begin{cases} 0.5(y - \hat{y})^2 & \text{if } |y-\hat{y}| < 1 \\ |y-\hat{y}| - 0.5 & \text{otherwise} \end{cases}$$ - **代码示例**: ```python criterion = nn.SmoothL1Loss() loss = criterion(output, target) ``` --- ### 二、使用建议 - **分类任务**:优先使用`CrossEntropyLoss`(多分类)或`BCEWithLogitsLoss`(二分类,无需手动Sigmoid)[^3]。 - **回归任务**:根据数据特性选择`MSELoss`(平滑数据)或`SmoothL1Loss`(含异常值)。 - **概率匹配**:使用`KLDivLoss`(如生成对抗网络)。 --- ### 三、完整列表与扩展 PyTorch内置损失函数还包括: - `nn.BCEWithLogitsLoss`(二分类,自动Sigmoid) - `nn.MultiLabelSoftMarginLoss`(多标签分类) - `nn.TripletMarginLoss`(度量学习) - `nn.CosineEmbeddingLoss`(相似性学习) 可通过官方文档查看全部损失函数:[PyTorch Loss Functions](https://pytorch.org/docs/stable/nn.html#loss-functions)[^1][^3]。 --- ### 四、代码示例(多分类任务) ```python import torch import torch.nn as nn # 模型输出(未经Softmax的logits) output = torch.randn(3, 5) # 3个样本,5个类别 target = torch.tensor([1, 0, 4]) # 真实类别索引 # 计算交叉熵损失 criterion = nn.CrossEntropyLoss() loss = criterion(output, target) print(loss.item()) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值