看到这个题目想必大家都猜到了,昨天的文章又有问题了。。。今天,又和两位大佬交流了一下YOLOV3损失函数,然后重新再对源码进行了梯度推导我最终发现,我的理解竟然还有一个很大的错误,接下来我就直入主题,讲讲在昨天文章放出的YOLOV3 损失函数基础上还存在什么错误。
上篇文章的地址是:你对YOLOV3损失函数真的理解正确了吗? ,然后通过推导我们将损失函数的表示形式定格为了下面的等式:
行云大佬的YOLOV3 损失函数
那么这个等式还存在什么问题呢?
答案就是DarkNet中坐标损失实际上是BCE(二元交叉熵)损失而不是这个公式写的MSE Loss。
我们首先定位一下源码的forward_yolo_layer_gpu
函数:
forward_yolo_layer_gpu 函数
可以看到
在计算损失函数之前先经过了Logistic回归,也就是一个Sigmoid函数进行激活然后再计算损失,如果这个损失如上面的公式所说是MSE Loss的话,那么我们来推导一下梯度。
按照上面的公式,坐标的损失函数可以表达为
其中
代表bbox中的任意一个变量(有x,y,w,h 4个),那么我们来求一下偏导,根据链式法则可以得到:
其中
是
对
的倒数,进一步将其整理为:
又因为DarkNet是直接weights+lr*delta
,所以是实际算的时候梯度是上面等式的相反数,所以:
然后我们看一下官方DarkNet源码对每个坐标的梯度表达形式:
官方DarkNet源码对每个坐标的梯度表达形式
前面的scale
就是
我们暂时不看,可以看到梯度的形式就是一个
呀(注意在forward_yolo_layer_gpu
函数中执行的是
操作,这里为了方便大家理解我还是写成了
),所以我就有了大大的问号?
Sigmoid函数的梯度去哪了???
Draw.大佬说其实YOLOV3的坐标损失依然是BCE Loss,这怎么和网上的博客不一样啊(所以啊,初期可以看博客,学习久了就要尝试脱离博客了),那么我们带着这个想法来推导一番。
我们知道对于BCE Loss来说:
这里
表示标签值,那么自然有
所以这里我们就变成了求loss对
的导数:
又因为DarkNet是直接weights+lr*delta
,所以是实际算的时候梯度是上面等式的相反数,所以:
回过头看一下DarkNet在坐标损失上的梯度呢?
官方DarkNet源码对每个坐标的梯度表达形式
这不是一模一样?
根据梯度一致性来判断,DarkNet YOLOV3坐标损失是BCE损失没跑了吧。
通过对梯度的推导,我们发现DarkNet官方实现的YOLOV3里面坐标损失用的竟然是BCE Loss,而YOLOV3官方论文里面说的是MSE Loss,我个人觉得论文不能全信啊233。
至此DarkNet中YOLO V3的损失函数解析完毕,只需要将
行云大佬的YOLOV3 损失函数
这里面的MSE坐标损失替换成BCE坐标损失就可以获得最终的官方版本DarkNet YOLOV3的损失函数啦。有问题留言区交流哦。