2015-10-05 62 views
2

numpy.square似乎给了不正确的输出时scipy.sparse矩阵传递给它:numpy.square返回稀疏矩阵不正确的结果

import numpy as np 
import scipy.sparse as S 
a = np.array([np.arange(5), np.arange(5), np.arange(5), np.arange(5), np.arange(5)]) 

a 
# array([[0, 1, 2, 3, 4], 
#  [0, 1, 2, 3, 4], 
#  [0, 1, 2, 3, 4], 
#  [0, 1, 2, 3, 4], 
#  [0, 1, 2, 3, 4]]) 

np.square(a) 
# array([[ 0, 1, 4, 9, 16], 
#  [ 0, 1, 4, 9, 16], 
#  [ 0, 1, 4, 9, 16], 
#  [ 0, 1, 4, 9, 16], 
#  [ 0, 1, 4, 9, 16]]) 

b = S.lil_matrix(a) 
c = np.square(b) 
c 
# <5x5 sparse matrix of type '<class 'numpy.int64'>' 
# with 20 stored elements in Compressed Sparse Row format> 

c[2,2] 
# 20 
# Expected output is 4, as in np.square(a) output above. 

这是一个错误?

回答

2

通常,将scipy.sparse矩阵传递到numpy将数组(array_like)作为输入的函数会导致未定义/无意的行为。

没有自动sparse -> dense剧组。

Numpy不知道Scipy的稀疏矩阵。

在Numpy理解的意义上,稀疏矩阵不是“array_like”。 numpy函数然后做的是将稀疏矩阵视为一些未知类型的Python对象 - 通常导致将它们放入1个元素的对象数组,并从那里开始工作。对于返回的标量结果,临时对象数组将被丢弃,并且只是其中包含的对象被返回,所以很容易错过实际完成的奇怪事情。

对象数组有一些回退用于在元素(未知Python对象)上执行算术运算等操作,包括如果需要执行*等,则调用元素的operator.mul。然后将这些结果与您看到的行为相结合。

2

更新:正如指出的hpaulj,其原因可能是有点更复杂。 np.square能够检测到np.matrix并能够对元素进行平方。然而,它在sp.sparse.*matrix上摇摇欲坠。


这是不是一个错误;这是numpyscipy如何实现__mul__运算符之间的细微差异。默认情况下,为*执行numpy.ndarray逐元素乘法而对于numpy.matrix(以及因此,对于scipy.sparse.*matrix),它执行矩阵乘法(来自PEP 465):

numpy提供了两种不同类型的具有不同__mul__方法。对于 numpy.ndarray对象,*执行元素乘法,并且 矩阵乘法必须使用函数调用(numpy.dot)。对于 numpy.matrix对象,*执行矩阵乘法,并且 元素乘法需要函数语法。

在内部,numpy.square使用所提供的参数的方法__mul__,这对于ndarray S和matrix ES不同。

+1

'np.square'文档说它可以通过多元素元素来完成。它为'np.matrix'对象做了这个。出于某些模糊的原因,用“稀疏”矩阵对象进行矩阵乘法。我认为调用堆栈是C和Python代码的混合体,很难遵循。 – hpaulj