【发布时间】:2021-07-02 20:07:46
【问题描述】:
我有一个形状为(3,3) 的数组A,可以将其视为形状为(5,) 的未知数组的滑动窗口视图。我想计算形状为(5,) 的数组的倒数。这个的伴随操作将是求和。我的意思是,我想将每个对应窗口中的值与数组中的相关位置累积起来,形状为(5,)。当然,我对这个反函数的预期输出和输入A 不相关,只是普通数组。我有两个例子,希望能更好地解释这一点。
A = np.array([[0, 0, 1],
[0, 0, 1],
[0, 0, 1]], dtype=np.float32)
我期望这个输出:
np.array([0, 0, 1, 1, 1])
另一个例子:
A = np.array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5]], dtype=np.float32)
我期望这个输出:
np.array([1, 2+2, 3+3+3, 4+4, 5]) = np.array([1, 4, 9, 8, 5])
我的解决方案很慢(结果存储在out)
out = np.zeros(5, dtype=np.float32)
windows = np.lib.stride_tricks.as_strided(out, shape=(3,3), strides=(4,4))
for i in np.ndindex(windows.shape):
windows[i] += A[i]
写一个跨步视图感觉有点笨拙,我相信有更好的解决方案。
有没有办法以向量化的方式编写它,而不需要 for 循环? (也适用于多个维度)
编辑
就更高维度的泛化而言,我有一些情况是从图像(二维数组)中获取窗口,而不是像上面的示例那样从一维数组中获取。对于二维情况,A 可以是大小为3 的窗口。这意味着从形状为(4,4) 的图像(输出)中,窗口A 的形状为(2,2,3,3)。
A = np.array([[[[0, 0, 0],
[0, 1, 0],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 0],
[0, 0, 0]]],
[[[0, 1, 0],
[0, 0, 0],
[0, 0, 0]],
[[1, 0, 0],
[0, 0, 0],
[0, 0, 0]]]], dtype=np.float32)
使用Pablo给出的解决方案,我得到以下错误
value array of shape (2,2,3,3) could not be broadcast to indexing result of shape (2,2)
使用我的步幅解决方案的略微修改版本:
def inverse_sliding_windows(A, window_sz, image_sz):
out = np.zeros(image_sz, dtype=np.float32)
windows = np.lib.stride_tricks.sliding_window_view(out, window_sz, writeable=True)
for i in np.ndindex(windows.shape):
windows[i] += A[i]
window_sz = (3,3)
image_sz = (4,4)
inverse_sliding_windows(A, window_sz, image_sz)
输出:
array([[0., 0., 0., 0.],
[0., 4., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]], dtype=float32)
为了澄清,窗口大小和输出形状是预先知道的,请参阅inverse_sliding_windows。
【问题讨论】:
-
我们是在说,在一般情况下,nxn 数组和输出
2*n-1? -
为简单起见,窗口的尺寸相同。所以是的,所有窗口
A的数组将是一个 nxn 数组。这意味着对于 1d 情况,输出的大小为2*n-1。 -
对于窗口大小为
3的 2d 案例,我希望它从形状(2,2,3,3)变为形状(4,4)。 -
这是否相当于将矩阵旋转-45度并逐行求和?
-
矢量化版本并不总能保证更好的运行时间。矩阵旋转方法非常低效。我确实有一个使用 for 循环的 2D 案例的解决方案,我相信它比矩阵旋转和其他天真的向量化的要快得多。话虽如此,您可能必须决定哪个更重要 - 矢量化或运行时间。如果不需要更高维度的泛化,我会在这里发布。否则,您能否将问题简化为更高维度?
标签: python python-3.x numpy vectorization