首页 文章

如何计算非常大的scipy稀疏矩阵之间的Dot积

提问于
浏览
2

我试图在巨大的矩阵和它自己之间找到点积 .

矩阵的形状(371744,36154)NonZero的数字 - 577731 [非常稀疏]

mat1是scipy.sparse.csr_matrix如果我使用 mat1 * mat1.T 我得到一个值错误,这看起来像它,因为在结果矩阵中有太多的非零元素,并且索引指针根据here溢出

dp_data = data_m * data_m.T
  File "/usr/lib/python2.7/dist-packages/scipy/sparse/base.py", line 247, in __mul__
    return self._mul_sparse_matrix(other)
  File "/usr/lib/python2.7/dist-packages/scipy/sparse/base.py", line 300, in _mul_sparse_matrix
    return self.tocsr()._mul_sparse_matrix(other)
  File "/usr/lib/python2.7/dist-packages/scipy/sparse/compressed.py", line 290, in _mul_sparse_matrix
    indices = np.empty(nnz, dtype=np.intc)
ValueError: negative dimensions are not allowed

我也试过 np.dot

doc说,
"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 matrix should be obtained first instead"

当我到mat1.toarray()或todense()时,我得到一个内存错误,因为矩阵是巨大的!我有16GB的内存!该程序似乎适用于较小的输入!

data_array = data_m.toarray()
  File "/usr/lib/python2.7/dist-packages/scipy/sparse/compressed.py", line 550, in toarray
    return self.tocoo(copy=False).toarray()
  File "/usr/lib/python2.7/dist-packages/scipy/sparse/coo.py", line 219, in toarray
    B = np.zeros(self.shape, dtype=self.dtype)
MemoryError

我正在使用Numpy版本1.8.1 Numpy版本0.9.0

我怎么做这个乘法?

2 回答

  • 1

    将点积称为稀疏矩阵的方法:

    dp_data = data_m.dot(data_m)
    

    numpy.dot是一个Universal Function,它不知道你的矩阵的稀疏性,而scipy.sparse.csc_matrix.dot是一个为你的矩阵类型定制的方法,因此,使用稀疏算法 .

  • 3

    首先,稀疏输出矩阵的大小和计算所需的CPU工作量取决于稀疏矩阵的结构 . 如果有很多空行,事情会变得更容易 . 另一方面,如果您的数据均匀分布,则需要计算很多 .

    要实现的第一件事是,在这种特定情况下( a * a.T ),您实际上是计算每行的每一行(36154元素向量)的点积 . 这有助于您将计算时间减半,因为结果将是对称的 . (这为您留下了大约5亿个矢量点产品 . )

    现在,无论你是否匆忙,问题都很多 . 如果您赶时间(性能很重要),那么可能有一些方法可以使计算更快,具体取决于数据中非零的分布方式 .

    一个相当简单的算法如下:

    # a is in row-form (n_row lists of non-zeros in each row)
    
    for r in 0..n_row-1
        if all elements in the row are zero
            skip the row
        for c in r..n_row-1
            d := dot(a[c],a[r])
            if d <> 0
                result[r,c] = d
                result[c,r] = d
    

    通过查找 a[c]a[r] 中的非零元素集的交集,可以轻松计算点积 . 大部分时间交叉点都是空的,只有当它不为空时才需要进行计算 .

    根据矩阵中空行的数量,这可能相对较快 . 另一方面,如果您没有任何空行或列,则需要花费时间计算500 000 000套交叉点 . (在这种情况下,大多数是在1组之间,因此它们是简单的比较 . )

    这种方法需要很少的内存,但仍然需要很多时间,从几小时到几天,除非有很多空行 .

相关问题