在numpy或pytorch中自动获取对角线矩阵条纹

2024-06-13 00:45:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要一个矩阵的对角线条纹(不确定这里的术语,对角线矩阵条纹似乎最能描述它)。在

例如,我有一个大小为KxN的矩阵,其中K和N是任意大小,K>;N。例如,我有一个矩阵:

[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]

我需要从中提取一条对角线条纹,在本例中,是一个矩阵MxV大小,它是通过截断原始条纹而创建的:

^{pr2}$

所以结果矩阵是:

[[ 0  4  8]
 [ 3  7  11]]

下面是一个使用矩阵掩蔽的小示例代码,用于去除屏蔽位置:

import numpy as np
X=np.arange(12).reshape(4,3)
mask=np.asarray([
  [ True,  False,  False],
  [ True,  True,  False], 
  [ False, True,  True], 
  [ False, False,  True]
])

>>> mask
array([[ True, False, False],
       [ True,  True, False],
       [False,  True,  True],
       [False, False,  True]], dtype=bool)

>>> X
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

>>> X.T[mask.T].reshape(3,2).T
array([[ 0,  4,  8],
       [ 3,  7, 11]])

但我不明白这样的掩模是如何自动生成K和N尺寸的,比如39x9或360x96

感谢任何帮助。也许在numpy、scipy或pytorch中有一些函数可以自动执行这个操作?在

编辑:

我还有一个问题,有没有可能不得到:

^{pr2}$

要获得这样的反向条纹:

[[ x   x   2]
 [ x   4   5]
 [ 6   7   x]
 [ 9   x   x]]

Tags: gtnumpyfalsetruenp矩阵maskarray
2条回答

扩展保罗的答案。您可以在PyTorch中多次使用diag执行相同的操作(我认为在PyTorch中没有任何直接的函数来执行跨步操作)

In [1]: import torch

In [2]: def stripe(a):
   ...:     i, j = a.size()
   ...:     assert(i>=j)
   ...:     out = torch.zeros((i-j+1, j))
   ...:     for diag in range(0, i-j+1):
   ...:         out[diag] = torch.diag(a, -diag)
   ...:     return out
   ...: 

In [3]: a = torch.randn((6, 3))

In [4]: a
Out[4]: 

 0.7669  0.6808 -0.6102
-1.0624 -1.2016 -0.7308
 1.4054 -1.0621  0.2618
-0.9505 -0.9322 -0.4321
-0.0134 -1.3684  0.1883
-0.8499  0.2533 -0.3976
[torch.FloatTensor of size 6x3]

In [5]: stripe(a)
Out[5]: 

 0.7669 -1.2016  0.2618
-1.0624 -1.0621 -0.4321
 1.4054 -0.9322  0.1883
-0.9505 -1.3684 -0.3976
[torch.FloatTensor of size 4x3]

stride_tricks完成以下操作:

>>> import numpy as np
>>> 
>>> def stripe(a):
...    a = np.asanyarray(a)
...    *sh, i, j = a.shape
...    assert i >= j
...    *st, k, m = a.strides
...    return np.lib.stride_tricks.as_strided(a, (*sh, i-j+1, j), (*st, k, k+m))
... 
>>> a = np.arange(24).reshape(6, 4)
>>> a
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]])
>>> stripe(a)
array([[ 0,  5, 10, 15],
       [ 4,  9, 14, 19],
       [ 8, 13, 18, 23]])

如果a是一个数组,这将创建一个可写的视图,这意味着如果您有兴趣,可以执行以下操作

^{pr2}$

更新:从左下到右上的条纹可以用同样的精神获得。唯一的小问题是:它与原始数组的地址不同。在

>>> def reverse_stripe(a):
...     a = np.asanyarray(a)
...     *sh, i, j = a.shape
...     assert i >= j
...     *st, k, m = a.strides
...     return np.lib.stride_tricks.as_strided(a[..., j-1:, :], (*sh, i-j+1, j), (*st, k, m-k))
... 
>>> a = np.arange(24).reshape(6, 4)
>>> reverse_stripe(a)
array([[12,  9,  6,  3],
       [16, 13, 10,  7],
       [20, 17, 14, 11]])

相关问题 更多 >