numpy和稀疏矩阵之间的点积

时间:2017-10-10 13:44:27

标签: python numpy

假设我们有以下数据:

import numpy as np
from scipy.sparse import csr_matrix 
A = csr_matrix([[1, 2, 0], [0, 0, 3], [4, 0, 5]]) # (3,3)
B = np.array([[1,2],[2,3],[3,3]]) # (2,3)

然后:

A.dot(B)
array([[ 5,  8],
       [ 9,  9],
       [19, 23]])

在上面我们有sparce_matrix.dot(numpy_matrix),输出是(3,2)`。但如果我改变:

B = np.array([[1,2,3],[2,3,3],[3,3,3]])

B.dot(A)
array([[ <3x3 sparse matrix of type '<type 'numpy.int64'>'
     with 5 stored elements in Compressed Sparse Row format>,
    <3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 5 stored elements in Compressed Sparse Row format>,
    <3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 5 stored elements in Compressed Sparse Row format>],
   [ <3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 5 stored elements in Compressed Sparse Row format>,
    <3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 5 stored elements in Compressed Sparse Row format>,
    <3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 5 stored elements in Compressed Sparse Row format>],
   [ <3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 5 stored elements in Compressed Sparse Row format>,
    <3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 5 stored elements in Compressed Sparse Row format>,
    <3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 5 stored elements in Compressed Sparse Row format>]], dtype=object)

所以在上面我们有一个numpy_matrix.dot(sparce_matrix),预期的输出是(3,3),但不是。

可以通过以下方式计算:

A.T.dot(B.T).T

但是为什么第二种情况下B.dot(A)输出的这种行为?有没有办法在没有转置它的情况下做到这一点?

1 个答案:

答案 0 :(得分:1)

B.dot(A)评估为B.dot(np.array(A))。它不知道A是稀疏的,它自己是dotA.dot(B)使用A的稀疏方法。

np.array(A)A.toarray()不同。试试吧。

还试用np.dot(B, A)。它可能会给A控制,但我不确定。在任何情况下,不要假设numpy函数正确处理稀疏矩阵。如果他们委托稀疏方法,那就没关系。但是测试。

In [744]: np.array(A)
Out[744]: 
array(<3x3 sparse matrix of type '<class 'numpy.int32'>'
    with 5 stored elements in Compressed Sparse Row format>, dtype=object)
In [745]: _.shape
Out[745]: ()

所以B.dot(A) B点缀着一个&#39;标量&#39;宾语。我很惊讶dot允许这样做;我想知道这是否是一个相对较新的变化。

对于这个小例子,转置解决方案和toarray一次大致相同。

In [750]: timeit B.dot(A.A)
119 µs ± 319 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [751]: timeit A.T.dot(B.T).T
102 µs ± 2.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

强制进行稀疏计算的另一种方法 - 使B稀疏

In [758]: Bs = sparse.csr_matrix(B)
In [759]: timeit (Bs*A)
211 µs ± 9.23 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

请注意,稀疏*密集会产生密集的结果。稀疏矩阵足够稀疏,它仍然比纯密集操作更快。

相对时间将随稀疏矩阵的稀疏性以及输入和输出的大小而变化。

如果A太大而无法变成密集阵列(时间或内存约束),那么B或者结果是否太大了?如果A有很多行且列数很少,那么B(在B.dot(A)中)必须有很多列。但是,如果A包含许多列,则结果将包含尽可能多的列。所以另外一种方法是使用大型密集阵列,大小与A.toarray()相当。