深度学习【17】物体检测:Focal Loss 反向求导及darknet上的实现

Focal Loss 反向求导及darknet上的实现

Focal Loss 可以解决不平衡分类问题,是在交叉熵损失函数上的扩展。详见,论文:Focal Loss for Dense Object Detection。
该文,主要推导FL在softmax函数下的求导,以及记录在darknet上的实现。

FL损失函数如下:

FL(pt)=α(1pt)γlog(pt) F L ( p t ) = − α ( 1 − p t ) γ l o g ( p t )

其中 pt p t 为:
pt={p, 1p,if y==1 otherwise  p t = { p , if  y == 1     1 − p , otherwise 

softmax公式:

pi=exiek p i = e x i ∑ e k

我们的目标得到x对FL的导数:

dFLdxi=dFLdpidpidxi d F L d x i = d F L d p i ∗ d p i d x i

又,

dFLdpt  =α(d(1pt)γdptlog(pt)+(1pt)γdlog(pt)dpt)=α(γ(1pt)γ1log(pt)+(1pt)γ1pt)=α(γ(1pi)γ1log(pi)+(1pi)γ1pi)because(y==1)(1)(2)(3) (1) d F L d p t = − α ( d ( 1 − p t ) γ d p t ∗ l o g ( p t ) + ( 1 − p t ) γ ∗ d l o g ( p t ) d p t ) (2)   = − α ( − γ ( 1 − p t ) γ − 1 l o g ( p t ) + ( 1 − p t ) γ 1 p t ) (3)   = − α ( − γ ( 1 − p i ) γ − 1 l o g ( p i ) + ( 1 − p i ) γ 1 p i ) b e c a u s e ( y == 1 )

xi x i 对softmax的求导,分两种情况:

ifi==j: dpidxi   ifi!=j: dpidxi =exiexkexiexiex2k=exiexkexiexkexiexk=pipipi=pi(1pi)=0exiexjex2k=pipj(4)(5)(6)(7)(8)(9)(10) (4) i f i == j : (5)   d p i d x i = e x i ∗ ∑ e x k − e x i ∗ e x i ∑ e x k 2 (6)   = e x i ∑ e x k − e x i ∑ e x k ∗ e x i ∑ e x k (7)   = p i − p i ∗ p i = p i ( 1 − p i ) (8)   i f i ! = j : (9)   d p i d x i = 0 − e x i ∗ e x j ∑ e x k 2 (10)   = − p i ∗ p j

因此,

ifi==j:  ifi!=j: dFLdxi=α(γ(1pi)γ1log(pi)pi+(1pi)γ)(pi1)dFLdxi=α(γ(1pi)γ1log(pi)pi+(1pi)γ)pj(11)(12)(13)(14) (11) i f i == j : (12)   d F L d x i = α ( − γ ( 1 − p i ) γ − 1 l o g ( p i ) p i + ( 1 − p i ) γ ) ∗ ( p i − 1 ) (13)   i f i ! = j : (14)   d F L d x i = α ( − γ ( 1 − p i ) γ − 1 l o g ( p i ) p i + ( 1 − p i ) γ ) ∗ p j

darknet的softmax交叉熵反向传导时,当i==j时是,1-pi_ 1-pi_ ,;当 i!=j i ! = j 时是 pj − p j ,因此还需多一个负号。

默认alpha=0.25,gamma=2


        int ti = index+stride*class;
        float grad =-2*(1-output[ti])*logf(fmaxf(output[ti],0.0000001))*output[ti]+(1-output[ti])*(1-output[ti]);

        for(n = 0; n < classes; ++n){ 
            delta[index + stride*n] = scale * (((n == class)?1 : 0) - output[index + stride*n]);

            delta[index+stride*n] *= 0.25*grad;

            if(n == class) *avg_cat += output[index + stride*n];

如果alpha=1,训练就会出现nan。但是alpha=0.25,,训练又很慢,还需要多做实验。

2017.10.16更新:将alpha设置为0.5,经过漫长的训练,平均map能够上升2%。

你可能感兴趣的:(深度学习)