sfd.pytorch
sfd.pytorch copied to clipboard
about loss implementation
@louis-she HI
在paper中,在计算loss时,有这样的描述:
The two terms are normalized by Ncls and Nreg , and weighted by a balancing parameter λ .
In our implementation, the cls term is normalized by the number of positive and negative anchors, and the reg term is normalized by the number of positive anchors. Because of the imbalance between the number of positive and negative anchors, λ is used to balance these two loss terms.
换句话说,理论上,分类损失除以(正样本+负样本)个数,回归损失除以(正样本)个数,然后给分类损失乘以一个权重(4). 比如正样本个数是100,那么分类损失就是除以400,然后乘以4;回归损失就是除以100.
但在code中,在计算2个损失时,
loss_class = 4 * F.cross_entropy(total_effective_pred, total_targets)
loss_reg = F.smooth_l1_loss(total_t, total_gt)
此时,相当于分类损失和回归损失都除以了(正样本+负样本)个数,都是400.
那么再给分类损失乘以权重4是不是有问题啊??
分类损失除以(正样本+负样本)个数,回归损失除以(正样本)个数
total_effective_pred 和 total_targets 就是只包含正样本的哈
我是基于你的training-v2分支进行分析的,
在training-v2分支中,分类损失乘以了4:
loss_class = 4 * F.cross_entropy(total_effective_pred, total_targets)
在master分支中,分类损失没有乘以4:
loss_class = F.cross_entropy(total_effective_pred, total_targets)
我认为master分支中才是合理的,不应该乘以4.
另外根据你的code,通过debug分析,total_effective_pred 和 total_targets 应该包含的是(正样本+负样本),请你再确认下:
effective_preds = torch.cat((cls_preds[pos_indices], neg_cls_preds[neg_indices]))
targets = torch.cat((pos_targets, neg_targets))
Ahh sorry.. 分类Loss肯定是要包含正负样本的,回归Loss只会包含正样本(负样本没办法回归)
分类损失和回归损失都除以了(正样本+负样本)个数,都是400.
所以这里 回归损失 并没有除以所有样本数,只除以了正样本数,因为:
loss_reg = F.smooth_l1_loss(total_t, total_gt)
如果你跟一下 total_t 和 和 total_gt,是只包含正样本的
smooth_l1_loss中的total_t, total_gt确实只包含正样本.这点没问题.
对于loss_reg = F.smooth_l1_loss(total_t, total_gt),参数size_average默认为True,即要除以样本数.
我一开始和你认为一样,既然total_t, total_gt只包含了正样本,那么在计算smooth_l1_loss时,除以的就应该是(正样本)个数(100).但是昨天在发现,虽然total_t, total_gt只包含了正样本,但是在计算smooth_l1_loss时,除以的却是(正样本+负样本)个数(400). 你可以debug跟一下.
https://github.com/pytorch/pytorch/blob/eb3cabffd69e37162a3fe0bb1bbfa3de83404f3a/torch/nn/modules/loss.py#L748-L751
因为 smooth_l1_loss 的每个样本都含有4个值(坐标),所以最后 reduction = 'mean' 在算均值的时候,实际是除以 样本数 * 4 ,所以这里除了400,这个400并不是正样本+负样本。所以这里应该修改为:
loss_reg = F.smooth_l1_loss(total_t, total_gt, reduction='sum') / total_t.size(0)
确实是个问题,感谢提出!会抽空修复这个问题。另外也非常欢迎提PR
虽然结果一样,但我还是理解错了,也谢谢你的提醒.
另外对于master分支,其实不用改,本身就是:
loss_class = F.cross_entropy( total_effective_pred, total_targets)
loss_reg = F.smooth_l1_loss(total_t, total_gt)
loss = loss_class + loss_reg
我是基于training-v2这个分支分析时,才发现了这个权重4.