【问题标题】:How to compute Dot product between very large scipy sparse matrix如何计算非常大的 scipy 稀疏矩阵之间的点积
【发布时间】:2014-09-13 23:51:01
【问题描述】:

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

矩阵的形状(371744、36154) 非零数 - 577731 [非常稀疏]

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

    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 说,
“从 NumPy 1.7 开始,np.dot 不知道稀疏矩阵,因此使用它会导致意外结果或错误。应该获得相应的密集矩阵首先是"

当我使用 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

我还怎么做这个乘法?

【问题讨论】:

  • 这是一个已知问题(您有更多适合 32 位 int 的非零项),已在最近的 scipy 版本中解决。更新到最新版本,您就可以上路了。
  • 这行得通,但我仍然需要巨大的点积!我无法将其放入内存中,我现在出现内存错误!
  • 购买更多内存怎么样?
  • 如果我对 LinAlg 的记忆有问题,请提前原谅。你可以把问题分解成更小的块,以后可以重新组合吗? AB 会不会与 Abi 的 i 上的总和相同,其中 bi 是 B 的第 i 个 col?您可以扩展它并从 B 的子集制作矩阵(一次可能是 1/4 的列)。不知道这会有多有效,但我认为它会完成工作。也非常容易进行并行计算。
  • 你试过用稀疏矩阵的dot属性代替np.dot吗?

标签: python numpy scipy sparse-matrix matrix-multiplication


【解决方案1】:

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

dp_data = data_m.dot(data_m)

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

【讨论】:

  • 对于稀疏数组*dot 产品。所以data_m*data_m 做了你建议的同样的事情。真正的问题是scipy 版本,而不是dot 的调用方式。
【解决方案2】:

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

首先要意识到的是,在这种特定情况下 (a * a.T),您实际上是在计算每一行(一个 36154 元素向量)与每一行的点积。这可以帮助您将计算时间减少一半,因为结果将是对称的。 (这会留下大约 50 000 000 000 个矢量点积。)

现在,无论您是否着急,问题都很多。如果您赶时间(性能很重要),那么可能有一些方法可以加快计算速度,具体取决于非零值在数据中的分布情况。

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

# 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] 中的非零元素集的交集来计算。大部分时间交叉点是空的,只有在不为空的时候才需要计算。

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

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

【讨论】:

    猜你喜欢
    • 2012-12-20
    • 2014-10-11
    • 2019-06-28
    • 2015-09-11
    • 2018-06-04
    • 1970-01-01
    • 2015-01-10
    • 2019-09-10
    • 2021-12-24
    相关资源
    最近更新 更多