首页IT科技yolo v3的损失函数(YOLOX改进之损失函数修改(上))

yolo v3的损失函数(YOLOX改进之损失函数修改(上))

时间2025-04-29 02:36:04分类IT科技浏览5013
导读:文章内容:如何在YOLOX官网代码中修改–置信度预测损失...

文章内容:如何在YOLOX官网代码中修改–置信度预测损失

环境:pytorch1.8

损失函数修改内容

(1)置信度预测损失更换:二元交叉熵损失替换为FocalLoss或者VariFocalLoss

(2)定位损失更换:IOU损失替换为GIOU             、CIOU                    、EIOU以及a-IOU系列

提示:使用之前可以先了解YOLOX及上述损失函数原理

参考链接

YOLOX官网链接:https://github.com/Megvii-BaseDetection/YOLOX

YOLOX原理解析(Bubbliiiing大佬版):https://blog.csdn.net/weixin_44791964/article/details/120476949

FocalLoss损失解析:https://cyqhn.blog.csdn.net/article/details/87343004

VariFocalLoss损失解析:https://blog.csdn.net/weixin_42096202/article/details/108567189

GIOU       、CIOU       、EIOU等:https://blog.csdn.net/neil3611244/article/details/113794197

a-IOU:https://blog.csdn.net/wjytbest/article/details/121513560

使用方法:直接替换即可

代码修改过程

1                    、置信度预测损失更换之FocalLoss(不需要创建新的py文件)

使用:直接在YOLOX-main/yolox/models/yolo_head.py的YOLOXHead类中创建focal_loss方法

(1)首先找到置信度预测损失计算位置loss_obj             ,并进行替换(位置在386-405行左右)

# loss_iou:定位损失;loss_obj:置信度预测损失;loss_cls:预测损失 loss_iou = ( self.iou_loss(bbox_preds.view(-1, 4)[fg_masks], reg_targets) ).sum() / num_fg #loss_obj = ( # self.bcewithlog_loss(obj_preds.view(-1, 1), obj_targets) #).sum() / num_fg loss_obj = ( self.focal_loss(obj_preds.sigmoid().view(-1, 1), obj_targets) ).sum() / num_fg loss_cls = ( self.bcewithlog_loss( cls_preds.view(-1, self.num_classes)[fg_masks], cls_targets ) ).sum() / num_fg

(2)创建focal_loss方法                    ,放到def get_l1_target(…)之前即可       ,代码如下:

def focal_loss(self, pred, gt): pos_inds = gt.eq(1).float() neg_inds = gt.eq(0).float() pos_loss = torch.log(pred+1e-5) * torch.pow(1 - pred, 2) * pos_inds * 0.75 neg_loss = torch.log(1 - pred+1e-5) * torch.pow(pred, 2) * neg_inds * 0.25 loss = -(pos_loss + neg_loss) return loss

2              、置信度预测损失更换之VariFocalLoss(代码较多       ,所以额外创建新的py文件)

步骤一:YOLOX-main/yolox/models文件夹下创建varifocalloss.py文件                    ,内容如下:

import torch.nn as nn import torch.nn.functional as F def reduce_loss(loss, reduction): """Reduce loss as specified. Args: loss (Tensor): Elementwise loss tensor. reduction (str): Options are "none", "mean" and "sum". Return: Tensor: Reduced loss tensor. """ reduction_enum = F._Reduction.get_enum(reduction) # none: 0, elementwise_mean:1, sum: 2 if reduction_enum == 0: return loss elif reduction_enum == 1: return loss.mean() elif reduction_enum == 2: return loss.sum() def weight_reduce_loss(loss, weight=None, reduction=mean, avg_factor=None): """Apply element-wise weight and reduce loss. Args: loss (Tensor): Element-wise loss. weight (Tensor): Element-wise weights. reduction (str): Same as built-in losses of PyTorch. avg_factor (float): Avarage factor when computing the mean of losses. Returns: Tensor: Processed loss values. """ # if weight is specified, apply element-wise weight if weight is not None: loss = loss * weight # if avg_factor is not specified, just reduce the loss if avg_factor is None: loss = reduce_loss(loss, reduction) else: # if reduction is mean, then average the loss by avg_factor if reduction == mean: loss = loss.sum() / avg_factor # if reduction is none, then do nothing, otherwise raise an error elif reduction != none: raise ValueError(avg_factor can not be used with reduction="sum") return loss def varifocal_loss(pred, target, weight=None, alpha=0.75, gamma=2.0, iou_weighted=True, reduction=mean, avg_factor=None): """`Varifocal Loss <https://arxiv.org/abs/2008.13367>`_ Args: pred (torch.Tensor): The prediction with shape (N, C), C is the number of classes target (torch.Tensor): The learning target of the iou-aware classification score with shape (N, C), C is the number of classes. weight (torch.Tensor, optional): The weight of loss for each prediction. Defaults to None. alpha (float, optional): A balance factor for the negative part of Varifocal Loss, which is different from the alpha of Focal Loss. Defaults to 0.75. gamma (float, optional): The gamma for calculating the modulating factor. Defaults to 2.0. iou_weighted (bool, optional): Whether to weight the loss of the positive example with the iou target. Defaults to True. reduction (str, optional): The method used to reduce the loss into a scalar. Defaults to mean. Options are "none", "mean" and "sum". avg_factor (int, optional): Average factor that is used to average the loss. Defaults to None. """ # pred and target should be of the same size assert pred.size() == target.size() pred_sigmoid = pred.sigmoid() target = target.type_as(pred) if iou_weighted: focal_weight = target * (target > 0.0).float() + \ alpha * (pred_sigmoid - target).abs().pow(gamma) * \ (target <= 0.0).float() else: focal_weight = (target > 0.0).float() + \ alpha * (pred_sigmoid - target).abs().pow(gamma) * \ (target <= 0.0).float() loss = F.binary_cross_entropy_with_logits( pred, target, reduction=none) * focal_weight loss = weight_reduce_loss(loss, weight, reduction, avg_factor) return loss class VarifocalLoss(nn.Module): def __init__(self, use_sigmoid=True, alpha=0.75, gamma=2.0, iou_weighted=True, reduction=mean, loss_weight=1.0): """`Varifocal Loss <https://arxiv.org/abs/2008.13367>`_ Args: use_sigmoid (bool, optional): Whether the prediction is used for sigmoid or softmax. Defaults to True. alpha (float, optional): A balance factor for the negative part of Varifocal Loss, which is different from the alpha of Focal Loss. Defaults to 0.75. gamma (float, optional): The gamma for calculating the modulating factor. Defaults to 2.0. iou_weighted (bool, optional): Whether to weight the loss of the positive examples with the iou target. Defaults to True. reduction (str, optional): The method used to reduce the loss into a scalar. Defaults to mean. Options are "none", "mean" and "sum". loss_weight (float, optional): Weight of loss. Defaults to 1.0. """ super(VarifocalLoss, self).__init__() assert use_sigmoid is True, \ Only sigmoid varifocal loss supported now. assert alpha >= 0.0 self.use_sigmoid = use_sigmoid self.alpha = alpha self.gamma = gamma self.iou_weighted = iou_weighted self.reduction = reduction self.loss_weight = loss_weight def forward(self, pred, target, weight=None, avg_factor=None, reduction_override=None): """Forward function. Args: pred (torch.Tensor): The prediction. target (torch.Tensor): The learning target of the prediction. weight (torch.Tensor, optional): The weight of loss for each prediction. Defaults to None. avg_factor (int, optional): Average factor that is used to average the loss. Defaults to None. reduction_override (str, optional): The reduction method used to override the original reduction method of the loss. Options are "none", "mean" and "sum". Returns: torch.Tensor: The calculated loss """ assert reduction_override in (None, none, mean, sum) reduction = ( reduction_override if reduction_override else self.reduction) if self.use_sigmoid: loss_cls = self.loss_weight * varifocal_loss( pred, target, weight, alpha=self.alpha, gamma=self.gamma, iou_weighted=self.iou_weighted, reduction=reduction, avg_factor=avg_factor) else: raise NotImplementedError return loss_cls

步骤二:在YOLOX-main/yolox/models/yolo_head.py中调用VarifocalLoss

(1)导入

from .varifocalloss import VarifocalLoss

(2)在init中实例化

self.varifocal = VarifocalLoss(reduction=none)

(3)替换原有的置信度预测损失loss_obj

# loss_iou:定位损失;loss_obj:置信度预测损失;loss_cls:预测损失 loss_iou = ( self.iou_loss(bbox_preds.view(-1, 4)[fg_masks], reg_targets) ).sum() / num_fg #loss_obj = ( # self.bcewithlog_loss(obj_preds.view(-1, 1), obj_targets) #).sum() / num_fg loss_obj = (self.varifocal(obj_preds.view(-1, 1), obj_targets) ).sum() / num_fg loss_cls = ( self.bcewithlog_loss( cls_preds.view(-1, self.num_classes)[fg_masks], cls_targets) ).sum() / num_fg

效果:根据个人数据集而定             。FocalLoss与VariFocalLoss在我的数据集上均能提升              ,模型越大效果越明显                    。(但是在yolox-tiny上FocalLoss效果AP50会低于原来)

以上代码链接

链接:https://pan.baidu.com/s/1ee1sQ9Eulz_mUdHTOnBe7w

提取码:8v8r

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
ac1200如何设置(BLINK AC1200U路由器怎么开启访客模式) seo网站排名优化案例(SEO绩效考核:优化网站排名,增加流量转化)