lilanxiao/Rotated_IoU

大佬,求助,CUDA out of memory

LUO77123 opened this issue · 12 comments

大佬,我用cal_iou求解旋转iou时候,进行广播机制,导致B和N就特别大,导致直接爆掉了,A100我降batchsize没用,有没有解决的办法喃。
image

你在cal_iou的输入是什么形状的呢?
我的代码有的地方用的是暴力穷举,开销挺大的。B和N太大了确实算不动。

你在cal_iou的输入是什么形状的呢? 我的代码有的地方用的是暴力穷举,开销挺大的。B和N太大了确实算不动。

大佬,代码基本没变,就是B,N太大了,目前我写了循环进去,以200为限,求解cal_iou,在concat拼接,另外发现一个bug,cal_iou计算iou时候,iou可能变成非常大的数,查找原因是,输入的box2(预测框)长=501,宽=0.0004,导致iou=4000多,这类框的iou最后直接替换成0。
大佬,毕业论文想引用你的iou计算文章,可以吗,还有就是后面GitHub上传yolov5或者yolov7旋转检测使用您的iou计算,想拉取一下链接,可以不。

这种循环拼接确实很消耗显存,因为必须保存之前所有梯度。我感觉OOM了是正常的。
关于这个bug:你这里使用的长宽比非常极端,我确实没有测试过这种情况。我建议你试试我debug branch上的另一个版本,并且在计算loss的时候强制使用torch.double数据类型。这样应该会稳定一些,但是开销也还要再大一点。
欢迎引用或者改写这个repo,都是没有限制的,因为我用的是MIT协议。

debug branch

大佬,我用的就是debug branch版本,主要是在使用simota,需要求iou矩阵,目标400多个,预测框5000多个,广播机制400就变成B,5000就变成了N,我只有循环拼接。我都一直降B,N大小,还是报错
image
哪些中间值是可以删掉的喃,大佬

我其实不熟悉simota。我不知道你的IoU矩阵是不是真的需要梯度信息。如果不需要梯度,可以直接在循环内部计算IoU的地方取消梯度。这样应该就不爆显存了。

with torch.no_grad():
    # calculate IoU
    # ... ....

如果需要400x5000的IoU矩阵还带梯度,我暂时想不到什么简单的解决方法。

我其实不熟悉simota。我不知道你的IoU矩阵是不是真的需要梯度信息。如果不需要梯度,可以直接在循环内部计算IoU的地方取消梯度。这样应该就不爆显存了。

with torch.no_grad():
    # calculate IoU
    # ... ....

如果需要400x5000的IoU矩阵还带梯度,我暂时想不到什么简单的解决方法。

谢谢大佬回复,我问问v7的作者需要更新梯度不,不需要我就with torch.no_grad():十分感谢

我其实不熟悉simota。我不知道你的IoU矩阵是不是真的需要梯度信息。如果不需要梯度,可以直接在循环内部计算IoU的地方取消梯度。这样应该就不爆显存了。

with torch.no_grad():
    # calculate IoU
    # ... ....

如果需要400x5000的IoU矩阵还带梯度,我暂时想不到什么简单的解决方法。

大佬,您在计算riou的具体方法有吗,除了(1.计算预测框与GT框的面积;2.确定两个框交点区域的顶点有两种方法:一种是两个BBox的边的交点,另一种是BBox在另一个BBox内的角。如果顶点不存在,则 IoU 值为零。3.理论上,这些顶点形成一个凸包。为了计算这个凸包的面积,我们需要按逆时针(或顺时针)顺序对顶点进行排序。首先,计算这些顶点的中心点。然后,计算每个顶点与中心形成的旋转角度。最后,可以按旋转角度对顶点进行排序。4. 然后,通过将其划分为小的单个三角形来获得相交区域。5. 根据方程式计算 IoU 值),是否还有更具体一点喃,想引用到论文里

你在cal_iou的输入是什么形状的呢? 我的代码有的地方用的是暴力穷举,开销挺大的。B和N太大了确实算不动。

大佬,还有一个问题,您的代码中,所有计算iou代码中,每次计算的中间值我都删掉了,这样影响梯度反传吗,能这样操作吗,例如:
image
image
image

这种循环拼接确实很消耗显存,因为必须保存之前所有梯度。我感觉OOM了是正常的。 关于这个bug:你这里使用的长宽比非常极端,我确实没有测试过这种情况。我建议你试试我debug branch上的另一个版本,并且在计算loss的时候强制使用torch.double数据类型。这样应该会稳定一些,但是开销也还要再大一点。 欢迎引用或者改写这个repo,都是没有限制的,因为我用的是MIT协议。

大佬,前面2个问题,这是第三个问题,您看到可以解答一下吗?
您代码求diou时候,用的enclosing_box 返回外接矩形的宽和高,与cv2.minAreaRect()函数计算并返回指定点集的最小区域边界斜矩形的宽高有什么不一样吗?
image

大佬,您在计算riou的具体方法有吗,除了(1.计算预测框与GT框的面积;2.确定两个框交点区域的顶点有两种方法:一种是两个BBox的边的交点,另一种是BBox在另一个BBox内的角。如果顶点不存在,则 IoU 值为零。3.理论上,这些顶点形成一个凸包。为了计算这个凸包的面积,我们需要按逆时针(或顺时针)顺序对顶点进行排序。首先,计算这些顶点的中心点。然后,计算每个顶点与中心形成的旋转角度。最后,可以按旋转角度对顶点进行排序。4. 然后,通过将其划分为小的单个三角形来获得相交区域。5. 根据方程式计算 IoU 值),是否还有更具体一点喃,想引用到论文里

你可以引用这一篇:https://arxiv.org/pdf/1908.03851.pdf
这应该是某一年的3DV会议论文。

大佬,还有一个问题,您的代码中,所有计算iou代码中,每次计算的中间值我都删掉了,这样影响梯度反传吗,能这样操作吗

我没试过,你可以自己试试。我感觉是可以的,但是没有必要。PyTorch会自动释放这些中间变量。

大佬,前面2个问题,这是第三个问题,您看到可以解答一下吗? 您代码求diou时候,用的enclosing_box 返回外接矩形的宽和高,与cv2.minAreaRect()函数计算并返回指定点集的最小区域边界斜矩形的宽高有什么不一样吗?

结果应该是一样的,但是方法不一样。我的代码为了方便并行和反向传播,用的是暴力穷举。opencv使用的是更一般性的,更优雅的算法。