做网站能注册账号的,地宝网南昌分类,做网站需要要多少钱,网站架构思维导图一、本文介绍
本文给大家带来的是分类损失 SlideLoss、VFLoss、FocalLoss损失函数#xff0c;我们之前看那的那些IoU都是边界框回归损失#xff0c;和本文的修改内容并不冲突#xff0c;所以大家可以知道损失函数分为两种一种是分类损失另一种是边界框回归损失#xff0c;…一、本文介绍
本文给大家带来的是分类损失 SlideLoss、VFLoss、FocalLoss损失函数我们之前看那的那些IoU都是边界框回归损失和本文的修改内容并不冲突所以大家可以知道损失函数分为两种一种是分类损失另一种是边界框回归损失上一篇文章里面我们总结了过去百分之九十的边界框回归损失的使用方法本文我们就来介绍几种市面上流行的和最新的分类损失函数同时在开始讲解之前推荐一下我的专栏本专栏的内容支持(分类、检测、分割、追踪、关键点检测),专栏目前为限时折扣欢迎大家订阅本专栏本专栏每周更新3-5篇最新机制更有包含我所有改进的文件和交流群提供给大家本文支持的损失函数共有如下图片所示
欢迎大家订阅我的专栏一起学习YOLO 专栏回顾YOLOv10改进系列专栏——本专栏持续复习各种顶会内容——科研必备 目录
一、本文介绍
二、原理介绍
三、核心代码
三、使用方式
3.1 修改一
3.2 修改二
3.3 使用方法
四 、本文总 二、原理介绍
其中绝大多数损失在前面我们都讲过了本文主要讲一下SlidLoss的原理SlideLoss的损失首先是由YOLO-FaceV2提出来的。
官方论文地址 官方论文地址点击即可跳转
官方代码地址 官方代码地址点击即可跳转
从摘要上我们可以看出SLideLoss的出现是通过权重函数来解决简单和困难样本之间的不平衡问题题什么是简单样本和困难样本
样本不平衡问题是一个常见的问题尤其是在分类和目标检测任务中。它通常指的是训练数据集中不同类别的样本数量差异很大。对于人脸检测这样的任务来说简单样本和困难样本之间的不平衡问题可以具体描述如下
简单样本
容易被模型正确识别的样本。通常出现在数据集中的数量较多。特征明显分类或检测边界清晰。在训练中这些样本会给出较低的损失值因为模型可以轻易地正确预测它们。
困难样本
模型难以正确识别的样本。在数据集中相对较少但对模型性能的提升至关重要。可能由于多种原因变得难以识别如遮挡、变形、模糊、光照变化、小尺寸或者与背景的低对比度。在训练中这些样本会产生较高的损失值因为模型很难对它们给出准确的预测。
解决样本不平衡的问题是提高模型泛化能力的关键。如果模型大部分只见过简单样本它可能在实际应用中遇到困难样本时性能下降。因此采用各种策略来解决这个问题例如重采样对困难样本进行过采样或对简单样本进行欠采样、修改损失函数给困难样本更高的权重或者是设计新的模型结构来专门关注困难样本。在YOLO-FaceV2中作者通过Slide Loss这样的权重函数来让模型在训练过程中更关注那些困难样本(这也是本文的修改内容)。 三、核心代码
使用方式看章节四 import mathclass SlideLoss(nn.Module):def __init__(self, loss_fcn):super(SlideLoss, self).__init__()self.loss_fcn loss_fcnself.reduction loss_fcn.reductionself.loss_fcn.reduction none # required to apply SL to each elementdef forward(self, pred, true, auto_iou0.5):loss self.loss_fcn(pred, true)if auto_iou 0.2:auto_iou 0.2b1 true auto_iou - 0.1a1 1.0b2 (true (auto_iou - 0.1)) (true auto_iou)a2 math.exp(1.0 - auto_iou)b3 true auto_ioua3 torch.exp(-(true - 1.0))modulating_weight a1 * b1 a2 * b2 a3 * b3loss * modulating_weightif self.reduction mean:return loss.mean()elif self.reduction sum:return loss.sum()else: # nonereturn lossclass Focal_Loss(nn.Module):# Wraps focal loss around existing loss_fcn(), i.e. criteria FocalLoss(nn.BCEWithLogitsLoss(), gamma1.5)def __init__(self, loss_fcn, gamma1.5, alpha0.25):super().__init__()self.loss_fcn loss_fcn # must be nn.BCEWithLogitsLoss()self.gamma gammaself.alpha alphaself.reduction loss_fcn.reductionself.loss_fcn.reduction none # required to apply FL to each elementdef forward(self, pred, true):loss self.loss_fcn(pred, true)# p_t torch.exp(-loss)# loss * self.alpha * (1.000001 - p_t) ** self.gamma # non-zero power for gradient stability# TF implementation https://github.com/tensorflow/addons/blob/v0.7.1/tensorflow_addons/losses/focal_loss.pypred_prob torch.sigmoid(pred) # prob from logitsp_t true * pred_prob (1 - true) * (1 - pred_prob)alpha_factor true * self.alpha (1 - true) * (1 - self.alpha)modulating_factor (1.0 - p_t) ** self.gammaloss * alpha_factor * modulating_factorif self.reduction mean:return loss.mean()elif self.reduction sum:return loss.sum()else: # nonereturn lossdef 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: 2if reduction_enum 0:return losselif reduction_enum 1:return loss.mean()elif reduction_enum 2:return loss.sum()def weight_reduce_loss(loss, weightNone, reductionmean, avg_factorNone):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 weightif weight is not None:loss loss * weight# if avg_factor is not specified, just reduce the lossif avg_factor is None:loss reduce_loss(loss, reduction)else:# if reduction is mean, then average the loss by avg_factorif reduction mean:loss loss.sum() / avg_factor# if reduction is none, then do nothing, otherwise raise an errorelif reduction ! none:raise ValueError(avg_factor can not be used with reductionsum)return lossdef varifocal_loss(pred,target,weightNone,alpha0.75,gamma2.0,iou_weightedTrue,reductionmean,avg_factorNone):Varifocal Loss https://arxiv.org/abs/2008.13367_Args:pred (torch.Tensor): The prediction with shape (N, C), C is thenumber of classestarget (torch.Tensor): The learning target of the iou-awareclassification score with shape (N, C), C is the number of classes.weight (torch.Tensor, optional): The weight of loss for eachprediction. Defaults to None.alpha (float, optional): A balance factor for the negative part ofVarifocal Loss, which is different from the alpha of Focal Loss.Defaults to 0.75.gamma (float, optional): The gamma for calculating the modulatingfactor. Defaults to 2.0.iou_weighted (bool, optional): Whether to weight the loss of thepositive example with the iou target. Defaults to True.reduction (str, optional): The method used to reduce the loss intoa scalar. Defaults to mean. Options are none, mean andsum.avg_factor (int, optional): Average factor that is used to averagethe loss. Defaults to None.# pred and target should be of the same sizeassert 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, reductionnone) * focal_weightloss weight_reduce_loss(loss, weight, reduction, avg_factor)return lossclass Vari_focalLoss(nn.Module):def __init__(self,use_sigmoidTrue,alpha0.75,gamma2.0,iou_weightedTrue,reductionsum,loss_weight1.0):Varifocal Loss https://arxiv.org/abs/2008.13367_Args:use_sigmoid (bool, optional): Whether the prediction isused for sigmoid or softmax. Defaults to True.alpha (float, optional): A balance factor for the negative part ofVarifocal Loss, which is different from the alpha of FocalLoss. Defaults to 0.75.gamma (float, optional): The gamma for calculating the modulatingfactor. Defaults to 2.0.iou_weighted (bool, optional): Whether to weight the loss of thepositive examples with the iou target. Defaults to True.reduction (str, optional): The method used to reduce the loss intoa scalar. Defaults to mean. Options are none, mean andsum.loss_weight (float, optional): Weight of loss. Defaults to 1.0.super(Vari_focalLoss, self).__init__()assert use_sigmoid is True, \Only sigmoid varifocal loss supported now.assert alpha 0.0self.use_sigmoid use_sigmoidself.alpha alphaself.gamma gammaself.iou_weighted iou_weightedself.reduction reductionself.loss_weight loss_weightdef forward(self,pred,target,weightNone,avg_factorNone,reduction_overrideNone):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 eachprediction. Defaults to None.avg_factor (int, optional): Average factor that is used to averagethe loss. Defaults to None.reduction_override (str, optional): The reduction method used tooverride the original reduction method of the loss.Options are none, mean and sum.Returns:torch.Tensor: The calculated lossassert 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,alphaself.alpha,gammaself.gamma,iou_weightedself.iou_weighted,reductionreduction,avg_factoravg_factor)else:raise NotImplementedErrorreturn loss_cls三、使用方式
3.1 修改一
我们找到如下的文件ultralytics/utils/loss.py然后将上面的核心代码粘贴到文件的开头位置注意是其他模块的导入之后粘贴后的样子如下图所示 3.2 修改二
第二步我门中到函数class v8DetectionLoss:没看错V10继承的v8损失函数我们修改v8就相当于修改了v10我们下下面的代码全部替换class v8DetectionLoss:的内容
class v8DetectionLoss:Criterion class for computing training losses.def __init__(self, model): # model must be de-paralleledInitializes v8DetectionLoss with the model, defining model-related properties and BCE loss function.device next(model.parameters()).device # get model deviceh model.args # hyperparametersm model.model[-1] # Detect() moduleself.bce nn.BCEWithLogitsLoss(reductionnone)下面的代码注释掉就是正常的损失函数如果不注释使用的就是使用对应的损失失函数# self.bce Focal_Loss(nn.BCEWithLogitsLoss(reductionnone)) # Focal# self.bce Vari_focalLoss() # VFLoss# self.bce SlideLoss(nn.BCEWithLogitsLoss(reductionnone)) # SlideLoss# self.bce QualityfocalLoss() # 目前仅支持者目标检测需要注意 分割 Pose 等用不了self.hyp hself.stride m.stride # model stridesself.nc m.nc # number of classesself.no m.nc m.reg_max * 4self.reg_max m.reg_maxself.device deviceself.use_dfl m.reg_max 1self.assigner TaskAlignedAssigner(topk10, num_classesself.nc, alpha0.5, beta6.0)self.bbox_loss BboxLoss(m.reg_max - 1, use_dflself.use_dfl).to(device)self.proj torch.arange(m.reg_max, dtypetorch.float, devicedevice)def preprocess(self, targets, batch_size, scale_tensor):Preprocesses the target counts and matches with the input batch size to output a tensor.if targets.shape[0] 0:out torch.zeros(batch_size, 0, 5, deviceself.device)else:i targets[:, 0] # image index_, counts i.unique(return_countsTrue)counts counts.to(dtypetorch.int32)out torch.zeros(batch_size, counts.max(), 5, deviceself.device)for j in range(batch_size):matches i jn matches.sum()if n:out[j, :n] targets[matches, 1:]out[..., 1:5] xywh2xyxy(out[..., 1:5].mul_(scale_tensor))return outdef bbox_decode(self, anchor_points, pred_dist):Decode predicted object bounding box coordinates from anchor points and distribution.if self.use_dfl:b, a, c pred_dist.shape # batch, anchors, channelspred_dist pred_dist.view(b, a, 4, c // 4).softmax(3).matmul(self.proj.type(pred_dist.dtype))# pred_dist pred_dist.view(b, a, c // 4, 4).transpose(2,3).softmax(3).matmul(self.proj.type(pred_dist.dtype))# pred_dist (pred_dist.view(b, a, c // 4, 4).softmax(2) * self.proj.type(pred_dist.dtype).view(1, 1, -1, 1)).sum(2)return dist2bbox(pred_dist, anchor_points, xywhFalse)def __call__(self, preds, batch):Calculate the sum of the loss for box, cls and dfl multiplied by batch size.loss torch.zeros(3, deviceself.device) # box, cls, dflfeats preds[1] if isinstance(preds, tuple) else predspred_distri, pred_scores torch.cat([xi.view(feats[0].shape[0], self.no, -1) for xi in feats], 2).split((self.reg_max * 4, self.nc), 1)pred_scores pred_scores.permute(0, 2, 1).contiguous()pred_distri pred_distri.permute(0, 2, 1).contiguous()dtype pred_scores.dtypebatch_size pred_scores.shape[0]imgsz torch.tensor(feats[0].shape[2:], deviceself.device, dtypedtype) * self.stride[0] # image size (h,w)anchor_points, stride_tensor make_anchors(feats, self.stride, 0.5)# Targetstargets torch.cat((batch[batch_idx].view(-1, 1), batch[cls].view(-1, 1), batch[bboxes]), 1)targets self.preprocess(targets.to(self.device), batch_size, scale_tensorimgsz[[1, 0, 1, 0]])gt_labels, gt_bboxes targets.split((1, 4), 2) # cls, xyxymask_gt gt_bboxes.sum(2, keepdimTrue).gt_(0)# pboxespred_bboxes self.bbox_decode(anchor_points, pred_distri) # xyxy, (b, h*w, 4)target_labels, target_bboxes, target_scores, fg_mask, _ self.assigner(pred_scores.detach().sigmoid(), (pred_bboxes.detach() * stride_tensor).type(gt_bboxes.dtype),anchor_points * stride_tensor, gt_labels, gt_bboxes, mask_gt)target_scores_sum max(target_scores.sum(), 1)# Cls loss# loss[1] self.varifocal_loss(pred_scores, target_scores, target_labels) / target_scores_sum # VFL wayif isinstance(self.bce, (nn.BCEWithLogitsLoss, Vari_focalLoss, Focal_Loss)):loss[1] self.bce(pred_scores, target_scores.to(dtype)).sum() / target_scores_sum # BCE VFLoss Focalelif isinstance(self.bce, SlideLoss):if fg_mask.sum():auto_iou bbox_iou(pred_bboxes[fg_mask], target_bboxes[fg_mask], xywhFalse, CIoUTrue).mean()else:auto_iou 0.1loss[1] self.bce(pred_scores, target_scores.to(dtype), auto_iou).sum() / target_scores_sum # SlideLosselif isinstance(self.bce, QualityfocalLoss):if fg_mask.sum():pos_ious bbox_iou(pred_bboxes, target_bboxes / stride_tensor, xywhFalse).clamp(min1e-6).detach()# 10.0x Faster than torch.one_hottargets_onehot torch.zeros((target_labels.shape[0], target_labels.shape[1], self.nc),dtypetorch.int64,devicetarget_labels.device) # (b, h*w, 80)targets_onehot.scatter_(2, target_labels.unsqueeze(-1), 1)cls_iou_targets pos_ious * targets_onehotfg_scores_mask fg_mask[:, :, None].repeat(1, 1, self.nc) # (b, h*w, 80)targets_onehot_pos torch.where(fg_scores_mask 0, targets_onehot, 0)cls_iou_targets torch.where(fg_scores_mask 0, cls_iou_targets, 0)else:cls_iou_targets torch.zeros((target_labels.shape[0], target_labels.shape[1], self.nc),dtypetorch.int64,devicetarget_labels.device) # (b, h*w, 80)targets_onehot_pos torch.zeros((target_labels.shape[0], target_labels.shape[1], self.nc),dtypetorch.int64,devicetarget_labels.device) # (b, h*w, 80)loss[1] self.bce(pred_scores, cls_iou_targets.to(dtype), targets_onehot_pos.to(torch.bool)).sum() / max(fg_mask.sum(), 1)else:loss[1] self.bce(pred_scores, target_scores.to(dtype)).sum() / target_scores_sum # 确保有损失可用# Bbox lossif fg_mask.sum():target_bboxes / stride_tensorloss[0], loss[2] self.bbox_loss(pred_distri, pred_bboxes, anchor_points, target_bboxes, target_scores,target_scores_sum, fg_mask,((imgsz[0] ** 2 imgsz[1] ** 2) / torch.square(stride_tensor)).repeat(1,batch_size).transpose(1, 0))loss[0] * self.hyp.box # box gainloss[1] * self.hyp.cls # cls gainloss[2] * self.hyp.dfl # dfl gainreturn loss.sum() * batch_size, loss.detach() # loss(box, cls, dfl) 3.3 使用方法
将上面的代码复制粘贴之后我门找到下图所在的位置使用方法就是那个取消注释就是使用的就是那个
四 、本文总结
到此本文的正式分享内容就结束了在这里给大家推荐我的YOLOv10改进有效涨点专栏本专栏目前为新开的平均质量分98分后期我会根据各种最新的前沿顶会进行论文复现也会对一些老的改进机制进行补充如果大家觉得本文帮助到你了订阅本专栏关注后续更多的更新~ 专栏回顾YOLOv10改进系列专栏——本专栏持续复习各种顶会内容——科研必备