Normalize diagonal sparse.csc_matrix

I have scipy.sparse.csc_matrix with dtype = np.int32. I want to efficiently split each column (or row, depending on which is faster for csc_matrix) of the matrix by the diagonal element in that column. So, mnew [:, i] = m [:, i] / m [i, i]. Note that I need to convert my matrix to np.double (since the mnew elements will be in [0,1]), and since the matrix is ​​massive and very sparse, I wonder if I can do this in some efficient / not for loop / never a tight path.

Best

Ilya

0
source share
1 answer

Make a sparse matrix:

In [379]: M = sparse.random(5,5,.2, format='csr') In [380]: M Out[380]: <5x5 sparse matrix of type '<class 'numpy.float64'>' with 5 stored elements in Compressed Sparse Row format> In [381]: M.diagonal() Out[381]: array([ 0., 0., 0., 0., 0.]) 

too many 0s in the diagonal - allows you to add a nonzero diagonal:

 In [382]: D=sparse.dia_matrix((np.random.rand(5),0),shape=(5,5)) In [383]: D Out[383]: <5x5 sparse matrix of type '<class 'numpy.float64'>' with 5 stored elements (1 diagonals) in DIAgonal format> In [384]: M1 = M+D In [385]: M1 Out[385]: <5x5 sparse matrix of type '<class 'numpy.float64'>' with 10 stored elements in Compressed Sparse Row format> In [387]: M1.A Out[387]: array([[ 0.35786668, 0.81754484, 0. , 0. , 0. ], [ 0. , 0.41928992, 0. , 0.01371273, 0. ], [ 0. , 0. , 0.4685924 , 0. , 0.35724102], [ 0. , 0. , 0.77591294, 0.95008721, 0.16917791], [ 0. , 0. , 0. , 0. , 0.16659141]]) 

Now it’s trivial to divide each column by its diagonal (this is a matrix “product”)

 In [388]: M1/M1.diagonal() Out[388]: matrix([[ 1. , 1.94983185, 0. , 0. , 0. ], [ 0. , 1. , 0. , 0.01443313, 0. ], [ 0. , 0. , 1. , 0. , 2.1444144 ], [ 0. , 0. , 1.65583764, 1. , 1.01552603], [ 0. , 0. , 0. , 0. , 1. ]]) 

Or split the rows - (multiply by the column vector)

 In [391]: M1/M1.diagonal()[:,None] 

oops, they are dense; let me make the diagonal sparse

 In [408]: md = sparse.csr_matrix(1/M1.diagonal()) # do the inverse here In [409]: md Out[409]: <1x5 sparse matrix of type '<class 'numpy.float64'>' with 5 stored elements in Compressed Sparse Row format> In [410]: M.multiply(md) Out[410]: <5x5 sparse matrix of type '<class 'numpy.float64'>' with 5 stored elements in Compressed Sparse Row format> In [411]: M.multiply(md).A Out[411]: array([[ 0. , 1.94983185, 0. , 0. , 0. ], [ 0. , 0. , 0. , 0.01443313, 0. ], [ 0. , 0. , 0. , 0. , 2.1444144 ], [ 0. , 0. , 1.65583764, 0. , 1.01552603], [ 0. , 0. , 0. , 0. , 0. ]]) 

md.multiply(M) for the column version.

Splitting a sparse matrix is similar, except for using the sum of the rows instead of the diagonal. The deal is a bit bigger with the potential divide by zero problem.

+2
source

Source: https://habr.com/ru/post/1270321/


All Articles