Scipy sparse matrix can not use np.matmul

Viewed 376

I have a problem while trying to do multiplication with a scipy sparse matrix (type:scipy.sparse.csr.csr_matrix) and a numpy array (type:numpy.ndarray).

To demonstrate this, here is a little experiment.

1. First create the matrix

row = [0, 1, 2]
col = [0, 0, 1]
value = [1, 2, 3]
x = csr_matrix((value, (row, col)), shape=[3, 3])

and

w = np.random.normal(size=(3,2))

2. Then use np.matmul() to perform the multiplication and get the error

np.matmul(x,w)
ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)

But x.dot(w) or x * w could work and get the same result. This made me really confused.

1 Answers

In full gory detail:

In [19]: from scipy.sparse import csr_matrix

In [20]: row = [0, 1, 2]
    ...: col = [0, 0, 1]
    ...: value = [1, 2, 3]
    ...: x = csr_matrix((value, (row, col)), shape=[3, 3])

In [21]: x
Out[21]: 
<3x3 sparse matrix of type '<class 'numpy.intc'>'
    with 3 stored elements in Compressed Sparse Row format>

In [22]: np.array(x)
Out[22]: 
array(<3x3 sparse matrix of type '<class 'numpy.intc'>'
    with 3 stored elements in Compressed Sparse Row format>, dtype=object)

[22] is a 0d object dtype array. It is not x.A!

In [23]: w = np.random.normal(size=(3,2))

Multiplications where x controls the action, performing a proper multiplication. Operators delegate the work to argument methods.

In [24]: x*w
Out[24]: 
array([[-1.64308263, -0.66048279],
       [-3.28616526, -1.32096559],
       [-2.9214839 ,  1.70194911]])

In [25]: x@w
Out[25]: 
array([[-1.64308263, -0.66048279],
       [-3.28616526, -1.32096559],
       [-2.9214839 ,  1.70194911]])

dot function converts x to [22] and then does the multiplication:

In [26]: np.dot(x,w)
Out[26]: 
array([[<3x3 sparse matrix of type '<class 'numpy.float64'>'
            with 3 stored elements in Compressed Sparse Row format>,
        <3x3 sparse matrix of type '<class 'numpy.float64'>'
            with 3 stored elements in Compressed Sparse Row format>],
       [<3x3 sparse matrix of type '<class 'numpy.float64'>'
            with 3 stored elements in Compressed Sparse Row format>,
        <3x3 sparse matrix of type '<class 'numpy.float64'>'
            with 3 stored elements in Compressed Sparse Row format>],
       [<3x3 sparse matrix of type '<class 'numpy.float64'>'
            with 3 stored elements in Compressed Sparse Row format>,
        <3x3 sparse matrix of type '<class 'numpy.float64'>'
            with 3 stored elements in Compressed Sparse Row format>]],
      dtype=object)

matmul does the same thing, but can't work with scalars (which is what [22] is):

In [27]: np.matmul(x,w)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [27], in <cell line: 1>()
----> 1 np.matmul(x,w)

ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)

From the main sparse docs page, https://docs.scipy.org/doc/scipy/reference/sparse.html

Warning

As of NumPy 1.7, np.dot is not aware of sparse matrices, therefore 
using it will result on unexpected results or errors. The 
corresponding dense array should be obtained first instead:

np.dot(A.toarray(), v)
array([ 1, -3, -1], dtype=int64)

but then all the performance advantages would be lost.

and

 Despite their similarity to NumPy arrays, it is strongly discouraged 
 to use NumPy functions directly on these matrices because NumPy may 
 not properly convert them for computations, leading to unexpected 
 (and incorrect) results.
Related