2017-07-03 379 views
0

当我发现以下奇怪现象时,我在networkx中使用以下代码块。在第一种情况下,我在稀疏矩阵上使用了ufunc multiply(*),这意外地正确地给了我一个度数序列。然而,当使用普通矩阵完成同样的操作时,它会给我一个10 x 10的矩阵,并且正如预期的那样np.dot(...)给了我正确的结果。具有邻接矩阵的乘法和点乘积(numpy)

import numpy as np 
import networks as nx 

ba = nx.barabasi_albert_graph(n=10, m=2) 

A = nx.adjacency_matrix(ba) 
# <10x10 sparse matrix of type '<class 'numpy.int64'>' 
# with 32 stored elements in Compressed Sparse Row format> 

A * np.ones(10) 

# output: array([ 5., 3., 4., 5., 4., 3., 2., 2., 2., 2.]) 

nx.degree(ba) 

# output {0: 5, 1: 3, 2: 4, 3: 5, 4: 4, 5: 3, 6: 2, 7: 2, 8: 2, 9: 2} 

B = np.ones(100).reshape(10, 10) 

B * np.ones(10) 

array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
    [ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]) 

np.dot(B, np.ones(10)) 
# array([ 10., 10., 10., 10., 10., 10., 10., 10., 10., 10.]) 

我期待,我应该做np.dot(A, np.ones(10)),但返回的10数组,10×10的矩阵

array([ <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>, 
    <10x10 sparse matrix of type '<class 'numpy.float64'>' 
with 32 stored elements in Compressed Sparse Row format>], dtype=object) 

什么是这里的细微差别?

回答

0

对于普通numpy阵列,*乘以元素(broadcasting)。 np.dot是矩阵乘积,乘积和。对于np.matrix子类*是矩阵产品,dotsparse.matrix不是一个子类,但它是建模的。 *是矩阵乘积。

In [694]: A = sparse.random(10,10,.2, format='csr') 
In [695]: A 
Out[695]: 
<10x10 sparse matrix of type '<class 'numpy.float64'>' 
    with 20 stored elements in Compressed Sparse Row format> 
In [696]: A *np.ones(10) 
Out[696]: 
array([ 0.6349177 , 0.  , 1.25781168, 1.12021258, 2.43477065, 
     1.10407149, 1.95096264, 0.6253589 , 0.44242708, 0.50353061]) 

稀疏矩阵具有dot方法,其行为是相同的:

In [698]: A.dot(np.ones(10)) 
Out[698]: 
array([ 0.6349177 , 0.  , 1.25781168, 1.12021258, 2.43477065, 
     1.10407149, 1.95096264, 0.6253589 , 0.44242708, 0.50353061]) 

致密版本:

In [699]: np.dot(A.A,np.ones(10)) 
Out[699]: 
array([ 0.6349177 , 0.  , 1.25781168, 1.12021258, 2.43477065, 
     1.10407149, 1.95096264, 0.6253589 , 0.44242708, 0.50353061]) 

我想np.dot本来处理稀疏矩阵权,即与他们自己的方法不同。但np.dot(A,np.ones(10))没有这样做,产生了2个稀疏矩阵的对象数组。我可以挖掘为什么,但现在,避免它。

通常,使用稀疏矩阵的稀疏函数和方法。不要假设numpy函数将正确地使用它们。


np.dot正常工作时,两个数组都是稀疏,

In [702]: np.dot(A,A) 
Out[702]: 
<10x10 sparse matrix of type '<class 'numpy.float64'>' 
    with 32 stored elements in Compressed Sparse Row format> 
In [703]: np.dot(A,A.T) 
Out[703]: 
<10x10 sparse matrix of type '<class 'numpy.float64'>' 
    with 31 stored elements in Compressed Sparse Row format> 

In [705]: np.dot(A, sparse.csr_matrix(np.ones(10)).T) 
Out[705]: 
<10x1 sparse matrix of type '<class 'numpy.float64'>' 
    with 9 stored elements in Compressed Sparse Row format> 
In [706]: _.A 
Out[706]: 
array([[ 0.6349177 ], 
     [ 0.  ], 
     [ 1.25781168], 
     [ 1.12021258], 
     [ 2.43477065], 
     [ 1.10407149], 
     [ 1.95096264], 
     [ 0.6253589 ], 
     [ 0.44242708], 
     [ 0.50353061]]) 

对于什么是值得稀疏sum与这种矩阵产品进行:

In [708]: A.sum(axis=1) 
Out[708]: 
matrix([[ 0.6349177 ], 
     [ 0.  ], 
     [ 1.25781168], 
     [ 1.12021258], 
     [ 2.43477065], 
     [ 1.10407149], 
     [ 1.95096264], 
     [ 0.6253589 ], 
     [ 0.44242708], 
     [ 0.50353061]]) 
+0

在这种情况下,是一种幸福,因为代码看起来更清洁,而表达式的两边可能会发生两种截然不同的事情。例如,在我的代码中有一个表达式是这样的:'A * np.ones(10)> np.random.uniform(10)* np.ones(10)'。 LHS和RHS是不同类型的乘法,但数学很明确! – buzaku