2015-11-09 4 views
6

Ich versuche, PCA auf riesige Sparse-Matrix anwenden, im folgenden Link heißt es, dass randomizedPCA von sklearn kann spärliche Matrix von scipy Sparse-Format behandeln. Apply PCA on very large sparse matrixDurchführen von PCA auf großer Sparse-Matrix mit sklearn

Allerdings bekomme ich immer Fehler. Kann jemand darauf hinweisen, was ich falsch mache?

Eingangsmatrix 'X_train' enthält Zahlen in float64:

>>>type(X_train) 
<class 'scipy.sparse.csr.csr_matrix'> 
>>>X_train.shape 
(2365436, 1617899) 
>>>X_train.ndim 
2 
>>>X_train[0]  
<1x1617899 sparse matrix of type '<type 'numpy.float64'>' 
    with 81 stored elements in Compressed Sparse Row format> 

ich zu tun versucht:

>>>from sklearn.decomposition import RandomizedPCA 
>>>pca = RandomizedPCA() 
>>>pca.fit(X_train) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/sklearn/decomposition/pca.py", line 567, in fit 
    self._fit(check_array(X)) 
    File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/sklearn/utils/validation.py", line 334, in check_array 
    copy, force_all_finite) 
    File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/sklearn/utils/validation.py", line 239, in _ensure_sparse_format 
    raise TypeError('A sparse matrix was passed, but dense ' 
TypeError: A sparse matrix was passed, but dense data is required. Use X.toarray() to convert to a dense numpy array. 

wenn ich dichte Matrix zu konvertieren versuchen, ich denke, ich aus der Erinnerung bin .

>>> pca.fit(X_train.toarray()) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/scipy/sparse/compressed.py", line 949, in toarray 
    return self.tocoo(copy=False).toarray(order=order, out=out) 
    File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/scipy/sparse/coo.py", line 274, in toarray 
    B = self._process_toarray_args(order, out) 
    File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/scipy/sparse/base.py", line 800, in _process_toarray_args 
    return np.zeros(self.shape, dtype=self.dtype, order=order) 
MemoryError 
+0

Haben Sie diese Antwort in der Frage, die Sie verknüpft haben, angezeigt? http://StackOverflow.com/a/10721425/2272172 – cel

+0

Ja, aber ich möchte wissen, ob es eine Möglichkeit gibt, PCA auf riesige Sparse-Matrix anwenden (wenn möglich mit Python und sklearn) – khassan

+0

Also Sie bereits 'TruncatedSVD' verwendet und es hat nicht funktioniert? Wenn ja, dokumentieren Sie das bitte auch in Ihrer Frage. – cel

Antwort

6

Aufgrund der Art der PCA, auch wenn die Eingabe eine Sparse-Matrix ist, ist die Ausgabe nicht. Sie können es mit einem kurzen Beispiel überprüfen:

>>> from sklearn.decomposition import TruncatedSVD 
>>> from scipy import sparse as sp 

Erstellen Sie eine zufällige Sparse Matrix mit 0,01% seiner Daten als Nicht-Nullen.

>>> X = sp.rand(1000, 1000, density=0.0001) 

Nehmen PCA es:

>>> clf = TruncatedSVD(100) 
>>> Xpca = clf.fit_transform(X) 

Nun, die Ergebnisse überprüfen:

>>> type(X) 
scipy.sparse.coo.coo_matrix 
>>> type(Xpca) 
numpy.ndarray 
>>> print np.count_nonzero(Xpca), Xpca.size 
95000, 100000 

, die das jedoch 95000 der Einträge ungleich Null sind, deutet darauf hin,

>>> np.isclose(Xpca, 0, atol=1e-15).sum(), Xpca.size 
99481, 100000 

99481 Elemente sind nahe bei 0 (<1e-15), aber nicht0.

Das bedeutet kurz gesagt, dass für eine PCA, selbst wenn die Eingabe eine dünn besetzte Matrix ist, die Ausgabe nicht ist. Wenn Sie also versuchen, 100.000.000 (1e8) Komponenten aus Ihrer Matrix zu extrahieren, erhalten Sie eine 1e8 x n_features (in Ihrem Beispiel 1e8 x 1617899) dichte Matrix, die natürlich nicht im Speicher gehalten werden kann.

Ich bin kein Experte Statistiker, aber ich glaube, es gibt derzeit keine Workaraound für diese Verwendung von Scikit-lernen, wie kein Problem der Scikit-Learning-Implementierung ist, ist nur die mathematische Definition ihrer Sparse PCA (durch von spärlichem SVD), was das Ergebnis dicht macht.

Die einzige Problemumgehung, die für Sie funktionieren könnte, besteht darin, dass Sie mit einer kleinen Anzahl von Komponenten beginnen und diese erhöhen, bis Sie ein Gleichgewicht zwischen den im Speicher verbleibenden Daten und dem erklärten Prozentsatz der Daten erhalten (die Sie wie folgt berechnen können):

>>> clf.explained_variance_ratio_.sum() 
+0

Ich konnte die Anzahl der Features von 1.6M auf 500 reduzieren (gerade genug, um in den Speicher zu passen). Sieht so aus, als ob es unmöglich ist, SVD auf einer riesigen Matrix auszuführen, wenn Sie nicht sehr viel RAM haben. – khassan