2015-07-15 5 views
7

Ich habe gerade versucht, die IncrementalPCA von sklearn.decomposition verwenden, aber es warf, bevor sie eine Memory ebenso wie die PCA und RandomizedPCA. Mein Problem ist, dass die Matrix, die ich zu laden versuche, zu groß ist, um in RAM zu passen. Im Moment wird es in einer hdf5 Datenbank als Datensatz der Form ~ (1000000, 1000) gespeichert, also habe ich 1.000.000.000 float32 Werte. Ich dachte, IncrementalPCA lädt die Daten in Stapeln, aber anscheinend versucht es, den gesamten Datensatz zu laden, was nicht hilft. Wie soll diese Bibliothek verwendet werden? Ist das hdf5-Format das Problem?Incremental PCA auf große Daten

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 

Vielen Dank für Hilfe

Antwort

14

Sie Programm wahrscheinlich versagt bei dem Versuch, den gesamten Datensatz in den Arbeitsspeicher zu laden. 32 Bits pro Float32 × 1.000.000 × 1000 sind 3,7 GiB. Bei Rechnern mit nur 4 GiB RAM kann das ein Problem sein. Um zu überprüfen, dass es tatsächlich das Problem, versuchen eine Reihe von dieser Größe zu schaffen allein:

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

Wenn Sie ein MemoryError zu sehen, benötigen Sie entweder mehr RAM, oder Sie benötigen, um Ihre Daten-Set einen Brocken zu einem Zeitpunkt, zu verarbeiten.

Mit h5py Datensätze sollten wir einfach den gesamten Datensatz zu unseren Methoden vermeiden vorbei, und statt Scheiben des Datensatzes übergeben. Eins nach dem anderen.

Wie ich Ihre Daten nicht haben, lassen Sie mich von der Erstellung einer zufälligen Datensatz der gleichen Größe starten:

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() 

Es schafft eine schöne 3,8 GiB-Datei.

Wenn wir nun in Linux sind, können wir beschränken, wie viel Speicher für unser Programm zur Verfügung:

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

Nun, wenn wir versuchen, Ihren Code ausführen können, werden wir das Memory bekommen. (Drücken Sie Strg-D, um die neue Bash-Sitzung zu beenden und die Grenze zurückgesetzt später)

Lassen Sie uns versuchen, das Problem zu lösen. Wir erstellen ein IncrementalPCA-Objekt und rufen dessen Methode .partial_fit() mehrmals auf, um jedes Mal ein anderes Segment des Datasets bereitzustellen. die Speicherzuweisung bleibt unter 200M

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

Es scheint, für mich zu arbeiten, und wenn ich schauen, was top Berichte.

+0

Okay, ich soll also im Grunde nicht fit nennen, aber mehrmals partial_fit. Ich habe diese Methode nicht gesehen, weil das Tutorial fit ist. Weißt du, warum Fit den Parameter batch_size hat, wenn es den gesamten Datensatz auf einmal lädt? – KrawallKurt

+0

Der Trick, nicht alle Daten im Speicher zu laden, wird wahrscheinlich von der h5py-Bibliothek übernommen. Ihr Dataset-Objekt ('h5 ​​['data']') scheint sich wie ein normales numpy-Array zu verhalten, ist es aber nicht. 'IncrementalPCA' weiß nicht, dass es sich um eine Datenstruktur auf der Festplatte handelt, und liest irgendwann alle Zeilen (' MemoryError'!). Die Berechnung wird immer noch in 'Batch_size'-Batches ausgeführt. – sastanin

+1

Dies geschieht in 'fit()' die [Anrufe check_array()] (https://github.com/scikit-learn/scikit-learn/blob/0.16.1/sklearn/decomposition/incremental_pca.py#L165), die sollten Daten zu einem regulären numpy Array (https://github.com/scikit-learn/scikit-learn/blob/0.16.1/sklearn/utils/validation.py#L268) Aufruf 'partial_fit() konvertieren 'umgeht diese Umwandlung. – sastanin