你的 ar1_diag2 没有重塑是:
Out[87]:
array([[[ 0, 1, 2],
[ 9, 10, 11],
[18, 19, 20]],
[[30, 31, 32],
[39, 40, 41],
[48, 49, 50]],
[[60, 61, 62],
[69, 70, 71],
[78, 79, 80]]])
查看ar1 测试是来自ar1 的3 (3,3) 块:
In [89]: ar1
Out[89]:
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8],
[ 9, 10, 11, 12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23, 24, 25, 26],
[27, 28, 29, 30, 31, 32, 33, 34, 35],
[36, 37, 38, 39, 40, 41, 42, 43, 44],
[45, 46, 47, 48, 49, 50, 51, 52, 53],
[54, 55, 56, 57, 58, 59, 60, 61, 62],
[63, 64, 65, 66, 67, 68, 69, 70, 71],
[72, 73, 74, 75, 76, 77, 78, 79, 80]])
我们可以使用as_strided 将其重塑为 (3,3,3,3) 数组。 (as_strided 被建议使用烤箱作为移动窗口的一种方式,尤其是重叠的窗口):
In [90]: X = np.lib.stride_tricks.as_strided(ar1,shape=(3,3,3,3),strides=(9*3*8,
...: 3*3*8,3*8,8))
In [91]: X
Out[91]:
array([[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]],
....
我可以从中选择所需的对角线块:
In [92]: X[np.arange(3),:,np.arange(3)]
Out[92]:
array([[[ 0, 1, 2],
[ 9, 10, 11],
[18, 19, 20]],
[[30, 31, 32],
[39, 40, 41],
[48, 49, 50]],
[[60, 61, 62],
[69, 70, 71],
[78, 79, 80]]])
最初我尝试了X[np.arange(3),np.arange(3)],但那是错误的对角线。我怀疑如果我在as_strided 中使用不同的步幅,这会起作用。 (strides=(9*3*8,3*8,3*3*8,8) 是正确的步伐。)
虽然as_strided 创建了一个view,并且在创建大型移动窗口时可以提供很大帮助,但它并不总是最快的。这里是松散的:
In [96]: timeit ar1_diag2 = np.array([ar1[3*j:3*j+3,3*j:3*j+3] for j in range(0,3)])
8.7 µs ± 24 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [97]: timeit X = np.lib.stride_tricks.as_strided(ar1,shape=(3,3,3,3),
strides=(9*3*8,3*3*8,3*8,8))[np.arange(3),:,np.arange(3)]
26 µs ± 1.22 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
编辑
我刚刚意识到我第一次使用as_strided 只是一个reshape(3,3,3,3)。也就是说,步幅是相同的。这意味着我们可以使用
In [115]: timeit ar1.reshape(3,3,3,3)[np.arange(3),:,np.arange(3)]
8.7 µs ± 236 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
这与您的 ar1_diag2 索引时间相同。