Getting diagonal matrix stripe automatically in numpy or pytorch

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

I need to get a diagonal stripe of the matrix (not sure about the terminology here, diagonal matrix stripe seems to describe it best).

Say, I have a matrix of size KxN, where K and N are arbitrary sizes and K>N. Say, I have a matrix:

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

From it I would need to extract a diagonal stripe, in this case, a matrix MxV size that is created by truncating the original one:

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

So the result matrix is:

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

Here is a small example code using masking for the matrices, to strip out the masked positions:

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

But I don't see how such a mask could be automatically generated to any K and N sizes, e.i. 39x9 or 360x96

Any help is appreciated. Maybe there is some function that does this automatically either in numpy, scipy or pytorch?

回答1:

Extending Paul's answer. You can do the same in PyTorch using diag multiple times (I do not think there is any direct function to do strides in 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] 


回答2:

stride_tricks do the trick:

>>> import numpy as np >>>  >>> def stripe(a): ...    a = np.asanyarray(a) ...    i, j = a.shape ...    assert i >= j ...    k, l = a.strides ...    return np.lib.stride_tricks.as_strided(a, (i-j+1, j), (k, k+l)) ...  >>> 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]]) 

If a is an array this creates a writable view, meaning that if you feel so inclined you can do things like

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!