HikariTJU / LD

Localization Distillation for Object Detection (CVPR 2022, TPAMI 2023)
Apache License 2.0
355 stars 51 forks source link

关于GI(General Instance) Feature-based Distillation 实现的问题 #33

Open flazerain opened 2 years ago

flazerain commented 2 years ago

我注意到您代码里的实现: idx_out = torch.ops.torchvision.nms(gibox, giscore, 0.3)[:10] return idx_out

gi_idx = self.get_gi_region(soft_label, cls_score, anchors, bbox_pred, soft_targets, stride) gi_teacher = teacher_x[gi_idx] gi_student = x[gi_idx] loss_im = self.loss_im(gi_student, gi_teacher)

并没有像GI 论文里那样使用GIbox ROIAlign 进行FM。

这样的话只选了10个FPN像素进行FM,而且经过NMS 这10个GI box像素附近的点也大概率被抑制掉了,这些像素应该也是信息量比较大的像素。

请问你们这样实现是为什么呢?有试过原文的做法吗,效果怎么样?

Zzh-tju commented 2 years ago

特征图上相邻两个点的步长可以差距很大,一个GI location的相邻点未必也是师生分类差距大的点,而使用GI box蒸馏范围就会很大。特别是对于大物体的P3层,如果使用GI box,也就是学生或教师预测框,那么几乎整张图都是蒸馏区域,我们认为这与GI的设计理念有所冲突。说白了,它的GI想要蒸馏的是师生分类得分差距较大的点,而且还使用了NMS就是为了挑选出一个较为离散的区域。但是box内部的点可未必都是师生差距大的点。要知道对于单阶段检测器,特征图上每个点都是一个独立的分类器与定位器,思想上来说你想找出分类差距大的地方蒸馏,就应该尽量避免让分类差距小的地方也参与蒸馏。

此外,RoI Align会消耗额外的运算,减慢训练速度。而且我们无法得知它的RoI Align后的分辨率是多少。它论文没有提及,同时这也是个未开源的工作。其论文提到,引入RoI Align的目的是降低大物体预测框包含的点太多会造成网络更多倾向于大物体。这是有待考证的,因为一旦使用RoI Align把GI box都resize到相同的尺寸,小物体的梯度又会成碾压之势。从它的GISM来看,它似乎是使用所有预测框来做。而分类较为困难的,师生会产生较大分歧的往往是小物体。大物体则相对简单,师生的一致性较好。因此它挑选出的GI box会更多集中在小物体上。而我们由于是在每个FPN层都选了10个点,因此也就无需引入额外的模块来对齐尺寸。(PS: 如果它的GISM也是每个FPN层都选10个GI box,那它使用RoI Align的这个平衡思想与我们就一致。区别是它让大量相邻点也参与了蒸馏。)

因此要实现完整的基于GI box的feature imitation至少要经过RoI Align后尺寸大小的调参,loss weight的调参。经过初步尝试的性能是还不如我们论文实现的简单使用10个GI location,且我们的方法简洁干净。注意到GI论文里RetinaNet ResNet-101蒸馏ResNet-50训练2x的GI box Feature imitation的汇报结果是提高1.7。且注意到它的这项蒸馏loss weight已经低到5e-4了,这表明它的这个实现对超参更为敏感,更需要精细调参。我们是GFocal ResNet-101蒸馏ResNet-50训练1x的GI location Feature imitation提高1.4,loss weight不用改变,性能涨幅差距不大的。

flazerain commented 2 years ago

确实GIbox内部的点未必都是师生差距大的点,但是我观察了一下计算结果,这10个点附近还是有很多差异大的点被抑制掉了,不如不用nms。要把bbox预测的影响考虑进去的话,差异大的点的评价也可以综合考虑score 和bbox。

另外实现里面两个batch一起做nms好像也不太对...

Zzh-tju commented 2 years ago

你是训练前期观察到的还是在训练最后几个epoch观察到的

Zzh-tju commented 2 years ago

两个batch内部做效果更好,我怀疑是如果使用对单张图做loss weight得再调。还有,单张图做就得加for循环搞nms,或者呈平方增长加大IoU矩阵大小

Zzh-tju commented 2 years ago

GI我认为是提供了一个动态蒸馏的好思路。我实际上后续想搞动态蒸馏区域的LD,尝试了改变NMS时的score,有使用分类差距,或者1-IoU定位差距,亦或者二者的结合搞LD,但最好性能只在41.4左右,距离main LD + VLR LD的41.8还有一点距离,随后我就弃疗了

flazerain commented 2 years ago

你是训练前期观察到的还是在训练最后几个epoch观察到的

前期吧,虽然加载了预训练模型

flazerain commented 2 years ago

两个batch内部做效果更好,我怀疑是如果使用对单张图做loss weight得再调。还有,单张图做就得加for循环搞nms,或者呈平方增长加大IoU矩阵大小

单张图做就得加for循环搞nms,或者呈平方增长加大IoU矩阵大小

这个是什么意思呢?

Zzh-tju commented 2 years ago

两个batch内部做效果更好,我怀疑是如果使用对单张图做loss weight得再调。还有,单张图做就得加for循环搞nms,或者呈平方增长加大IoU矩阵大小

单张图做就得加for循环搞nms,或者呈平方增长加大IoU矩阵大小

这个是什么意思呢?

一个batch不止一张图,做GI正常来说是每张图10个点。因此在loss_single里必须拆开成两个tensor搞NMS,不能合在一起。

而我们的实现中,是一个batch两张图合在一起,在每个FPN level上选了10个GI点。因为loss_single的输入就是两张图进来