【问题标题】:Store and retrieve large sparse matrix [closed]存储和检索大型稀疏矩阵
【发布时间】:2013-04-09 00:34:13
【问题描述】:

我有一个相当大的稀疏矩阵,我估计它在加载到内存时会占用 1Gb。

我不需要随时访问整个矩阵,所以某种内存映射会起作用;但是,似乎不可能使用 numpy 或辣(我熟悉的工具)来内存映射稀疏矩阵。

它可以很容易地放入内存中,但是如果我每次运行程序时都必须加载它会很痛苦。也许有什么方法可以在运行之间将它保存在内存中?

那么,你有什么建议: 1.找到一种方法来记忆映射一个稀疏矩阵; 2.每次都将整个想法加载到内存中 3. ?

【问题讨论】:

  • 你的矩阵是如何存储的?您希望将矩阵的哪些部分同时加载到内存中?如所问,您的问题是广泛回答的方式......

标签: python memory matrix numpy sparse-matrix


【解决方案1】:

以下可能是一个一般概念,但您将不得不弄清楚很多细节......您应该首先熟悉CSR format,其中一个数组的所有信息都存储在3个数组中,length 中的两个是非零条目的数量,length 中的一个是行数加一:

>>> import scipy.sparse as sps
>>> a = sps.rand(10, 10, density=0.05, format='csr')
>>> a.toarray()
array([[ 0.        ,  0.46531486,  0.03849468,  0.51743202,  0.        ],
       [ 0.        ,  0.67028033,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.9967058 ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ]])
>>> a.data
array([ 0.46531486,  0.03849468,  0.51743202,  0.67028033,  0.9967058 ])
>>> a.indices
array([1, 2, 3, 1, 4])
>>> a.indptr
array([0, 3, 4, 4, 5, 5])

所以a.data 具有非零条目,按行主要顺序,a.indices 具有非零条目的相应列索引,a.indptr 具有其他两个数组的起始索引,其中数据为每一行都开始,例如a.indptr[3] = 4a.indptr[3+1] = 5,因此第四行中的非零条目是 a.data[4:5],它们的列索引是 a.indices[4:5]

因此,您可以将这三个数组存储在磁盘中,并将它们作为 memmap 访问,然后您可以按如下方式检索 m 到 n 行:

ip = indptr[m:n+1].copy()
d = data[ip[0]:ip[-1]]
i = indices[ip[0]:ip[-1]]
ip -= ip[0]
rows = sps.csr_matrix((d, i, ip))

作为一般概念证明:

>>> c = sps.rand(1000, 10, density=0.5, format='csr')
>>> ip = c.indptr[20:25+1].copy()
>>> d = c.data[ip[0]:ip[-1]]
>>> i = c.indices[ip[0]:ip[-1]]
>>> ip -= ip[0]
>>> rows = sps.csr_matrix((d, i, ip))
>>> rows.toarray()
array([[ 0.        ,  0.        ,  0.        ,  0.        ,  0.55683501,
         0.61426248,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.67789204,  0.        ,  0.71821363,
         0.01409666,  0.        ,  0.        ,  0.58965142,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.1575835 ,  0.08172986,
         0.41741147,  0.72044269,  0.        ,  0.72148343,  0.        ],
       [ 0.        ,  0.73040998,  0.81507086,  0.13405909,  0.        ,
         0.        ,  0.82930945,  0.71799358,  0.8813616 ,  0.51874795],
       [ 0.43353831,  0.00658204,  0.        ,  0.        ,  0.        ,
         0.10863725,  0.        ,  0.        ,  0.        ,  0.57231074]])
>>> c[20:25].toarray()
array([[ 0.        ,  0.        ,  0.        ,  0.        ,  0.55683501,
         0.61426248,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.67789204,  0.        ,  0.71821363,
         0.01409666,  0.        ,  0.        ,  0.58965142,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.1575835 ,  0.08172986,
         0.41741147,  0.72044269,  0.        ,  0.72148343,  0.        ],
       [ 0.        ,  0.73040998,  0.81507086,  0.13405909,  0.        ,
         0.        ,  0.82930945,  0.71799358,  0.8813616 ,  0.51874795],
       [ 0.43353831,  0.00658204,  0.        ,  0.        ,  0.        ,
         0.10863725,  0.        ,  0.        ,  0.        ,  0.57231074]])

【讨论】:

    【解决方案2】:

    Scipy 支持different kinds of sparse matrices。但是您必须编写一个例程才能将其读入内存。你应该使用哪种类型取决于你想用它做什么。

    如果您的矩阵非常稀疏,您可以使用struct 模块将(row, column, value) 元组作为二进制数据保存到磁盘。假设可移植性不是问题,这将使磁盘上的数据更小并且更容易加载。

    然后您可以像这样读取数据:

    import struct
    from functools import partial
    
    fmt = 'IId'
    size = struct.calcsize(fmt)
    
    with open('sparse.dat', 'rb') as infile:
        f = partial(infile.read, size)
        for chunk in iter(f, ''):
            row, col, value = struct.unpack(fmt, chunk)
            # put it in your matrix here
    

    【讨论】:

      猜你喜欢
      • 2013-11-16
      • 2015-09-01
      • 2015-03-01
      • 2013-06-09
      • 2019-03-12
      • 2021-09-22
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多