2015-07-15 12 views
7

Właśnie próbowałem używać IncrementalPCA z sklearn.decomposition, ale rzucił MemoryError tak jak wcześniej PCA i RandomizedPCA. Mój problem polega na tym, że matryca, którą próbuję wczytać, jest zbyt duża, aby zmieścić się w pamięci RAM. Obecnie jest przechowywany w bazie danych hdf5 jako zbiór danych o kształcie ~ (1000000, 1000), więc mam 1.000.000.000 wartości float32. Myślałem, że IncrementalPCA ładuje dane w partiach, ale najwyraźniej próbuje załadować cały zestaw danych, co nie pomaga. W jaki sposób ma służyć ta biblioteka? Czy format hdf5 jest problemem?Przyrostowy PCA na dużych danych

from sklearn.decomposition import IncrementalPCA 
import h5py 

db = h5py.File("db.h5","r") 
data = db["data"] 
IncrementalPCA(n_components=10, batch_size=1).fit(data) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/sklearn/decomposition/incremental_pca.py", line 165, in fit 
    X = check_array(X, dtype=np.float) 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/sklearn/utils/validation.py", line 337, in check_array 
    array = np.atleast_2d(array) 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/numpy/core/shape_base.py", line 99, in atleast_2d 
    ary = asanyarray(ary) 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/numpy/core/numeric.py", line 514, in asanyarray 
    return array(a, dtype, copy=False, order=order, subok=True) 
    File "h5py/_objects.pyx", line 54, in h5py._objects.with_phil.wrapper (-------src-dir-------/h5py/_objects.c:2458) 
    File "h5py/_objects.pyx", line 55, in h5py._objects.with_phil.wrapper (-------src-dir-------/h5py/_objects.c:2415) 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/h5py/_hl/dataset.py", line 640, in __array__ 
    arr = numpy.empty(self.shape, dtype=self.dtype if dtype is None else dtype) 
MemoryError 

Dzięki za pomoc

Odpowiedz

14

program, który jest prawdopodobnie w przypadku braku próby załadowania całego zestawu danych do pamięci RAM. 32 bity na element pływający32 × 1 000 000 × 1000 to 3,7 GiB. To może być problem na maszynach z tylko 4 GB pamięci RAM. Aby sprawdzić, czy jest to rzeczywiście problem, spróbuj utworzyć tablicę tylko w tym rozmiarze:

>>> import numpy as np 
>>> np.zeros((1000000, 1000), dtype=np.float32) 

Jeśli widzisz MemoryError, albo trzeba więcej pamięci RAM, albo trzeba przetworzyć zestawu danych jeden kawałek na raz.

W przypadku zbiorów danych h5py powinniśmy po prostu pominąć przekazywanie całego zestawu danych naszym metodom i zamiast tego przekazywać wycinki zbioru danych. Jeden na raz.

Ponieważ nie mam danych, zacznę od tworzenia losowy zbiór danych o tej samej wielkości:

import h5py 
import numpy as np 
h5 = h5py.File('rand-1Mx1K.h5', 'w') 
h5.create_dataset('data', shape=(1000000,1000), dtype=np.float32) 
for i in range(1000): 
    h5['data'][i*1000:(i+1)*1000] = np.random.rand(1000, 1000) 
h5.close() 

Tworzy miłą 3.8 plik Gib.

Teraz, gdy jesteśmy w Linuksie, możemy ograniczyć ilość pamięci jest dostępna do naszego programu:

$ bash 
$ ulimit -m $((1024*1024*2)) 
$ ulimit -m 
2097152 

Teraz, jeśli spróbujemy uruchomić kod, będziemy uzyskać MemoryError. (naciśnij Ctrl-D, aby opuścić nową sesję bash i później wyzerować limit)

Spróbujmy rozwiązać problem. Stworzymy obiekt IncrementalPCA i wielokrotnie będziemy wywoływać jego metodę .partial_fit(), dostarczając za każdym razem inny kawałek zestawu danych.

import h5py 
import numpy as np 
from sklearn.decomposition import IncrementalPCA 

h5 = h5py.File('rand-1Mx1K.h5') 
data = h5['data'] # it's ok, the dataset is not fetched to memory yet 

n = data.shape[0] # how many rows we have in the dataset 
chunk_size = 1000 # how many rows we feed to IPCA at a time, the divisor of n 
icpa = IncrementalPCA(n_components=10, batch_size=16) 

for i in range(0, n//chunk_size): 
    ipca.partial_fit(data[i*chunk_size : (i+1)*chunk_size]) 

Wydaje się, że pracuje dla mnie, a jeśli spojrzeć na to, co top sprawozdaniach pobytów alokacji pamięci poniżej 200M.

+0

Okej, więc zasadniczo nie powinienem nazywać się fit, ale partial_fit kilka razy. Nie widziałem tej metody, ponieważ samouczek używa dopasowania. Czy wiesz, dlaczego fit ma parametr batch_size dla, jeśli ładuje cały zestaw danych jednocześnie? – KrawallKurt

+0

Trwa nie ładowanie wszystkich danych w pamięci zapewne jest zapewnione przez bibliotekę h5py. Jego obiekt dataset ('h5 ​​['data']') wydaje się zachowywać jak zwykła tablica numpy, ale tak nie jest. 'IncrementalPCA' nie wie, że jest strukturą danych na dysku, i w pewnym momencie odczytuje wszystkie wiersze (' MemoryError'!). Obliczenia są nadal wykonywane w partiach 'batch_size'. – sastanin

+1

To dzieje się w 'fit()', który [wywołuje check_array()] (https://github.com/scikit-learn/scikit-learn/blob/0.16.1/sklearn/decomposition/incremental_pca.py#L165), który ma przekonwertować dane na regularną tablicę numpy (https://github.com/scikit-learn/scikit-learn/blob/0.16.1/sklearn/utils/validation.py#L268) Wywołanie "partial_fit() 'omija tę konwersję. – sastanin

Powiązane problemy