带滑动窗口的Numpy求和非常慢
代码:带滑动窗口的Numpy求和非常慢,numpy,sliding-window,numpy-slicing,Numpy,Sliding Window,Numpy Slicing,代码: 它可以工作,但最后两行需要花费很多时间,因为它们将在循环中。问题是“grid”变量包含一个窗口数组。我现在不知道如何加快这个过程 让我们一点一点地简化问题-减少维度,并去掉最终的尺寸3维: shape = np.array([6, 6]) grid = np.array([x.ravel() for x in np.meshgrid(*[np.arange(x) for i, x in enumerate(shape)], indexing='ij')]).T slices = [tup
它可以工作,但最后两行需要花费很多时间,因为它们将在循环中。问题是“grid”变量包含一个窗口数组。我现在不知道如何加快这个过程 让我们一点一点地简化问题-减少维度,并去掉最终的尺寸3维:
shape = np.array([6, 6])
grid = np.array([x.ravel() for x in np.meshgrid(*[np.arange(x) for i, x in enumerate(shape)], indexing='ij')]).T
slices = [tuple(slice(box[i], box[i] + 2) for i in range(len(box))) for box in grid]
score = np.zeros((7,7,3))
column = np.random.randn(36, 12) #just for example
column
>> array([[ 0, 1, 2, 3, ... 425, 426, 427, 428, 429, 430, 431]])
column = column.reshape((16, 3, 3, 3))
for i, window in enumerate(slices):
score[window] += column[i]
score
>> array([[[0.000e+00, 1.000e+00, 2.000e+00],
[3.000e+01, 3.200e+01, 3.400e+01],
[9.000e+01, 9.300e+01, 9.600e+01], ...
[8.280e+02, 8.300e+02, 8.320e+02],
[4.290e+02, 4.300e+02, 4.310e+02]]])
这是一个移动窗口-一(3,3)数组,移位1,…,下移1,等等
使用as_stripped
可以构建数组的视图,该视图由所有这些窗口组成,但不需要实际复制值。在我能够构建如下等效步幅之前,我已经使用了as_-stride
:
In [265]: shape = np.array([4,4])
In [266]: grid = np.array([x.ravel() for x in np.meshgrid(*[np.arange(x) for i
...: , x in enumerate(shape)], indexing='ij')]).T
...: grid = [tuple(slice(box[i], box[i] + 3) for i in range(len(box))) fo
...: r box in grid]
...:
...:
In [267]: len(grid)
Out[267]: 16
In [268]: score = np.arange(36).reshape(6,6)
In [269]: X = np.array([score[x] for x in grid]).reshape(4,4,3,3)
In [270]: X
Out[270]:
array([[[[ 0, 1, 2],
[ 6, 7, 8],
[12, 13, 14]],
[[ 1, 2, 3],
[ 7, 8, 9],
[13, 14, 15]],
[[ 2, 3, 4],
[ 8, 9, 10],
[14, 15, 16]],
....
[[21, 22, 23],
[27, 28, 29],
[33, 34, 35]]]])
这可以扩展到你的(28,28,3)维,并转化为求和
生成这样的移动窗口已在前面的SO问题中介绍过。它也在一个图像处理软件包中实现
适用于3通道图像
In [271]: score.shape
Out[271]: (6, 6)
In [272]: score.strides
Out[272]: (48, 8)
In [273]: ast = np.lib.stride_tricks.as_strided
In [274]: x=ast(score, shape=(4,4,3,3), strides=(48,8,48,8))
In [275]: np.allclose(X,x)
Out[275]: True
因为我们一次移动一个元素,所以x
的步幅很容易从源步幅中导出
对于4x4车窗,只需更改形状即可
In [45]: arr.shape
Out[45]: (6, 6, 3)
In [46]: arr.strides
Out[46]: (144, 24, 8)
In [47]: arr[:3,:3,0]
Out[47]:
array([[ 0., 1., 2.],
[ 6., 7., 8.],
[12., 13., 14.]])
In [48]: x = ast(arr, shape=(4,4,3,3,3), strides=(144,24,144,24,8))
In [49]: x[0,0,:,:,0]
Out[49]:
array([[ 0., 1., 2.],
[ 6., 7., 8.],
[12., 13., 14.]])
在 @Divikar建议使用
skiliage
使用默认的步骤=1
,结果是兼容的:
x = ast(arr, shape=(3,3,4,4,3), strides=(144,24,144,24,8))
让我们一点一点地简化问题-减少维度,并去掉最终的尺寸3维:
shape = np.array([6, 6])
grid = np.array([x.ravel() for x in np.meshgrid(*[np.arange(x) for i, x in enumerate(shape)], indexing='ij')]).T
slices = [tuple(slice(box[i], box[i] + 2) for i in range(len(box))) for box in grid]
score = np.zeros((7,7,3))
column = np.random.randn(36, 12) #just for example
column
>> array([[ 0, 1, 2, 3, ... 425, 426, 427, 428, 429, 430, 431]])
column = column.reshape((16, 3, 3, 3))
for i, window in enumerate(slices):
score[window] += column[i]
score
>> array([[[0.000e+00, 1.000e+00, 2.000e+00],
[3.000e+01, 3.200e+01, 3.400e+01],
[9.000e+01, 9.300e+01, 9.600e+01], ...
[8.280e+02, 8.300e+02, 8.320e+02],
[4.290e+02, 4.300e+02, 4.310e+02]]])
这是一个移动窗口-一(3,3)数组,移位1,…,下移1,等等
使用as_stripped
可以构建数组的视图,该视图由所有这些窗口组成,但不需要实际复制值。在我能够构建如下等效步幅之前,我已经使用了as_-stride
:
In [265]: shape = np.array([4,4])
In [266]: grid = np.array([x.ravel() for x in np.meshgrid(*[np.arange(x) for i
...: , x in enumerate(shape)], indexing='ij')]).T
...: grid = [tuple(slice(box[i], box[i] + 3) for i in range(len(box))) fo
...: r box in grid]
...:
...:
In [267]: len(grid)
Out[267]: 16
In [268]: score = np.arange(36).reshape(6,6)
In [269]: X = np.array([score[x] for x in grid]).reshape(4,4,3,3)
In [270]: X
Out[270]:
array([[[[ 0, 1, 2],
[ 6, 7, 8],
[12, 13, 14]],
[[ 1, 2, 3],
[ 7, 8, 9],
[13, 14, 15]],
[[ 2, 3, 4],
[ 8, 9, 10],
[14, 15, 16]],
....
[[21, 22, 23],
[27, 28, 29],
[33, 34, 35]]]])
这可以扩展到你的(28,28,3)维,并转化为求和
生成这样的移动窗口已在前面的SO问题中介绍过。它也在一个图像处理软件包中实现
适用于3通道图像
In [271]: score.shape
Out[271]: (6, 6)
In [272]: score.strides
Out[272]: (48, 8)
In [273]: ast = np.lib.stride_tricks.as_strided
In [274]: x=ast(score, shape=(4,4,3,3), strides=(48,8,48,8))
In [275]: np.allclose(X,x)
Out[275]: True
因为我们一次移动一个元素,所以x
的步幅很容易从源步幅中导出
对于4x4车窗,只需更改形状即可
In [45]: arr.shape
Out[45]: (6, 6, 3)
In [46]: arr.strides
Out[46]: (144, 24, 8)
In [47]: arr[:3,:3,0]
Out[47]:
array([[ 0., 1., 2.],
[ 6., 7., 8.],
[12., 13., 14.]])
In [48]: x = ast(arr, shape=(4,4,3,3,3), strides=(144,24,144,24,8))
In [49]: x[0,0,:,:,0]
Out[49]:
array([[ 0., 1., 2.],
[ 6., 7., 8.],
[12., 13., 14.]])
在 @Divikar建议使用
skiliage
使用默认的步骤=1
,结果是兼容的:
x = ast(arr, shape=(3,3,4,4,3), strides=(144,24,144,24,8))
添加样本数据?请检查并包括所需的样本输出。最后两行似乎很容易矢量化。。。纯python for循环的迭代和求和速度非常慢。。矢量化操作正好解决了这一问题。你的意思是我可以使用np.vectorize()对它们进行矢量化吗?在对代码进行了一些调整之后,我在两个部分上尝试了`%%timeit。设置平均为5ms,循环平均为6ms。差别不大。在600+范围内的迭代将需要时间。添加样本数据?请查看并包含所需的样本输出。最后两行似乎很容易矢量化。。。纯python for循环的迭代和求和速度非常慢。。矢量化操作正好解决了这一问题。你的意思是我可以使用np.vectorize()对它们进行矢量化吗?在对代码进行了一些调整之后,我在两个部分上尝试了`%%timeit。设置平均为5ms,循环平均为6ms。差别不大。600+范围内的迭代将需要时间。确定。我还不熟悉as_-stride函数。“步长”参数的含义是什么?
strips
是numpy数组的基本属性(以及shape
和dtype
)。这是使这个多维代码如此强大的部分原因。但是它在中的使用是一个相当高级的主题,我已经更新了我的代码。我知道你的解决方案可以转化为求和,但在我的特殊情况下,我希望结果是“分数”形状,因为我想迭代地将“列”添加到“分数”变量中。我会接受答案,但我有一点其他问题OK。我还不熟悉as_-stride函数。“步长”参数的含义是什么?strips
是numpy数组的基本属性(以及shape
和dtype
)。这是使这个多维代码如此强大的部分原因。但是它在中的使用是一个相当高级的主题,我已经更新了我的代码。我知道你的解决方案可以转化为求和,但在我的特殊情况下,我希望结果是“分数”形状,因为我想迭代地将“列”添加到“分数”变量中。我会接受答案,但我有一点其他问题