2015-10-16 96 views
2

我有一個巨大的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://stackoverflow.com/a/18232374/832621),這是非常快速和緊湊的移動數據... –

回答

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的元素訪問比使用普通字典要慢。建立一個常規字典的速度更快,然後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的三個主要用途之一,其他的是線性代數和機器學習)。