例如,如果我最初有一个密集矩阵:
A = numpy.array([[0, 0],[0, 1]])
然后使用 csc_matrix(A) 将其转换为 CSC 稀疏矩阵。然后将矩阵存储为:
(1, 1) 1
#(row, column) val
它由三个值组成。为什么稀疏矩阵的大小只有 8 个字节,即使计算机基本上存储了 3 个值?当然,矩阵的大小至少为 12 个字节,因为整数通常包含 4 个字节。
我不同意稀疏矩阵的大小为 8 个字节。我可能错过了一些东西,但如果我这样做,我会得到一个非常不同的答案:
>>> import sys
>>> import numpy
>>> from scipy import sparse
>>> A = numpy.array([[0, 0],[0, 1]])
>>> s = sparse.csc_matrix(A)
>>> s
<2x2 sparse matrix of type '<class 'numpy.int32'>'
with 1 stored elements in Compressed Sparse Column format>
>>> sys.getsizeof(s)
56
这是内存中数据结构的大小,我向您保证它是准确的。Python必须知道它有多大,因为它会进行内存分配。
另一方面,如果您使用s.data.nbytes
:
>>> s.data.nbytes
4
这给出了预期的答案 4。这是意料之中的,因为s
报告自身具有一个类型为int32
的存储元素。根据文档返回的值,
不包括数组对象的非元素属性消耗的内存。
正如35421869明确指出的那样,这不是一个更准确的结果,只是对不同问题的答案。
我无法解释为什么当结果 8 明显正确时报告值 4 字节。一种可能性是numpy.array([[0, 0],[0, 1]])
实际上并不是实际转换为稀疏数组的内容。值 5 从何而来?值 8 与起始值numpy.array([[0, 0],[0, 5.0]])
一致。
您的 12 字节数字基于两个未满足的期望。
- 可以将稀疏矩阵表示为三元组(行、列、值)的列表。事实上,这就是COO矩阵的存储方式,至少在原则上是这样。但是 CSC 代表压缩稀疏列,因此显式列索引比 COO 矩阵中的索引少。这篇维基百科文章清晰地解释了存储的实际工作原理。
nbytes
不报告存储矩阵元素的总内存成本。它报告了一个numpy
不变的(在许多不同类型的矩阵上)x.nbytes == np.prod(x.shape) * x.itemsize
。这是一个重要的数量,因为矩阵的显式存储元素构成了其最大的附属数据结构,并且必须在连续内存中分配。