提升语义分割效果的方法 OHEM+LovaszSoftmax Loss
-
论文:The Lovasz-Softmax loss: A tractable surrogate for the optimization of the intersection-over-union measure in neural networks
Github:https://github.com/bermanmaxim/LovaszSoftmax
CVPR2018
论文提出了LovaszSoftmax,是一种基于IOU的loss,效果优于cross_entropy,可以在分割任务中使用。最终在Pascal VOC和 Cityscapes 两个数据集上取得了最好的结果。
论文贡献:
结合Lovasz hinge 和Jaccard loss 解决2值图片的分割问题
提出了Lovasz-Softmax loss 对多个类别分割的参数设置
设计了一个基于batch的IOU作为基于dataset IOU的高效代理
分析和对比各种IOU测量方法
基于本文的loss,对经典的分割方法的分割效果做出很大的提升OHEM
Training Region-based Object Detectors with Online Hard Example Mining(1) 训练过程需要进行参数的空间搜索
(2) 简单样本与难分辨样本之间的类别不平衡是亟需解决的问题
(3) 自动地选择难分辨样本来进行训练不仅效率高而且性能好
(4) 提出了OHEM算法,不仅效率高而且性能好,在各种数据集上表现优越Training Region-based Object Detectors with Online Hard Example Mining
困难负样本挖掘的方法。困难负样本是指AI模型难以区分的负样本。在模型不断训练的过程中,模型通常会对正样本有着比较高的confidence,但少不了对某些负样本也留有余芥,给了一个不那么接近0的confidence。而困难负例挖掘就是找到这些负例,然后针对性地训练。OHEM提出是一种线上的困难负例挖掘解决方案。使用了这个trick以后,检测模型的准确性有一定提升。
论文原本是在目标检测上 实际上分割领域用的更广泛
Cityscapes数据集上的经典方法下面是本人实际使用的代码
分割19类 忽略255
效果还行 没做消融实验 不确定提升效果class OhemCrossEntropy_2D(nn.Module): def __init__(self, ignore_index=-1, thresh=0.6, min_kept=350000, weight=None): super(OhemCrossEntropy_2D, self).__init__() self.thresh = thresh self.min_kept = max(1, min_kept) self.ignore_index = ignore_index self.weight = weight self.criterion = nn.CrossEntropyLoss( weight=weight, ignore_index=ignore_index, reduction="none" ) self.ls = Lovasz_softmax(ignore=self.ignore_index) self.nll = nn.NLLLoss(weight=weight, ignore_index=self.ignore_index, reduction="none") print(weight) def forward(self, score, target, **kwargs): ph, pw = score.size(2), score.size(3) h, w = target.size(1), target.size(2) if ph != h or pw != w: score = F.upsample(input=score, size=(h, w), mode="bilinear") pred = F.softmax(score, dim=1) pixel_losses = (self.criterion(score, target) + self.ls(pred, target)).contiguous().view(-1) mask = target.contiguous().view(-1) != self.ignore_index tmp_target = target.clone() tmp_target[tmp_target == self.ignore_index] = 0 pred = pred.gather(1, tmp_target.unsqueeze(1)) pred, ind = pred.contiguous().view(-1,)[mask].contiguous().sort() min_value = pred[min(self.min_kept, pred.numel() - 1)] threshold = max(min_value, self.thresh) pixel_losses = pixel_losses[mask][ind] pixel_losses = pixel_losses[pred < threshold] return pixel_losses.mean()
-
Alice_恒源云
-