如何更快地获取子矩阵块?

时间:2019-01-24 06:50:38

标签: python python-3.x numpy

我有一个非常大的矩阵(nxn),为此,我将构建尺寸为mxm的相交切片(子矩阵)。每个连续子矩阵之间的偏移量为step。这是n=8, m=4, step=2的示例:

import numpy as np
matrix=np.random.randn(8,8)
n=matrix.shape[0]
m=4
step=2

这将存储所有拐角索引(x,y),我们将从中获取一个4x4的矩阵:(x:x+4,x:x+4)

a={(i,j) for i in range(0,n-m+1,step) for j in range(0,n-m+1,step)}

子矩阵将像这样提取

sub_matrices = np.zeros([m,m,len(a)])
for i,ind in enumerate(a):
    x,y=ind
    sub_matrices[:,:,i]=matrix[x:x+m, y:y+m]

有没有更快的方法来执行此子矩阵初始化?

2 个答案:

答案 0 :(得分:3)

我们可以利用基于np.lib.stride_tricks.as_stridedscikit-image's view_as_windows来获取滑动窗口。 More info on use of as_strided based view_as_windows

from skimage.util.shape import view_as_windows   

# Get indices as array 
ar = np.array(list(a))

# Get all sliding windows
w = view_as_windows(matrix,(m,m))

# Get selective ones by indexing with ar
selected_windows = np.moveaxis(w[ar[:,0],ar[:,1]],0,2)

或者,我们可以使用列表理解来提取row和col索引,然后使用它们进行索引,就像这样-

R = [i[0] for i in a]
C = [i[1] for i in a]
selected_windows = np.moveaxis(w[R,C],0,2)

从一开始就进行优化,我们可以跳过创建步进数组a,而仅将step arg与view_as_windows一起使用,就像这样-

view_as_windows(matrix,(m,m),step=2)

这将给我们一个4D数组,并在它的前两个轴上建立索引,将具有所有mxm形的窗口。这些窗口只是输入的视图,因此没有额外的内存开销以及几乎免费的运行时间!

答案 1 :(得分:1)

import numpy as np

a = np.random.randn(n, n)

b = a[0:m*step:step, 0:m*step:step]

如果您具有一维数组,则可以通过以下代码获取它的子矩阵:

c = a[start:end:step]

如果维度为两个或多个,请在每个维度之间添加逗号。

d = a[start1:end1:step1, start2:end3:step2]