为什么 roi_align 在 pytorch 中似乎不起作用?
Why does roi_align not seem to work in pytorch?
我是pytorch初学者。 pytorch中的RoIAlign模块好像有bug。代码很简单,但结果出乎我的意料。
代码:
import torch
from torchvision.ops import RoIAlign
if __name__ == '__main__':
output_size = (3,3)
spatial_scale = 1/4
sampling_ratio = 2
#x.shape:(1,1,6,6)
x = torch.FloatTensor([[
[[1,2,3,4,5,6],
[7,8,9,10,11,12],
[13,14,15,16,17,18],
[19,20,21,22,23,24],
[25,26,27,28,29,30],
[31,32,33,34,35,36],],
]])
rois = torch.tensor([
[0,0.0,0.0,20.0,20.0],
])
channel_num = x.shape[1]
roi_num = rois.shape[0]
a = RoIAlign(output_size, spatial_scale=spatial_scale, sampling_ratio=sampling_ratio)
ya = a(x, rois)
print(ya)
输出:
tensor([[[[ 6.8333, 8.5000, 10.1667],
[16.8333, 18.5000, 20.1667],
[26.8333, 28.5000, 30.1667]]]])
但在这种情况下,不应该是对每个 2x2 单元格进行平均池化操作,例如:
tensor([[[[ 4.5000, 6.5000, 8.5000],
[16.5000, 18.5000, 20.5000],
[28.5000, 30.5000, 32.5000]]]])
我的手电筒版本是 1.3.0,带有 python3.6 和 cuda 10.1,在 Ubuntu16 上。困扰了两天,如果有人能帮助我,我将不胜感激。
直观解读
图像坐标有些复杂。我们需要考虑到像素实际上是正方形而不是 space 中的点这一事实。我们将像素的中心解释为整数坐标,例如 (0,0) 指的是第一个像素的中心,而 (-0.5, -0.5) 指的是第一个像素的左上角。基本上这就是您没有得到预期结果的原因。从 (0,0) 到 (5,5) 的 roi 实际上会切穿边界像素,并导致在执行 roi 对齐时在像素之间进行采样。相反,如果我们将 roi 定义为从 (-0.5, -0.5) 到 (5.5, 5.5),那么我们会得到预期的结果。考虑到比例因子,这转化为从 (-2, -2) 到 (22, 22) 的 roi。
import torch
from torchvision.ops import RoIAlign
output_size = (3, 3)
spatial_scale = 1 / 4
sampling_ratio = 2
x = torch.FloatTensor([[
[[1, 2, 3, 4, 5, 6 ],
[7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18],
[19, 20, 21, 22, 23, 24],
[25, 26, 27, 28, 29, 30],
[31, 32, 33, 34, 35, 36]]
]])
rois = torch.tensor([
[0, -2.0, -2.0, 22.0, 22.0],
])
a = RoIAlign(output_size, spatial_scale=spatial_scale, sampling_ratio=sampling_ratio)
ya = a(x, rois)
print(ya)
这导致
tensor([[[[ 4.5000, 6.5000, 8.5000],
[16.5000, 18.5000, 20.5000],
[28.5000, 30.5000, 32.5000]]]])
另类解读
将区间 [0, 5] 分成 3 个等长区间得到 [0, 1.67], [1.67, 3.33], [3.33, 5]。所以输出的边界 window 会落在这些坐标中。显然,这不会导致很好的采样结果。
我是pytorch初学者。 pytorch中的RoIAlign模块好像有bug。代码很简单,但结果出乎我的意料。
代码:
import torch
from torchvision.ops import RoIAlign
if __name__ == '__main__':
output_size = (3,3)
spatial_scale = 1/4
sampling_ratio = 2
#x.shape:(1,1,6,6)
x = torch.FloatTensor([[
[[1,2,3,4,5,6],
[7,8,9,10,11,12],
[13,14,15,16,17,18],
[19,20,21,22,23,24],
[25,26,27,28,29,30],
[31,32,33,34,35,36],],
]])
rois = torch.tensor([
[0,0.0,0.0,20.0,20.0],
])
channel_num = x.shape[1]
roi_num = rois.shape[0]
a = RoIAlign(output_size, spatial_scale=spatial_scale, sampling_ratio=sampling_ratio)
ya = a(x, rois)
print(ya)
输出:
tensor([[[[ 6.8333, 8.5000, 10.1667],
[16.8333, 18.5000, 20.1667],
[26.8333, 28.5000, 30.1667]]]])
但在这种情况下,不应该是对每个 2x2 单元格进行平均池化操作,例如:
tensor([[[[ 4.5000, 6.5000, 8.5000],
[16.5000, 18.5000, 20.5000],
[28.5000, 30.5000, 32.5000]]]])
我的手电筒版本是 1.3.0,带有 python3.6 和 cuda 10.1,在 Ubuntu16 上。困扰了两天,如果有人能帮助我,我将不胜感激。
直观解读
图像坐标有些复杂。我们需要考虑到像素实际上是正方形而不是 space 中的点这一事实。我们将像素的中心解释为整数坐标,例如 (0,0) 指的是第一个像素的中心,而 (-0.5, -0.5) 指的是第一个像素的左上角。基本上这就是您没有得到预期结果的原因。从 (0,0) 到 (5,5) 的 roi 实际上会切穿边界像素,并导致在执行 roi 对齐时在像素之间进行采样。相反,如果我们将 roi 定义为从 (-0.5, -0.5) 到 (5.5, 5.5),那么我们会得到预期的结果。考虑到比例因子,这转化为从 (-2, -2) 到 (22, 22) 的 roi。
import torch
from torchvision.ops import RoIAlign
output_size = (3, 3)
spatial_scale = 1 / 4
sampling_ratio = 2
x = torch.FloatTensor([[
[[1, 2, 3, 4, 5, 6 ],
[7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18],
[19, 20, 21, 22, 23, 24],
[25, 26, 27, 28, 29, 30],
[31, 32, 33, 34, 35, 36]]
]])
rois = torch.tensor([
[0, -2.0, -2.0, 22.0, 22.0],
])
a = RoIAlign(output_size, spatial_scale=spatial_scale, sampling_ratio=sampling_ratio)
ya = a(x, rois)
print(ya)
这导致
tensor([[[[ 4.5000, 6.5000, 8.5000],
[16.5000, 18.5000, 20.5000],
[28.5000, 30.5000, 32.5000]]]])
另类解读
将区间 [0, 5] 分成 3 个等长区间得到 [0, 1.67], [1.67, 3.33], [3.33, 5]。所以输出的边界 window 会落在这些坐标中。显然,这不会导致很好的采样结果。