focal loss dice loss源码_YAD2K:Keras版本的YOLO算法损失函数源码解读

e27810679e320de0e22163b8907ace40.png
“深度学习算法代码无非包括三个部分,一是数据预处理,二是网络搭建,三是损失函数构建。”——Fast.ai创始人Jeremy Howard

YOLO是目标检测领域中比较著名的one stage检测算法,在能保证一定检测精度的同时,还能有极高的FPS。YOLO官方代码由论文作者使用Darknet这个框架写成,这是个比较小众的框架,但为了能让更多人懂得YOLO算法的原理,github上有位叫allanzelener的朋友在两年前公开了keras版本的YOLO源码,项目名字叫YAD2K:Yet Another Darknet 2 Keras。虽然作者已经有一年多没维护这个项目了,但对于习惯使用keras或者tensorflow的同学来说,还是非常好的学习项目。

正如本文前言,一个项目代码最重要就是这三个部分,其中数据预处理笔者在专栏的其它文章介绍过,而网络搭建简单如搭乐高积木,正好笔者在研究目标检测,YOLO的Loss函数部分代码比较长,许多人乍一看不大好理解(原文公式也非常长),因此本文就主要介绍YAD2K的loss函数代码,适合想深入了解YOLO算法的同学,同时也作为Fancy Keras专栏的loss函数花式写法案例介绍。

YOLO算法原理(略)

由于网上有非常多的论文解读,对于初学者笔者强烈建议观看吴恩达DeepLearning.ai CNN课程中的目标检测一章,老师讲得非常透彻(见底部参考资料)。

816b9929e885cbe85bfdb3c5dfaff2a1.png

loss函数及关键代码解释

fa1315f327bc60d47e9d78feba90ad47.png
  • 坐标损失部分(公式第一二行):

9fab6be4144cd238ddc0c2de17f18685.png

这是BBOX坐标回归的损失部分,注意这里只使用“包含Ground Truth Box的cells中,与GTBox的IoU最大的那个anchor”作损失贡献,这就是论文中所说的“responsible predictor”:

YOLO predicts multiple bounding boxes per grid cell.
At training time we only want one bounding box predictor to be responsible for each object. We assign one predictor to be “responsible” for predicting an object based on which prediction has the highest current IOU with the ground truth.

也就是说,这49个区域我们只能用满足上面条件的区域作损失计算,需要用一个“mask”来过滤掉不必要的部分。这个mask使用项目中“yad2k/models/keras_yolo.py”line 352的“preprocess_true_boxes”函数完成,它会返回“detectors_mask”和“matching_true_boxes”,其中“detectors_mask”正是我们所需的mask,而“matching_true_boxes”就是我们这个监督学习所需要的标签y。

我们来看看第280行到283行的代码,对应的就是坐标损失函数:

# Coordinate loss for matching detection boxes.

首先“matching_boxes”是我们的标签y的bbox坐标值,我们可以从上面获得的“matching_true_boxes”中提取出来;“coordinates_scale ”就是论文中的

,即坐标损失的权重;再乘以“detectors_mask ”,只需要responsible的cells中IoU最大的那些anchors来参与损失贡献,其它一概不要;最后就是预测值与真实值坐标之差的平方,这些组成了我们的坐标损失代码。
  • confidence损失部分(公式第三四行)

0515f6783f4804b6f8356353ad894dbd.png

这部分有点难理解,主要分为“有object”和“无object”两个部分,我们知道在上面坐标损失函数中,有一个“detectors_mask”能够选出我们所需的anchors,那么“有object”的部分就能用这个mask来解决。但是“无object”这个部分有点tricky,按常理来说,我们直接用“1-detectors_mask”就能选出来,但这样选出来的无object负例就太多了,发生类别严重不平衡的情况,导致网络最终什么都检测不出来(或者说网络学会了检测无object)。因此我们不能全部负例都要,我们可以只留下同样在responsible的cells中,那些IoU“不是最大值”的anchors(因为最大值的那些被用来当作正例了),这样就能大大降低负例的数量了。

在“yad2k/models/keras_yolo.py”中,第152到298行之间都是“yolo_loss”的代码部分,从第193行到第254行是一些求解预测值与GTBox的IoU求解过程,得到另外一个重要的mask:“object_detections”,这个mask的意义是“在responsible的cells中没有包含object的anchors。”我们来对比两个mask的意义:

- detectors_mask:使用 初始化anchors(如论文中设定的五种不同尺寸的anchors)与GTBox计算彼此的IoU值,得出responsible的cells,取 拥有IoU最大值的那些anchors进行损失计算,其它anchors不参与。 - object_detections:使用 网络预测出来的bbox与GTBox计算彼此的IOU值,得出responsible的cells,在这些cells中取 IoU不是最大值的anchors作为负例mask(即1-object_detections)。

从上面的意义对比可以看到,object_detections是用预测出来的bbox来求解IoU,目的就是选出少量的负例。

在第261到第263行的代码中,就是confidence损失中,无object部分的代码:

no_object_weights = (no_object_scale * (1 - object_detections) *
                     (1 - detectors_mask))
no_objects_loss = no_object_weights * K.square(-pred_confidence)

可以看到,使用(1 - object_detections)和(1 - detectors_mask)这两个mask的重叠部分,即可得出我们所需的无object负例,最后乘以(0-pred_confidence)的平方,即可得出无object的confidence损失值。

在第265到第271行的代码中,就是confidence损失中,无object部分的代码:

if rescore_confidence:
    objects_loss = (object_scale * detectors_mask *
                    K.square(best_ious - pred_confidence))
else:
    objects_loss = (object_scale * detectors_mask *
                    K.square(1 - pred_confidence))
confidence_loss = objects_loss + no_objects_loss

这部分比较简单,只需把有object的系数、detectors_mask、以及(1-pred_confidence)的平方相乘,即可得出有object的confidence损失值。最后把两部分的损失值相加,就得出完整的confidence损失。

  • 分类损失(公式第五行)

c84ce60cfa6b8480696c767b11c58609.png

对应的代码就是第275到第278行:

matching_classes = K.cast(matching_true_boxes[..., 4], 'int32')
matching_classes = K.one_hot(matching_classes, num_classes)
classification_loss = (class_scale * detectors_mask *
                       K.square(matching_classes - pred_class_prob))

标签值经过one_hot处理,最后把分类损失的系数、detectors_mask、预测类别与真实类别之差的平方乘起来,得到最终的分类损失。

总结

YOLO的算法细节光阅读论文还是有一种云里雾里的感觉,连吴恩达老师都坦言当初看论文的时候也有这种感觉,听听他怎么说的:

49f85344bfbdf425117ec4b03e6375bc.png

74eef891e9780f62b2efd99f7d71d80b.png

f4a9b95c5fdc24ccb0c676161d13bcbd.png

60a7270cccfc6e87ba04ccc4e6edc310.png

fdbc13ae88481c8b3f1fec0c7457a53b.png

a1541bddf1b26c5b6fe7bb77e7af4aa1.png

还是那句:“Talk is cheap, show me your code.”多读论文+多读源码+复现论文,才能真正检验自己的实力!

参考资料

[1] github项目:allanzelener/YAD2K

[2] YOLO论文:You Only Look Once: Unified, Real-Time Object Detection

[3] 吴恩达CNN教学视频:Convolutional Neural Networks | Coursera

本文已收录于本人的个人网站,欢迎浏览收藏:铁人贾斯廷的基地 | 技术宅的碎碎念

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值