首页 文章

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

提问于
浏览
2

我需要获得矩阵的对角条纹(这里不确定术语,对角矩阵条纹似乎最好描述它) .

比方说,我有一个大小为KxN的矩阵,其中K和N是任意大小,K> N.说,我有一个矩阵:

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

从中我需要提取对角条纹,在这种情况下,是通过截断原始条带创建的矩阵MxV大小:

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

所以结果矩阵是:

[[ 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中自动执行此操作?

编辑:

我有另一个问题,是否有可能而不是得到:

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

要得到这样的反向条纹:

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

2 回答

  • 1

    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 是一个数组,则会创建一个可写视图,这意味着如果你有这种倾向,你可以做类似的事情

    >>> stripe(a)[...] *= 10
    >>> a
    array([[  0,   1,   2,   3],
           [ 40,  50,   6,   7],
           [ 80,  90, 100,  11],
           [ 12, 130, 140, 150],
           [ 16,  17, 180, 190],
           [ 20,  21,  22, 230]])
    

    更新:可以以同样的精神获得从左下到右上的条纹 . 只有轻微的复杂性:它不是基于与原始数组相同的地址 .

    >>> 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]])
    
  • 3

    延伸保罗的答案 . 您可以在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]
    

相关问题