Python:如何有效地将2d numpy数组保存到磁盘?

问题描述:

我有一个巨大的2d numpy数组,假设它是一个共生矩阵。我试图使用scipy.sparse作为我的数据结构,但dok_matrix索引非常慢(速度慢4倍)。Python:如何有效地将2d numpy数组保存到磁盘?

# Impossible 
import numpy 
N = 1000000 (1 milion) 
coo = np.zeros((N, N), dtype=np.uint32) 

我想坚持这个数组。

找到保存方法之后,我尝试使用PyTableshd5py,但是找不到内存不足的方法来保存它。

with open(name, 'w') as _file: 
    np.save(_file, coo) 

例如,使用PyTables

import tables 
    _file = tables.openFile(
       name, 
       mode='w', 
       title='Co-occurrence matrix') 
    atom = tables.Atom.from_dtype(coo.dtype) 
    _filters = tables.Filters(complib='blosc', complevel=5) 
    ds = _file.createEArray(
      _file.root, 
      'coo_matrix', 
      atom, 
      shape=(0, coo.shape[-1]), 
      expectedrows=coo.shape[-1], 
      filters=_filters) 
    # ds[:] = coo => not an option 
    for _index, _data in enumerate(coo): 
     ds.append(coo[_index][np.newaxis,:]) 
    _file.close() 

而且使用hd5py

import h5py 
h5f = h5py.File(name, 'w') 
h5f.create_dataset('dataset_1', data=coo) 

这两种方法都不断增加内存的使用,直到我必须杀死进程。那么,有什么办法可以逐步做到吗?如果无法做到这一点,你能推荐另一种方法来坚持这个矩阵吗?

编辑

我创建这个共生矩阵是这样的:

coo = np.zeros((N, N), dtype=np.uint32) 
    for doc_id, doc in enumerate(self.w.get_docs()): 
     for w1, w2 in combinations(doc, 2): 
       if w1 != w2: 
        coo[w1, w2] += 1 

我要救COO(2D numpy的阵列)以后从磁盘检索,发现共现值,例如:coo [w1,w2]

+0

只是为了满足我自己的好奇心:什么是*后负荷*? –

+0

除了存储你想用这个数组做什么?更改个人价值观,访问他们,访问片,数学? – hpaulj

+0

有['np.savez_compressed'选项](http://*.com/a/18232374/832621),这是非常快速和紧凑的移动数据... –

np.save是一种节省密集数组的快速高效方式。它所做的只是编写一个小标题,然后写入数组的数据缓冲区。

但是对于大型数组,该数据缓冲区将有N*N*4(对于您的dtype)字节 - 在一个连续的内存块中。该设计也适用于元素访问 - 代码确切知道i,j元素的位置。

请注意,np.zeros((N,N))不会一次分配所有必需的内存。内存使用可能会在使用过程中增长(包括保存)

np.savez对数据存储没有帮助。它为每个变量执行save,并将结果文件收集到一个zip压缩文件(也可能是压缩文件)中。

表和h5py可以保存和加载块,但是这并不能帮助如果你必须在某个时间点对整个数组进行存储 - 创建或使用。

由于您的数组将非常稀疏,因此scipy稀疏矩阵可以节省内存,因为它只存储非零元素。但它也必须存储该元素的坐标,因此非零元素的存储空间并不那么紧凑。有许多格式,每种格式都有其优点和缺点。

dok使用Python字典存储数据,其格式为(i,j)。它是增量构建稀疏矩阵的更好格式之一。我在其他SO问题中发现,使用dok的元素访问比使用普通字典要慢。建立一个常规字典的速度更快,然后updatedok

lil是增量构建的另一个很好的格式。它将数据存储在2个列表中。

coo一旦您有一整套i,j,data数组,便于构建矩阵。

csrcsc适合计算(特别是线性代数种类)和元素访问。但对于改变稀疏性(添加非零元素)没有好处。

但是,您可以用一种格式构建矩阵,并随时将其转换为另一种格式以供使用或存储。

有关于存储稀疏矩阵的问题。最简单的是与MATLAB兼容的.mat格式(稀疏的csc)。要使用np.save,您需要保存底层阵列(对于coo,csc,csr格式)。必须使用Python pickle来保存doklil

请在[scipy] large sparse上搜索以查看有关此类矩阵的其他SO问题。你不是第一个使用numpy/scipy来同时计算文档(这是scipy sparse的三个主要用途之一,其他的是线性代数和机器学习)。