2015-06-17 52 views
0

我有一個(非常大)的數據集。大小約爲250,000個二進制向量,每個大小爲800.
數據集駐留在(壓縮表示形式)的(.txt ascii編碼)文件中。意思是,該文件中的每一行代表一個矢量的外觀,而不是800個字符的零和一個。
例如,假設第i個線在該文件中看起來像這樣:Python:序列化/反序列化大量數據

12 14 16 33 93 123 456 133 

這意味着第i個向量是與它的12'th 14'th,16'th的載體, ......第133個指數值爲1,其餘爲零。

該文件的大小略大於30MB。因爲我使用這些數據來提供一個神經網絡,所以這些數據需要進行一些預處理,以便將其轉化爲網絡所期望的:列表大小爲250,000,其中該列表中的每個元素都是20x40矩陣(其中,列表清單)零和一個。
例如,如果我們重新調整的問題4×2,這是最後的名單是什麼樣子:

[[[1,0],[1,1],[0,0],[1,0]], [[0,0],[0,1],[1,0],[1,0]], ..., [[1,1],[0,1],[0,0],[1,1]]] 

(只,而不是4×2我有20X40矩陣)。

所以我寫了兩個函數:load_data() - 解析文件並返回800個二進制列表的列表,以及reshape() - 將列表重塑爲20x40矩陣。
不用說,當load_data()reshape()正在運行時,我可憐的筆記本電腦真的很難工作。完成預處理需要大約7-9分鐘,而在那段時間內,我可以在我的筆記本電腦上做大麥。即使最小化IDE窗口也是一項非常困難的任務。
由於我使用這些數據來調整神經網絡,我發現自己經常會殺死正在運行的進程,重新調整網絡並重新開始 - 每次重新啓動都會導致load_data()後跟reshape()。因此,我決定通過加載數據 - >轉換爲二進制向量 - 重新構建這一痛苦的過程來簡化它。
我想從文件中加載數據,轉換爲二進制向量,重新整形並將其序列化爲文件my_input
現在,無論何時我需要喂網絡,我都可以對my_input的數據進行反序列化,並省去很多時間。
這是我做的:

input_file=open('my_input', 'wb') 

print 'loading data from file...' 
input_data=load_data() # this will load the data from file and will re-encode it to binary vectors 

print 'reshaping...' 
reshaped_input=reshape(input_data) 

print 'writing to file...' 
cPickle.dump(reshaped_input, input_file, HIGHEST_PROTOCOL) 
input_file.close() 

問題是這樣的:
得到的文件是巨大的; 1.7GB大小,看起來遊戲並不值得(我希望我使用它的權利),因爲它需要太多的時間來加載它(沒有衡量多少,我只是試圖加載它,並且9-10分鐘後,我放棄並殺死了這個過程)。

爲什麼生成的文件比原來的要大得多(我希望它會更大,但不是那麼多)?
是否有另一種編碼數據的方法(serialize/de-serialize wise),這將導致一個較小的文件,並將值得我同時?
或者,或者,如果任何人都可以提出更好的方法來加快速度(除了購買更快的計算機),那也會很棒。

p。當涉及到反序列化時,我不關心兼容性問題。我的電腦上唯一一個將這些數據反序列化的地方。

+1

你試過numpy.save嗎?有些版本也包括壓縮.. http://docs.scipy.org/doc/numpy/reference/generated/numpy.save.html – bsa

+0

雖然與您的問題沒有關係......如果您有'800'尺寸特徵向量和「唯一」250000個樣本,那麼在將數據提供給您的神經網絡之前,不要忘記嘗試對訓練集進行維數降低! (如果你還沒有這樣做,當然);-) – Peque

+0

@Peque,謝謝你的提示。 –

回答

2

如果你要存儲一個比特的數據中的每一個值,你會最終有一個25MB的文件;所以你的「壓縮」方案實際上是讓你的文件更大。你目前的方案的唯一好處是你可以用ascii存儲你的數據。

計算:

250.000 * 800 bits = 250.000 * 100 bytes = 25.000.000 bytes = 25 MB 

因此,只要手動存儲的位模式,閱讀他們回來,和你的計算去。

編輯:看起來像阻力最小的路徑是使用第三方模塊packbits(即您需要下載它)。你必須首先將你的一長串矩陣平鋪在一個平面列表中(作爲一個迭代器),把它寫成一系列位(注意:每32位int可以用32個值「打包」 - 不僅僅是您在評論中建議的一個值),然後對輸入進行反向轉換。列表展平食譜是一打一毛錢(請參閱here),但是這裏有一個帶有互補不展開代碼的代碼。

from itertools import zip_longest  
def chunks(iterable, size): 
    "chunks(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g', 0, 0)" 
    return zip_longest(*[iter(iterable)]*size, fillvalue=0) 

def flatten(data): 
    """Convert a list of N x M matrices into a flat iterator""" 
    return (v for matrix in data for row in matrix for v in row) 

def unflatten(data, n, m): 
    """Convert a flat sequence (of ints) into a list of `n` by `m` matrices""" 
    msize = n * m 
    for chunk in chunks(data, msize): 
     yield [ chunk[i:i+m] for i in range(0, msize, m) ] 

如果sampledata是4×2矩陣的樣本陣列,

rt = list(unflatten(flatten(sampledata), 4, 2)) 

是具有相同的結構和值(但元組而不是行陣列)的列表。你可以填寫其餘的嗎?

+0

這是「閱讀他們回來」,我很擔心。如果我要將它們保存爲位,這意味着數據將不得不轉變爲網絡所期望的;每當從25MB文件加載數據時,整數列表(零和1)列表的列表。每一位都需要轉換爲四個字節的整數,代表零或一個整數。 –

+0

夠公平的。讓我仔細研究一下,看看編寫一些代碼來循環訪問數據是多麼容易。但是,爲什麼使用列表而不是numpy數組? – alexis

+0

因爲它們更容易工作,至少對我而言。我在序列化之前將所有列表轉換爲數組,然後在numpy.asarray之前(在reshape()之前...列表沒有reshape())。 –