首页 文章

添加到常规numpy ndarray时调用scipy.sparse __add__方法?

提问于
浏览
2

我正在计算scipy.sparse矩阵(CSC)和numpy ndarray向量之间的点积:

>>> print type(np_vector), np_vector.shape
<type 'numpy.ndarray'> (200,)
>>> print type(sp_matrix), sparse.isspmatrix(sp_matrix), sp_matrix.shape
<class 'scipy.sparse.csc.csc_matrix'> True (200, 200)
>>> dot_vector = dot(np_vector, sp_matrix)

结果似乎是一个新的ndarray矢量,正如我所料:

>>> print type(dot_vector), dot_vector.shape
<type 'numpy.ndarray'> (200,)

但是,当我尝试向该向量添加标量时,我收到异常:

>>> scalar = 3.0
>>> print dot_vector + scalar 
C:\Python27\lib\site-packages\scipy\sparse\compressed.pyc in __add__(self, other)
    173                 return self.copy()
    174             else: # Now we would add this scalar to every element.
--> 175                 raise NotImplementedError('adding a nonzero scalar to a '
    176                                           'sparse matrix is not supported')
    177         elif isspmatrix(other):

NotImplementedError: adding a nonzero scalar to a sparse matrix is not supported

好像结果 dot_vector 再次是一个稀疏矩阵 .

具体来说,似乎我有一个ndarray但是为 + 运算符调用了稀疏矩阵 __add__ .

这是我期望被调用的方法:

>>> print dot_vector.__add__
<method-wrapper '__add__' of numpy.ndarray object at 0x05250690>

我在这里遗漏了什么或这看起来真的很奇怪吗?
是什么决定了为 + 运算符调用哪个方法?
我在IPython Notebook( ipython notebook --pylab inline )中运行此代码 . 可能是IPython --pylab或笔记本内核以某种方式搞砸了吗?

谢谢你的帮助!

1 回答

  • 7

    您对 np.dot 所做的事情与您执行以下操作时所获得的内容并无太大差别:

    >>> np.dot([1, 2, 3], 4)
    array([ 4,  8, 12])
    

    因为 np.dot 不知道稀疏矩阵,所以在你的情况下的返回也是矢量的每个元素与原始稀疏矩阵的乘积 . 这可能是在调用稀疏矩阵的 __rmul__ 方法时执行的,所以你得到的是一个200项数组,每个数组本身就是一个稀疏矩阵 . 当您尝试向该向量添加标量时,它会被广播,当尝试将标量添加到每个矩阵时,会弹出错误 .

    这样做的正确方法是调用稀疏矩阵的 .dot 方法 . 要通过行向量预乘:

    >>> aa = sps.csc_matrix(np.arange(9).reshape(3, 3))
    >>> bb = np.arange(3)
    >>> aa.T.dot(bb)
    array([15, 18, 21])
    

    并通过列向量进行后乘:

    >>> aa.dot(bb)
    array([ 5, 14, 23])
    

    这当然完全等同于您使用数组操作的内容:

    >>> aaa = np.arange(9).reshape(3,3)
    >>> aaa.dot(bb)
    array([ 5, 14, 23])
    >>> bb.dot(aaa)
    array([15, 18, 21])
    

相关问题