【YOLOv4探讨 之四】标签平滑Label Smoothing

YOLOv4中,为了防止分类过拟合,使用了标签平滑Label Smoothing的技巧。
Label Smoothing最早源于论文《Rethinking the inception architecture for computer vision》,这里不讨论。基本原理如下:通常YOLO模型中,80个分类标签都是使用0或1进行描述,在训练过程中,如果认为属于第n个分类,则该位置输出1(这种分类标签编码形式也称为one hot编码,即一位(独热)编码)。在数据集为无穷的情况下,可以对所有分类进行训练和标记,但是数据集不可能是无穷,尤其是当数据集量并不太大的时候,训练次数过多,很容易造成过拟合。采用Label Smoothing的技巧可以将标签的确定性减弱,从而降低过拟合的可能性。
在YOLOv4的实际代码中,将Label Smoothing体现在了计算分类函数求导得到的delta中,YOLO模型的分类求导和反向传播可以参考文章《YOLO中LOSS函数的计算》(https://editor.csdn.net/md/?articleId=106583800)和《YOLOv3反向传播原理 之 全流程源码分析》(https://editor.csdn.net/md/?articleId=107303735)。
关于Label Smoothing的实际操作具体而言,令
l a b e l t r u e s m o o t h = l a b e l t r u e × ( 1 − α ) + l a b e l t r u e × α label_{true_{}} ^{smooth}= label_{true_{}} ×(1-α)+label_{true_{}} ×α labeltruesmooth=labeltrue×(1α)+labeltrue×α
这个真标签在实际应用中体现在求delta的过程中,原delta在YOLOv3代码中为:

delta[index + stride*class] = 1 - output[index + stride*class];

在YOLOv4中处理后代码如下:

void delta_yolo_class(float *output, float *delta, int index, int class_id, int classes, int stride, float *avg_cat, int focal_loss, float label_smooth_eps, float *classes_multipliers)
{
    ......
    float y_true = 1;
    if(label_smooth_eps) y_true = y_true *  (1 - label_smooth_eps) + 0.5*label_smooth_eps;
    float result_delta = y_true - output[index + stride*class_id];
    if(!isnan(result_delta) && !isinf(result_delta)) delta[index + stride*class_id] = result_delta;
    ......

这里在计算delta的第二项将 l a b e l t r u e label_{true_{}} labeltrue写成0.5,应该是一个加强作用,另外还可以防止出现 l a b e l t r u e s m o o t h > 1 label_{true_{}} ^{smooth}>1 labeltruesmooth1的情况发生。

你可能感兴趣的:(YOLOv4,人工智能,深度学习,机器学习)