rotmmdet
rotmmdet copied to clipboard
GD Loss Training showed NaN in custom dataset
Hi!请问用GD loss(KLD和GWD)是不是容易引起梯度爆炸?我在自定义的数据上表现出的梯度爆炸的情况,前几个iteration还ok,但是后面就直接nan了,期待您的答复~
大佬好! 我这边试验下来不会。当然我不清楚您这边是用的哪一种representation,representation搞错了就特别容易nan。
这里有个小坑,我用的默认的representation是xy_stddev_pearson。然鹅大部分的旋转检测都用的是xy_wh_r。我之所以这么搞,是因为这个repo是专用于yoloR的,而yoloR对检测框的表达方式是xy_stddev_pearson(这玩意我论文还没写,本质上是基于yoloV4、V5改的旋转检测,试下来性能很不错) https://github.com/zhanggefan/rotmmdet/blob/3878da53f72fb2b3fb92f2164d706231c5c21319/mmdetrot/models/losses/gaussian_distance_loss.py#L181-L193
记得在配置里改一下哈
另外,别忘了加grad clip。
哈哈哈,我看了GDLoss这块的源码,我也尝试过xy_stddev_pearson和xy_wh_r的,也包括加入了grad_clip=dict(max_norm=35, norm_type=2),但是还是会发生NaN的,包括用了S2ANet那套IOU Loss,结果都NaN,但是用Smooth L1 Loss就不会出现梯度爆炸。emm,也可能是我的代码哪出了问题吧,我再debug一下; 哦对了,你有把你们的GDLoss用在S2ANet上么?比较想知道你们用GDLoss在S2ANet跑的效果,哈哈哈; 第二个问题是,会不会是因为刚开始训练那段时间的预测框定位的不够精准导致的NaN,也就是初期阶段IOU的确就趋近于0(但是可能性不大,因为我是要做label assignment的,阳性样本上不可能明显存在这种情况),然后就梯度爆炸了,我是有想过先用Smooth L1 loss训练,然后后面用GDLoss fine tuning一下的,但是这样没解决根本问题,模型训练还是不稳定; 第三个问题是,这个GDLoss训练时候稳定么?以及梯度回传是不是比较小,也就是说会不会难以收敛? 感谢您的答复~
其实我这个代码是我公司业务代码的开源版本。我在我的数据集上从来没出现过梯度爆炸,训练也非常的稳定。。。但是我还没有在DOTA等遥感数据上测试过这个代码。我确实有这个计划进一步在遥感上调试,但确实工作太忙了。。。
对了,Smooth L1 loss能行,IOU Loss不行,GD Loss也不行,会不会是因为没有decode?我之前有个兄弟在实验的时候,直接对pred-diff和gt-diff做了GD Loss,最后也是发散了,后来发现IOU Loss和GD Loss都是pred-box对gt-box,于是先做了decode再算loss以后,就收敛了。我这个代码做了微调以后,用在了3D检测上(我本职工作是lidar点云目标检测),用的也是anchor based的模型,也没发散过。
当然还有另一种可能性。我之所以不出现nan,也许和我一直使用fp16训练有关系,fp16因为有loss scaler的特殊逻辑,当loss算出来为inf的时候,是不进行反向传播的,可能因此恰好躲开了一部分可能导致梯度爆炸的梯度更新。
至于GDLoss用在S2A上,我印象中杨学组里有人跑过(我这个版本的代码之前他们还有个迭代求解版的GWD,后来应该已经更新成我这个代码的类似版了)你如果在旋转检测群里的话可以问下他
感谢您的答复,祝好!
请问xy_stddev_pearson的含义是什么,我之前没见过这种表达,并且xy_wh_r是怎么转到xy_stddev_pearson的啊?
请问xy_stddev_pearson的含义是什么,我之前没见过这种表达,并且xy_wh_r是怎么转到xy_stddev_pearson的啊?
您好!
这个xy_stddev_pearson的表达方法应该是这个repo里面首创的,我之前没有在其他地方看过类似的表达方式。我因为工作业务繁重,没时间发paper,因此没有公开的资料说明,请您见谅呀!
他的含义是:一个XY二维高斯分布,可以通过描述其X边缘高斯分布、Y边缘高斯分布、以及XY相关系数来唯一确定。这里的trick是,xy_stddev直接可以用来表达一个水平框,那么一个水平框加上pearson系数就得到了旋转框;水平框尺寸很接近于斜框的外界水平框,但又不太一样。
如下图,当xy_stddev相同,但pearson不同的时候,会得到如下不同的旋转框(其中peason=0的时候恰好为水平框,这个水平框被用来做gt assign):
对于yolov4、v5这种大量使用sigmoid作为激活函数的网络,通过使用sigmoid(tanh)激活函数来得到pearson系数非常合适,不会有值域问题;而同时xy_stddev又可以直接兼容2D水平框检测,原本的yolov5的box decode、gt assign代码可以直接拿来用。如此一来,只需要在yolov4、v5的基础上多预测一个pearson就改成了旋转检测器了。总之是一种投机取巧的方法。
转法是这样: xy_wh_r -> 均值和协方差矩阵 均值 -> X、Y边缘均值 协方差矩阵对角线元素 -> X、Y边缘方差 协方差矩阵非对角线元素除以行列式开方 -> X、Y相关系数pearson