YOLOv3已经出来很久了,自己的文字检测也是用的YOLOv3完成的,最近一直被问到一些相关细节问题,自己不看源码也确实记不起来了,干脆就简单写下来好了。代码参考均来自于Github:keras-yolov3
一、改进
改进一:边界框的预测
yolov3的anchors和yolov2一样由聚类得到,数量由5个增加到9个。直接预测得到tx,ty,tw,th,to然后通过下面两张图的转换公式得到最后的归一化真实值(还需要乘以对应图像的H,W还原)。
其中:
# 将output 转换为实际值
box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast(grid_shape[::-1], K.dtype(feats))
box_wh = K.exp(feats[..., 2:4]) * anchors_tensor / K.cast(input_shape[::-1], K.dtype(feats))
box_confidence = K.sigmoid(feats[..., 4:5])
box_class_probs = K.sigmoid(feats[..., 5:])
改进二:类别预测
不再使用Softmax进行分类,类内竞争会损失精度,对每一类使用二分类,分类损失也使用二值交叉熵。
改进三:多尺度预测
FPN已经被证明了是非常有效的tricks,自然而然被纳入了yolov3中。其中包含三个特征图尺度,分别下采样32x,16x,8x,每个特征图上设置三种大小的anchors,对应大、中、小,每一个尺度的特征图上可以得到 N × N × [3 ∗ (4 + 1 + 80)] 的结果,分别是N x N个 gird cell ,3种尺度的anchors,x、y、w、h、confidence、80类。
改进四:特征提取器
由yolov2的darknet-19升级为darknet-53。
darknet-53.png result.png
改进五:训练方法
作者此处引用了自己的网站主页。。。
二、具体做法和实验结果
精度.png 速度.png三、一些尝试但是不起作用
- 尝试使用预测中心点x、y的偏移量和w、h的比例关系,稳定性下降,结果并不好。
- 尝试直接预测x、y而不是使用logistic,MAP下降。
- 尝试使用Focal Loss,MAP下降2%,作者也不确定原因。
- 尝试使用Faster-rcnn的双IOU阈值,在训练期间:iou>0.7,正例;0.3<iou<0.7,忽略;iou<0.3,负例。效果并不好。
四、损失函数
- xy_loss
二值交叉熵(KL散度)
- wh_loss
SSE
- confidence_loss
分为obj和no_obj两种情况计算。对于obj(该检测框有对应的真实框),二值交叉熵;对于no_obj(该检测框无对应的真实框),当检测框和真实框的iou低于0.5,需要计算no_obj_confidence_loss,也是二值交叉熵。
- class_loss
二值交叉熵
# 这里是一个系数,面积越小权重越高
box_loss_scale = 2 - y_true[l][...,2:3]*y_true[l][...,3:4]
xy_loss = object_mask * box_loss_scale * K.binary_crossentropy(raw_true_xy, raw_pred[...,0:2], from_logits=True)
wh_loss = object_mask * box_loss_scale * 0.5 * K.square(raw_true_wh-raw_pred[...,2:4])
confidence_loss = object_mask * K.binary_crossentropy(object_mask, raw_pred[...,4:5], from_logits=True)+ \
(1-object_mask) * K.binary_crossentropy(object_mask, raw_pred[...,4:5], from_logits=True) * ignore_mask
class_loss = object_mask * K.binary_crossentropy(true_class_probs, raw_pred[...,5:], from_logits=True)
网友评论