归一化矩阵行 scipy 矩阵
Normalizing matrix row scipy matrix
我希望对从 networkx 有向图获得的稀疏 scipy 矩阵的每一行进行归一化。
import networkx as nx
import numpy as np
G=nx.random_geometric_graph(10,0.3)
M=nx.to_scipy_sparse_matrix(G, nodelist=G.nodes())
from __future__ import division
print(M[3])
(0, 1) 1
(0, 5) 1
print(M[3].multiply(1/M[3].sum()))
(0, 1) 0.5
(0, 5) 0.5
没关系,我像往常一样正常化并且它按预期工作。
但是如果我写:
>>> M[3]=M[3].multiply(1/M[3].sum())
>>> M[3]
<1x10 sparse matrix of type '<type 'numpy.int64'>'
with 10 stored elements in Compressed Sparse Row format>
(0, 0) 0
(0, 1) 0
(0, 2) 0
(0, 3) 0
(0, 4) 0
(0, 5) 0
(0, 6) 0
(0, 7) 0
(0, 8) 0
(0, 9) 0
我只需要遍历每一行并对这个稀疏 scipy 矩阵进行归一化。
你会怎么做?
谢谢
这是一种方法(来自 networkx.pagerank_scipy)。它使用 scipy 线性代数函数而不是遍历每一行。对于大图,这可能会更快。
In [42]: G=nx.random_geometric_graph(5,0.5)
In [43]: M=nx.to_scipy_sparse_matrix(G, nodelist=G.nodes(), dtype=float)
In [44]: M.todense()
Out[44]:
matrix([[ 0., 1., 0., 1., 1.],
[ 1., 0., 0., 0., 1.],
[ 0., 0., 0., 1., 1.],
[ 1., 0., 1., 0., 1.],
[ 1., 1., 1., 1., 0.]])
In [45]: S = scipy.array(M.sum(axis=1)).flatten()
In [46]: S[S != 0] = 1.0 / S[S != 0]
In [47]: Q = scipy.sparse.spdiags(S.T, 0, *M.shape, format='csr')
In [48]: (Q*M).todense()
Out[48]:
matrix([[ 0. , 0.33333333, 0. , 0.33333333, 0.33333333],
[ 0.5 , 0. , 0. , 0. , 0.5 ],
[ 0. , 0. , 0. , 0.5 , 0.5 ],
[ 0.33333333, 0. , 0.33333333, 0. , 0.33333333],
[ 0.25 , 0.25 , 0.25 , 0.25 , 0. ]])
原因
print(M[3].multiply(1/M[3].sum()))
产生了预期的结果,并且
M[3]=M[3].multiply(1/M[3].sum())
产生零是因为 M
是一个整数数组,<type 'numpy.int64'>
。只要我们不尝试将规范分配回 M
,这就不是问题。
如果M.A
array([[0, 1, 0, 1, 1],
[1, 0, 0, 0, 1],
[0, 0, 0, 1, 1],
[1, 0, 1, 0, 1],
[1, 1, 1, 1, 0]], dtype=int32)
各列的总和为:Msum = M.sum(axis=1)
。很密集
matrix([[3],
[2],
[2],
[3],
[4]], dtype=int32)
与其相反:
Mnorm = 1/Msum
matrix([[ 0.33333333],
[ 0.5 ],
[ 0.5 ],
[ 0.33333333],
[ 0.25 ]])
M.multiply(Mnorm)
是密集的(就像 M.multiply
的设置方式)。但是让范数稀疏,乘积也稀疏
M1 = M.multiply(sparse.csr_matrix(Mnorm))
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 14 stored elements in Compressed Sparse Row format>
M1.A
array([[ 0. , 0.33333333, 0. , 0.33333333, 0.33333333],
[ 0.5 , 0. , 0. , 0. , 0.5 ],
[ 0. , 0. , 0. , 0.5 , 0.5 ],
[ 0.33333333, 0. , 0.33333333, 0. , 0.33333333],
[ 0.25 , 0.25 , 0.25 , 0.25 , 0. ]])
等效的密集numpy
操作是:
A = M.A
A/np.sum(A, axis=1, keepdims=True)
我希望对从 networkx 有向图获得的稀疏 scipy 矩阵的每一行进行归一化。
import networkx as nx
import numpy as np
G=nx.random_geometric_graph(10,0.3)
M=nx.to_scipy_sparse_matrix(G, nodelist=G.nodes())
from __future__ import division
print(M[3])
(0, 1) 1
(0, 5) 1
print(M[3].multiply(1/M[3].sum()))
(0, 1) 0.5
(0, 5) 0.5
没关系,我像往常一样正常化并且它按预期工作。 但是如果我写:
>>> M[3]=M[3].multiply(1/M[3].sum())
>>> M[3]
<1x10 sparse matrix of type '<type 'numpy.int64'>'
with 10 stored elements in Compressed Sparse Row format>
(0, 0) 0
(0, 1) 0
(0, 2) 0
(0, 3) 0
(0, 4) 0
(0, 5) 0
(0, 6) 0
(0, 7) 0
(0, 8) 0
(0, 9) 0
我只需要遍历每一行并对这个稀疏 scipy 矩阵进行归一化。 你会怎么做? 谢谢
这是一种方法(来自 networkx.pagerank_scipy)。它使用 scipy 线性代数函数而不是遍历每一行。对于大图,这可能会更快。
In [42]: G=nx.random_geometric_graph(5,0.5)
In [43]: M=nx.to_scipy_sparse_matrix(G, nodelist=G.nodes(), dtype=float)
In [44]: M.todense()
Out[44]:
matrix([[ 0., 1., 0., 1., 1.],
[ 1., 0., 0., 0., 1.],
[ 0., 0., 0., 1., 1.],
[ 1., 0., 1., 0., 1.],
[ 1., 1., 1., 1., 0.]])
In [45]: S = scipy.array(M.sum(axis=1)).flatten()
In [46]: S[S != 0] = 1.0 / S[S != 0]
In [47]: Q = scipy.sparse.spdiags(S.T, 0, *M.shape, format='csr')
In [48]: (Q*M).todense()
Out[48]:
matrix([[ 0. , 0.33333333, 0. , 0.33333333, 0.33333333],
[ 0.5 , 0. , 0. , 0. , 0.5 ],
[ 0. , 0. , 0. , 0.5 , 0.5 ],
[ 0.33333333, 0. , 0.33333333, 0. , 0.33333333],
[ 0.25 , 0.25 , 0.25 , 0.25 , 0. ]])
原因
print(M[3].multiply(1/M[3].sum()))
产生了预期的结果,并且
M[3]=M[3].multiply(1/M[3].sum())
产生零是因为 M
是一个整数数组,<type 'numpy.int64'>
。只要我们不尝试将规范分配回 M
,这就不是问题。
如果M.A
array([[0, 1, 0, 1, 1],
[1, 0, 0, 0, 1],
[0, 0, 0, 1, 1],
[1, 0, 1, 0, 1],
[1, 1, 1, 1, 0]], dtype=int32)
各列的总和为:Msum = M.sum(axis=1)
。很密集
matrix([[3],
[2],
[2],
[3],
[4]], dtype=int32)
与其相反:
Mnorm = 1/Msum
matrix([[ 0.33333333],
[ 0.5 ],
[ 0.5 ],
[ 0.33333333],
[ 0.25 ]])
M.multiply(Mnorm)
是密集的(就像 M.multiply
的设置方式)。但是让范数稀疏,乘积也稀疏
M1 = M.multiply(sparse.csr_matrix(Mnorm))
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 14 stored elements in Compressed Sparse Row format>
M1.A
array([[ 0. , 0.33333333, 0. , 0.33333333, 0.33333333],
[ 0.5 , 0. , 0. , 0. , 0.5 ],
[ 0. , 0. , 0. , 0.5 , 0.5 ],
[ 0.33333333, 0. , 0.33333333, 0. , 0.33333333],
[ 0.25 , 0.25 , 0.25 , 0.25 , 0. ]])
等效的密集numpy
操作是:
A = M.A
A/np.sum(A, axis=1, keepdims=True)