Numpy - 考虑抵消分割矩阵

时间:2016-08-26 00:36:59

标签: python-2.7 numpy

给定value矩阵我想将其拆分为方形m x n(a = 3或a = 4)任意偏移矩阵(最小偏移= 1,最大偏移=块大小),如Mathematica的Partition函数确实:

例如,给定一个4 x 4矩阵a x a,如

A

如果我给3 x 3块并且offset = 1,我想得到4个矩阵:

1  2  3  4 
5  6  7  8
9  10 11 12
13 14 15 16

如果矩阵1 2 3 5 6 7 9 10 11 2 3 4 6 7 8 10 11 12 5 6 7 9 10 11 13 14 15 6 7 8 10 11 12 14 15 16 A并且我使用3 x 3块且偏移= 3,我想要输出块:

A = np.arange(1, 37).reshape((6,6))

我很好,矩阵A是一个列表列表,我认为我不需要NumPy的功能。令我感到惊讶的是1 2 3 7 8 9 3 14 15 4 5 6 10 11 12 16 17 18 19 20 21 25 26 27 31 32 33 22 23 24 28 29 30 34 35 36 array_split都没有提供开箱即用的偏移选项,使用切片在纯Python中编码是否更直接,或者我应该看看NumPy的步伐?我希望代码清晰易读。

1 个答案:

答案 0 :(得分:3)

正如您所提示的,有一种方法可以使用strides

执行此操作
In [900]: M = np.lib.stride_tricks.as_strided(A, shape=(2,2,3,3), strides=(16,4,16,4))
In [901]: M
Out[901]: 
array([[[[ 1,  2,  3],
         [ 5,  6,  7],
         [ 9, 10, 11]],

        [[ 2,  3,  4],
         [ 6,  7,  8],
         [10, 11, 12]]],


       [[[ 5,  6,  7],
         [ 9, 10, 11],
         [13, 14, 15]],

        [[ 6,  7,  8],
         [10, 11, 12],
         [14, 15, 16]]]])
In [902]: M.reshape(4,3,3)  # to get it in form you list
Out[902]: 
array([[[ 1,  2,  3],
        [ 5,  6,  7],
        [ 9, 10, 11]],

       [[ 2,  3,  4],
        [ 6,  7,  8],
        [10, 11, 12]],

       [[ 5,  6,  7],
        [ 9, 10, 11],
        [13, 14, 15]],

       [[ 6,  7,  8],
        [10, 11, 12],
        [14, 15, 16]]])

步伐的一个问题是,它是先进的,并且很难向没有多少经验的人解释。我想出了没有太多试验和错误的表格,但我已经在这里闲逛太久了。 :))。

但是这个迭代解决方案更容易解释:

In [909]: alist=[]
In [910]: for i in range(2):
     ...:     for j in range(2):
     ...:         alist.append(A[np.ix_(range(i,i+3),range(j,j+3))])
     ...:         
In [911]: alist
Out[911]: 
[array([[ 1,  2,  3],
        [ 5,  6,  7],
        [ 9, 10, 11]]), 
 array([[ 2,  3,  4],
        [ 6,  7,  8],
        [10, 11, 12]]), 
 array([[ 5,  6,  7],
        [ 9, 10, 11],
        [13, 14, 15]]), 
 array([[ 6,  7,  8],
        [10, 11, 12],
        [14, 15, 16]])]

可以将其转换为np.array(alist)的数组。如果它更清楚,使用它没有任何问题。

有关as_strided方法的一点要注意的是,它是一个视图,对M的更改可能会更改A,并且{{1}中的一个位置发生更改可以修改M中的几个地方。但重塑M可能会将其变成副本。总的来说,从M读取值更安全,并将其用于Msum等计算。在适当的位置,更改可能无法预测。

迭代解决方案可以生成副本。

使用mean代替np.ogrid的迭代解决方案(否则相同的想法):

np.ix_

np.array([A[np.ogrid[i:i+3, j:j+3]] for i in range(2) for j in range(2)]) ix_只是构建索引块的矢量对的简单方法:

ogrid

同样的事情,但In [970]: np.ogrid[0:3, 0:3] Out[970]: [array([[0], [1], [2]]), array([[0, 1, 2]])] 个对象:

slice

此列表版本的行为与np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(2) for j in range(2)]) 解决方案类似view行为(列表的元素是视图)。

对于具有非重叠块的6x6,请尝试:

as_strided

假设你想要连续的块,内部切片/范围不会改变,只有外部In [1016]: np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(0,6,3) for j i ...: n range(0,6,3)]) Out[1016]: array([[[ 1, 2, 3], [ 7, 8, 9], [13, 14, 15]], [[ 4, 5, 6], [10, 11, 12], [16, 17, 18]], [[19, 20, 21], [25, 26, 27], [31, 32, 33]], [[22, 23, 24], [28, 29, 30], [34, 35, 36]]]) i的步进

j