【问题标题】:scipy.sparse __add__ method being called when adding to a regular numpy ndarray?添加到常规 numpy ndarray 时调用 scipy.sparse __add__ 方法?
【发布时间】:2013-04-19 18:31:40
【问题描述】:

我正在计算 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 或 notebook 内核搞砸了?

感谢您的帮助!

【问题讨论】:

  • 请创建一个 minimal 显示此行为的脚本并将其发布在您的问题中。我怀疑有一个包含稀疏矩阵的全局 dot_vector 变量,并被使用而不是包含向量的本地变量。但是没有看到完整的剧本,这纯属猜测。
  • 你不能在 scipy.sparse 中使用 numpy 的点,很简单。

标签: python numpy scipy ipython sparse-matrix


【解决方案1】:

您拨打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])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-31
    • 2021-02-16
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 2017-11-03
    • 2018-10-10
    • 1970-01-01
    相关资源
    最近更新 更多