scipy.sparse.csr_matrix.toarray()占用大量内存

oba*_*tos 5 python memory numpy scipy sparse-matrix

我有一个相当大的稀疏矩阵A作为scipy.sparse.csr_matrix。它具有以下属性:

A.shape: (77169, 77169)
A.nnz: 284811011
A.dtype: dtype('float16')
Run Code Online (Sandbox Code Playgroud)

现在我必须使用将其转换为密集数组.toarray()。我对内存使用量的估计是

77169**2 * (16./8.) / 1024.**3 = 11.09... GB
Run Code Online (Sandbox Code Playgroud)

这很好,因为我的机器有 ~48GB 内存。事实上,如果我创建的a=np.ones((77169, 77169), dtype=np.float16)话,效果确实很好a.nbytes/1024.**3 = 11.09...。但是,当我A.toarray()在稀疏矩阵上运行时,它会打包所有内存并在某个时刻开始使用交换(它不会引发MemoryError)。这里出了什么问题?难道它不应该很容易融入我的记忆吗?

hpa*_*ulj 2

对于csr toarray()does

self.tocoo(copy=False).toarray(order=order, out=out)
Run Code Online (Sandbox Code Playgroud)

你可以继续跟踪coo.toarray,但我怀疑它最终会使用编译的代码。但我怀疑它最终会做相当于:

In [715]: M=sparse.random(10,10,.2,format='csr')
In [717]: M=M.astype(np.float16)
In [718]: A = np.zeros(M.shape, M.dtype)
In [719]: Mo=M.tocoo()
In [720]: A[Mo.row, Mo.col] = Mo.data
Run Code Online (Sandbox Code Playgroud)

奇怪的是如果我这样做

In [728]: Mo.toarray()
     ...
    257         coo_todense(M, N, self.nnz, self.row, self.col, self.data,
--> 258                     B.ravel('A'), fortran)
    259         return B
...
ValueError: Output dtype not compatible with inputs.
Run Code Online (Sandbox Code Playgroud)

它遇到了麻烦float16Mo.astype(float).toarray()工作正常。即使使用toarray(out=out)float16 输出,我也会收到此错误,这让我怀疑coo_todense仅使用几个 dtype 替代方案进行编译。也许我稍后会深入探讨这一点。

In [741]: scipy.__version__
Out[741]: '0.18.1'
Run Code Online (Sandbox Code Playgroud)

Warren 的错误报告中的评论

但 xxx_todense 函数实际上是 A += X,

Mo.data表明从到 的副本A[]比指示的更复杂。 toarray对重复项进行求和,就像使用Mo.tocsr()or一样Mo.sum_duplicates()