pytorch代码-图像分类损失函数

本文主要是实践代码篇,所以不会贴出太多理论知识,但是也会贴上理论解释的一些博文,对理论有兴趣的可以去看看

代码来源

本文代码来自:基于pytorch实现的图像分类源码
代码实践示例:使用Pytorch实现图像花朵分类

图像分类损失

  • CrossEntropyLoss
import torch
import torch.nn as nn
class CrossEntropyLoss(nn.Module):
    def __init__(self, label_smoothing: float = 0.0, weight: torch.Tensor = None):
        super(CrossEntropyLoss, self).__init__()
        self.cross_entropy = nn.CrossEntropyLoss(weight=weight, label_smoothing=label_smoothing)
    
    def forward(self, input: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
        return self.cross_entropy(input, target)
其中label_smoothing是标签平滑的值,weight是每个类别的类别权重。
假设有三个类别,我想设定类别权重为 0.5,0.8,1.5
那么代码就是:
l = CrossEntropyLoss(weight=torch.fromnumpy(np.array([0.5,0.8,1.5])))
  • FocalLoss
import torch
import torch.nn as nn
import torch.nn.functional as F
class FocalLoss(nn.Module):
    def __init__(self, label_smoothing:float = 0.0, weight: torch.Tensor = None, gamma:float = 2.0):
        super(FocalLoss, self).__init__()
        self.label_smoothing = label_smoothing
        self.weight = weight
        self.gamma = gamma
    
    def forward(self, input: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
        target_onehot = F.one_hot(target, num_classes=input.size(1))
        target_onehot_labelsmoothing = torch.clamp(target_onehot.float(), min=self.label_smoothing/(input.size(1)-1), max=1.0-self.label_smoothing)
        input_softmax = F.softmax(input, dim=1) + 1e-7
        input_logsoftmax = torch.log(input_softmax)
        ce = -1 * input_logsoftmax * target_onehot_labelsmoothing
        fl = torch.pow((1 - input_softmax), self.gamma) * ce
        fl = fl.sum(1) * self.weight[target.long()]
        return fl.mean()
我们这个focalloss是支持标签平滑的。
其中label_smoothing是标签平滑的值,weight是每个类别的类别权重(可以理解为二分类focalloss中的alpha,因为alpha就是调节样本的平衡度),。
假设有三个类别,我想设定类别权重为 0.5,0.8,1.5
那么代码就是:
l = FocalLoss(weight=torch.fromnumpy(np.array([0.5,0.8,1.5])))
  • PolyLoss
import torch
import torch.nn as nn
import torch.nn.functional as F
class PolyLoss(nn.Module):
    """
    PolyLoss: A Polynomial Expansion Perspective of Classification Loss Functions
    
    """
    def __init__(self, label_smoothing: float = 0.0, weight: torch.Tensor = None, epsilon=2.0):
        super().__init__()
        self.epsilon = epsilon
        self.label_smoothing = label_smoothing
        self.weight = weight

    def forward(self, outputs, targets):
        ce = F.cross_entropy(outputs, targets, label_smoothing=self.label_smoothing, weight=self.weight)
        pt = F.one_hot(targets, outputs.size()[1]) * F.softmax(outputs, 1)

        return (ce + self.epsilon * (1.0 - pt.sum(dim=1))).mean()
其中label_smoothing是标签平滑的值,weight是每个类别的类别权重。
假设有三个类别,我想设定类别权重为 0.5,0.8,1.5
那么代码就是:
l = PolyLoss(weight=torch.fromnumpy(np.array([0.5,0.8,1.5])))

最后

可能有小伙伴不知道该如何确定类别的权重,一般出现需要设定类别权重的两种情况:

  1. 类别不平衡
    对于这种情况,基本上都是使用sklearn中的compute_class_weight方法进行计算每个类别对应的权重.
  2. 类别基本平衡,但是某个类别准确率相对比较低
    对于这种情况,你需要手动设定weight,你需要可视化测试集的每个类别的识别情况,再根据那个类别精度比较低,可以适当调高这个类别的权重,就等于让模型更多的注意到这个类别的loss进行优化。

当然也有小伙伴可能代码能力比较差,但是不用怕,这个代码已经帮你们实现上述的需求,还有更加丰富的可视化和功能,有需要可以使用一下。这个代码的使用示例在本博客开头代码来源中有链接,有整个操作流程。

你可能感兴趣的:(pytorch,分类,深度学习,人工智能,python)