PCA troppo lento quando entrambi n, p sono grandi: alternative?


9

Impostazione del problema

Ho punti dati (immagini) di alta dimensione (4096), che sto cercando di visualizzare in 2D. A tal fine, sto usando t-sne in un modo simile al seguente codice di esempio di Karpathy .

La documentazione di scikit-learn consiglia di utilizzare PCA per ridurre prima la dimensione dei dati:

Si consiglia vivamente di utilizzare un altro metodo di riduzione della dimensionalità (ad esempio PCA per dati densi o TruncatedSVD per dati sparsi) per ridurre il numero di dimensioni a un importo ragionevole (ad esempio 50) se il numero di funzioni è molto elevato.

Sto usando questo codice di Darks.Liu per eseguire PCA in Java:

//C=X*X^t / m
DoubleMatrix covMatrix = source.mmul(source.transpose()).div(source.columns);
ComplexDoubleMatrix eigVal = Eigen.eigenvalues(covMatrix);
ComplexDoubleMatrix[] eigVectorsVal = Eigen.eigenvectors(covMatrix);
ComplexDoubleMatrix eigVectors = eigVectorsVal[0];
//Sort sigen vector from big to small by eigen values 
List<PCABean> beans = new ArrayList<PCA.PCABean>();
for (int i = 0; i < eigVectors.columns; i++) {
    beans.add(new PCABean(eigVal.get(i).real(), eigVectors.getColumn(i)));
}
Collections.sort(beans);
DoubleMatrix newVec = new DoubleMatrix(dimension, beans.get(0).vector.rows);
for (int i = 0; i < dimension; i++) {
    ComplexDoubleMatrix dm = beans.get(i).vector;
    DoubleMatrix real = dm.getReal();
    newVec.putRow(i, real);
}
return newVec.mmul(source);

Usa jblas per le operazioni di algebra lineare, che da quello che ho letto dovrebbe essere l'opzione più veloce là fuori. Tuttavia, il calcolo degli autovettori e degli autovalori (righe 3,4) risulta essere un enorme collo di bottiglia (~ 10 minuti, che è molto più lungo di quello che posso permettermi in questa fase).

Ho letto del Kernel PCA che dovrebbe essere buono per i casi in cui la dimensione è molto grande, ma il suo tempo di esecuzione è che potrebbe essere problematico poiché voglio anche occuparmi di casi sia di dimensione che di numero di esempi di grandi dimensioni.O(n3)

A mio avviso, le mie opzioni sono o "ottimizzare" la PCA o optare per un altro metodo di riduzione della dimensionalità che è intrinsecamente più veloce.

Le mie domande

  1. C'è qualche speranza che la PCA possa essere utilizzata in modo "offline"? cioè, usando un ampio set di dati di immagini, esegui PCA su di esse e quindi utilizza i componenti principali calcolati per loro per ridurre la dimensione di altri (nuovi!) punti dati?
  2. Posso accelerare il calcolo degli autovettori, supponendo di sapere in anticipo che sono interessato solo, diciamo, ai primi 100 componenti principali?
  3. Esiste un metodo di riduzione della dimensionalità alternativo appropriato nel mio caso (cioè prima di applicare t-sne) che sarà più veloce di PCA? Sto cercando qualcosa che possa essere implementato facilmente in Java.

Risposte:


8

Domanda 1: Supponiamo che tu abbia osservato una matrice di dati . Da questo si può calcolare l'eigendecomposition . La domanda ora è: se otteniamo nuovi dati dalla stessa popolazione, forse raccolti in una matrice , sarà vicino alla rotazione ortogonale ideale di ? Questo tipo di domanda è affrontata dal teorema di Davis-Kahan e dalla teoria della perturbazione della matrice in generale (se riesci a trovare una copia, il libro di testo di Stewart e Sun del 1990 è il riferimento standard). X T X = Q Λ Q T Z R m × p Z Q ZXRn×pXTX=QΛQTZRm×pZQZ

Domanda 2: puoi sicuramente accelerare le cose se sai di aver bisogno solo dei migliori autovettori . In RI utilizzare per questo; Sono sicuro che esiste un equivalente Java poiché sono comunque tutti involucri fortran.krARPACK

Domanda 3: Non so nulla delle implementazioni Java, ma questo thread discute sull'accelerazione della PCA come fa questo thread CV. C'è un sacco di ricerche su questo genere di cose e ci sono tonnellate di metodi là fuori che usano cose come approssimazioni di basso rango o randomizzazione.


3

Il codice che stai utilizzando invertirà l'intera matrice. Questo è probabilmente già O (p ^ 3). Puoi approssimare il risultato in O (p ^ 2) ma sarà comunque lento (ma probabilmente 100 volte più veloce). In sostanza, prendi un vettore arbitrario e esegui iterazioni di potenza. Con alta probabilità, otterrai una buona approssimazione del primo autovettore. Quindi rimuovere questo fattore dalla matrice, ripetere per ottenere il secondo. Eccetera.

Ma hai provato se le veloci implementazioni tSNE di Barnes Hut in ELKI potrebbero forse funzionare solo sui tuoi dati con un indice come l'albero di copertura? Ho fatto in modo che l'implementazione funzionasse bene quando gli altri fallivano.


3
Cosa significa "whp". rappresentare?
Kodiologo

Con alta probabilità. Vedi la letteratura statistica.
Ha QUIT - Anony-Mousse il

2

Se il tuo obiettivo è solo quello di effettuare la riduzione dimensionale in modo semplice e diretto, puoi provare una tecnica di minimi quadrati alternati (ALS). Ad esempio Apache Spark mlibha un'implementazione ALS e credo che offra un API Java. Questo dovrebbe darti una matrice e una matrice . La matrice conterrà vettori di riga visualizzabili.K × p K × pn×KK×pK×p

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.