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

时间:2015-10-16 22:30:40

标签: python numpy pytables

我有一个庞大的2d numpy数组,它可以作为共生矩阵运行。我曾尝试使用scipy.sparse作为我的数据结构,但dok_matrix索引速度非常慢(慢4倍)。

# 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]

1 个答案:

答案 0 :(得分:0)

np.save是一种快速有效的保存密集阵列的方法。它所做的只是写一个小标题,然后是数组的数据缓冲区。

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

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

np.savez对数据存储没有帮助。它为每个变量执行save,并在zip存档(也可以压缩)中收集生成的文件。

表和h5py可以保存和加载块,但是如果你必须在某个时刻使用整个数组 - 无论是创建还是使用它都没有帮助。

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

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

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

一旦你拥有一整套coo数组,

i,j,data便于构建矩阵。

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

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

存在关于存储稀疏矩阵的SO问题。最简单的是使用MATLAB兼容的.mat格式(稀疏的csc)。要使用np.save,您需要保存基础数组(适用于coocsccsr格式)。 Python pickle必须用于保存doklil

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