Python 2.7 Numpy-考虑偏移量拆分矩阵

Python 2.7 Numpy-考虑偏移量拆分矩阵,python-2.7,numpy,Python 2.7,Numpy,给定一个m x n矩阵,我想把它分解成任意偏移量的平方a x a(a=3或a=4)矩阵(最小偏移量=1,最大偏移量=块大小),就像Mathematica的函数那样: 例如,给定一个4x4矩阵alike 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 如果我给3 x 3块,偏移量=1,我想得到4个矩阵: 1 2 3 5 6 7 9 10 11 2 3 4 6 7 8 10 11 12 5 6 7 9 10 11 1

给定一个
m x n
矩阵,我想把它分解成任意偏移量的平方
a x a
(a=3或a=4)矩阵(最小偏移量=1,最大偏移量=块大小),就像Mathematica的函数那样:

例如,给定一个4x4矩阵
a
like

1  2  3  4 
5  6  7  8
9  10 11 12
13 14 15 16
如果我给3 x 3块,偏移量=1,我想得到4个矩阵:

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
A=np.arange(1,37)。重塑((6,6))
并且我使用偏移量为3的3 x 3块,我希望作为块的输出:

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

我同意矩阵A是一个列表列表,我认为我不需要NumPy的功能。我很惊讶,
array\u split
numpy.split
都没有提供这种现成的偏移选项,用纯Python进行切片编码是更简单的方法还是我应该研究numpy的进步?我希望代码高度易读。

正如您所提示的,有一种方法可以使用
步幅来实现这一点

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]]])
步幅的一个问题是它很先进,而且很难向没有多少numpy经验的人解释。我没有经过太多的尝试和错误就找到了表格,但我在这里呆的时间太长了

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

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)
将其转换为数组。如果它更清晰的话,使用它没有什么错

关于跨越式的
方法,需要记住的一点是,它是一个视图,对
M
的更改可能会更改
a
,对
M
中一个位置的更改可能会修改
M
中的多个位置。但是,重塑
M
可能会把它变成一个副本。因此,总的来说,从
M
中读取值,并将其用于计算
sum
mean
。就地更改可能是不可预测的

迭代解决方案会在四周生成副本

使用
np.ogrid
代替
np.ix
的迭代解(否则与此相同):

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)])
这个列表版本的
视图
行为与
as________
解决方案类似(列表的元素是视图)

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

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

In [1017]: np.arange(0,6,3)
Out[1017]: array([0, 3])

类似的问题可以用滚动或滑动窗口来表达。有些人甚至可能会找到一个好的副本。@hpauji谢谢,我喜欢
np.ix_uu
版本,我认为它足够简单,但在指定偏移量时,我无法让它在另一个矩阵上工作,例如,这个
import numpy as np a=np.arange(1,37)。重塑((6,6))打印列表=[]blockSize=3 offset=3对于范围内的i(0,blockSize-1,offset):对于范围内的j(0,blockSize-1,offset):alist.append(A[np.ix(范围(i,i+blockSize,offset),范围(j,j+blockSize,offset)))np.array(alist)
在偏移量为3和1时都失败,我怎样才能解决这个问题呢?我必须把那个评论交给编辑,然后换行阅读。此
偏移量的目的是什么?在
范围中
第三个值是
步长
。它是块之间的偏移量,就像滑动窗口步幅一样。在
A=np.arange(1,37).重塑((6,6))
中,3 x 3块的偏移量为3将只给出从
np.split(A,3)
中获得的4个块。我扩展了问题以进行说明。我添加了我的一个解决方案的6x6版本。它只是改变了外部的
范围
表达式。谢谢,但是6x6解决方案只是一个例子,解释了我想要一个通用的块分离函数,其函数为mxn矩阵,如OP所述<代码>np.数组([A[slice(i,i+3),slice(j,j+3)],用于范围(0,6,3)中的i,用于范围(0,6,3)]中的j)
当矩阵有6 x 3个元素时失败。我将尝试根据您的帖子编写一个解决方案。
In [1017]: np.arange(0,6,3)
Out[1017]: array([0, 3])