PCA trop lent lorsque les deux n, p sont grands: Alternatives?

9

Configuration du problème

J'ai des points de données (images) de grande dimension (4096), que j'essaie de visualiser en 2D. À cette fin, j'utilise t-sne d'une manière similaire à l' exemple de code suivant de Karpathy .

La documentation de scikit-learn recommande d'utiliser PCA pour réduire d'abord la dimension des données:

Il est fortement recommandé d'utiliser une autre méthode de réduction de dimensionnalité (par exemple PCA pour les données denses ou TruncatedSVD pour les données clairsemées) pour réduire le nombre de dimensions à une quantité raisonnable (par exemple 50) si le nombre de caractéristiques est très élevé.

J'utilise ce code de Darks.Liu pour effectuer PCA en 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);

Il utilise des jblas pour les opérations d'algèbre linéaire, qui d'après ce que j'ai lu est censé être l'option la plus rapide. Cependant, le calcul des vecteurs propres et des valeurs propres (lignes 3,4) s'avère être un énorme goulot d'étranglement (~ 10 minutes, ce qui est beaucoup plus long que ce que je peux me permettre pour cette étape).

J'ai lu sur Kernel PCA qui est censé être bon pour les cas dans lesquels la dimension est très grande, mais son exécution est ce qui pourrait être problématique car je veux également traiter les cas à la fois de dimension et de nombre d'exemples étant grand.O(n3)

Selon moi, mes options sont soit «d'optimiser» l'ACP, soit d'opter pour une autre méthode de réduction de dimensionnalité qui est intrinsèquement plus rapide.

Mes questions

  1. Y a-t-il un espoir que l'ACP puisse être utilisée de manière "hors ligne"? c'est-à-dire, en utilisant un grand ensemble de données d'images, effectuer une ACP sur celles-ci, puis utiliser les principaux composants calculés pour eux afin de réduire la dimension d' autres (nouveaux!) points de données?
  2. Puis-je accélérer le calcul des vecteurs propres, en supposant que je sache à l'avance que je ne suis intéressé que, disons, par les 100 principaux composants principaux?
  3. Existe-t-il une autre méthode de réduction de la dimensionnalité appropriée dans mon cas (c'est-à-dire avant d'appliquer le t-sne) qui sera plus rapide que l'ACP? Je cherche quelque chose qui peut être implémenté facilement en Java.
galoosh33
la source

Réponses:

8

Question 1: Disons que vous avez observé une matrice de données . De cela , vous pouvez calculer le eigendecomposition . La question est maintenant: si nous obtenons de nouvelles données provenant de la même population, peut-être collectées dans une matrice , sera-t-il proche de la rotation orthogonale idéale de ? Ce type de question est abordé par le théorème de Davis-Kahan et la théorie des perturbations matricielles en général (si vous pouvez en obtenir une copie, le manuel de 1990 de Stewart et Sun est la référence standard).XRn×pXTX=QΛQTZRm×pZQZ

Question 2: vous pouvez certainement accélérer les choses si vous savez que vous n'avez besoin que des meilleurs vecteurs propres. Dans RI utiliser pour cela; Je suis sûr qu'il y a un équivalent Java car ce sont tous des wrappers fortran de toute façon.krARPACK

Question 3: Je ne sais rien des implémentations Java, mais ce fil discute de l'accélération de PCA comme le fait ce fil de CV. Il y a une tonne de recherches sur ce genre de chose et il y a des tonnes de méthodes qui utilisent des choses comme les approximations de bas rang ou la randomisation.

jld
la source
3

Le code que vous utilisez inversera la matrice entière. C'est probablement déjà O (p ^ 3). Vous pouvez approximer le résultat en O (p ^ 2) mais ce sera toujours lent (mais probablement 100 fois plus rapide). Essentiellement, prenez un vecteur arbitraire et effectuez des itérations de puissance. Avec une forte probabilité, vous obtiendrez une bonne approximation du premier vecteur propre. Retirez ensuite ce facteur de la matrice, répétez l'opération pour obtenir le second. Etc.

Mais avez-vous essayé si les implémentations rapides de Barnes Hut tSNE dans ELKI fonctionneront peut-être simplement sur vos données avec un index tel que l'arbre de couverture? J'ai bien travaillé cette mise en œuvre lorsque d'autres ont échoué.

A QUIT - Anony-Mousse
la source
3
Que signifie "whp". représenter?
Kodiologue
Avec une forte probabilité. Voir la littérature statistique.
A QUIT - Anony-Mousse
2

Si votre objectif est simplement d'effectuer une réduction de dimension d'une manière simple et directe, vous pouvez essayer une technique des moindres carrés alternés (ALS). Par exemple, Apache Spark mliba une implémentation ALS et je crois qu'il propose une API Java. Cela devrait vous donner une matrice et une matrice . La matrice contiendra des vecteurs de ligne visualisables.n×KK×pK×p

conjectures
la source