【问题标题】:Why is each element in a sparse csc matrix 8 bytes?为什么稀疏 csc 矩阵中的每个元素都是 8 个字节?
【发布时间】:2019-04-06 14:07:29
【问题描述】:

例如,如果我最初有一个密集矩阵:

A = numpy.array([[0, 0],[0, 1]])

然后使用 csc_matrix(A) 将其转换为 csc 稀疏矩阵。然后将矩阵存储为:

(1, 1)    1
#(row, column)   val

由三个值组成。为什么稀疏矩阵的大小只有 8 个字节,尽管计算机本质上存储了 3 个值?矩阵的大小肯定至少为 12 个字节,因为整数通常包含 4 个字节。

【问题讨论】:

    标签: python matrix memory storage


    【解决方案1】:

    我不同意稀疏矩阵的大小是 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 类型的存储元素。返回的值,根据docs

    不包括数组对象的非元素属性消耗的内存。

    这不是一个更准确的结果,只是对另一个问题的回答,正如35421869 所说的那样。

    当结果 4 明显正确时,我无法解释为什么您报告 8 字节的值。一种可能性是numpy.array([[0, 0],[0, 1]]) 实际上并不是实际转换为稀疏数组的内容。值 5 是从哪里来的? 8的值与numpy.array([[0, 0],[0, 5.0]])的起始值一致。

    您的 12 字节数字是基于两个未满足的期望。

    1. 可以将稀疏矩阵表示为三元组列表(行、列、值)。事实上,这就是 COO 矩阵的存储方式,至少在原则上是这样。但是 CSC 代表 压缩稀疏列,因此与 COO 矩阵相比,显式列索引更少。这个Wikipedia article 清楚地解释了存储的实际工作原理。
    2. nbytes 不报告存储矩阵元素的总内存成本。它报告了numpy 不变量(在许多不同类型的矩阵中)x.nbytes == np.prod(x.shape) * x.itemsize。这是一个重要的量,因为矩阵中显式存储的元素构成了它最大的附属数据结构,并且必须分配在连续的内存中。

    【讨论】:

    • 我正在使用 .data.nbytes ,我觉得它更准确地表示内存。所以 s.data.nbytes 总共会给出 8 个字节
    • 我的错误,5 应该是 1。我再次检查了代码,结果发现我使用的是浮点值而不是整数,这就解释了为什么它给出 8 个字节而不是4. 但是,我的问题仍然存在。如果它存储的是整数值 1,以及它的行和列索引 (1, 1),那么存储量肯定应该大于 4 个字节吗?
    • 不,行和列不是元素,因此不包括在内,如文档所述。它们是稀疏数组元数据的一部分,存在于 56 字节结构中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    • 2012-08-27
    • 1970-01-01
    • 2015-12-05
    • 2018-07-18
    • 2021-03-11
    • 2015-01-30
    相关资源
    最近更新 更多