Anteriormente pregunté esto en StackOverflow, pero parece que podría ser más apropiado aquí, dado que no obtuvo ninguna respuesta en SO. Es una especie de intersección entre estadísticas y programación.
Necesito escribir un código para hacer PCA (Análisis de componentes principales). He examinado los algoritmos conocidos e implementado este , que por lo que puedo decir es equivalente al algoritmo NIPALS. Funciona bien para encontrar los primeros 2-3 componentes principales, pero luego parece ser muy lento para converger (del orden de cientos a miles de iteraciones). Aquí están los detalles de lo que necesito:
El algoritmo debe ser eficiente cuando se trata con un gran número de características (orden de 10,000 a 20,000) y tamaños de muestra del orden de unos pocos cientos.
Debe ser razonablemente implementable sin una biblioteca de álgebra / matriz lineal decente, ya que el lenguaje de destino es D, que aún no tiene uno, e incluso si lo tuviera, preferiría no agregarlo como una dependencia al proyecto en cuestión .
Como nota al margen, en el mismo conjunto de datos, R parece encontrar todos los componentes principales muy rápido, pero utiliza una descomposición de valores singulares, que no es algo que quiera codificar yo mismo.
Respuestas:
Implementé la SVD aleatoria como se indica en "Halko, N., Martinsson, PG, Shkolnisky, Y., y Tygert, M. (2010). Un algoritmo para el análisis de componentes principales de grandes conjuntos de datos. Arxiv preprint arXiv: 1007.5510, 0526. Recuperado el 1 de abril de 2011, de http://arxiv.org/abs/1007.5510 ". Si desea obtener SVD truncado, realmente funciona mucho más rápido que las variaciones de svd en MATLAB. Puedes obtenerlo aqui:
Para probarlo, simplemente cree una imagen en la misma carpeta (como una matriz grande, puede crear la matriz usted mismo)
Cuando lo ejecuto en mi escritorio para obtener una imagen de tamaño 635 * 483, obtengo
Como puede ver, para valores bajos de
k
, es más de 10 veces más rápido que usar Matlab SVD. Por cierto, es posible que necesite la siguiente función simple para la función de prueba:No agregué el método PCA ya que es fácil de implementar usando SVD. Puede consultar este enlace para ver su relación.
fuente
podrías intentar usar un par de opciones.
1- Descomposición matricial penalizada . Aplica algunas restricciones de penalización en las u y las v para obtener cierta dispersión. Algoritmo rápido que se ha utilizado en datos genómicos.
Ver Whitten Tibshirani. También tienen un R-pkg. "Una descomposición de matriz penalizada, con aplicaciones para dispersar componentes principales y análisis de correlación canónica".
2- SVD aleatorizado . Dado que SVD es un algoritmo maestro, puede ser conveniente encontrar una aproximación muy rápida, especialmente para el análisis exploratorio. Usando SVD aleatorio, puede hacer PCA en grandes conjuntos de datos.
Ver Martinsson, Rokhlin y Tygert "Un algoritmo aleatorio para la descomposición de matrices". Tygert tiene código para una implementación muy rápida de PCA.
A continuación se muestra una implementación simple de SVD aleatorizada en R.
fuente
Parece que tal vez quieras usar el algoritmo de Lanczos . De lo contrario, es posible que desee consultar Golub & Van Loan. Una vez codifiqué un algoritmo SVD (en SML, de todos los idiomas) de su texto, y funcionó razonablemente bien.
fuente
Sugeriría probar el kernel PCA que tiene una complejidad de tiempo / espacio que depende de la cantidad de ejemplos (N) en lugar de la cantidad de características (P), lo que creo que sería más adecuado en su entorno (P >> N)). Kernel PCA básicamente funciona con la matriz de kernel NxN (matriz de similitudes entre los puntos de datos), en lugar de la matriz de covarianza PxP, que puede ser difícil de manejar para P. grande. Otra cosa buena sobre la PCA de kernel es que puede aprender proyecciones no lineales también si lo usa con un núcleo adecuado. Vea este documento sobre el kernel PCA .
fuente
Me parece recordar que es posible realizar PCA calculando la descomposición propia de X ^ TX en lugar de XX ^ T y luego transformar para obtener las PC. Sin embargo, no puedo recordar los detalles de antemano, pero está en el libro (excelente) de Jolliffe y lo buscaré la próxima vez que esté en el trabajo. Transliteraría las rutinas de álgebra lineal de, por ejemplo, métodos numéricos en C, en lugar de usar cualquier otro algoritmo.
fuente
También existe el método bootstrap de Fisher et al , diseñado para varios cientos de muestras de alta dimensión.
La idea principal del método se formula como "el remuestreo es una transformación de baja dimensión". Entonces, si tiene un número pequeño (varios cientos) de muestras de alta dimensión, entonces no puede obtener más componentes principales que el número de sus muestras. Por lo tanto, tiene sentido considerar las muestras como una base parsimoniosa, proyectar los datos en el subespacio lineal que abarcan estos vectores y calcular PCA dentro de este subespacio más pequeño. También proporcionan más detalles sobre cómo tratar el caso cuando no todas las muestras se pueden almacenar en la memoria.
fuente
Ver el artículo de Sam Roweis, Algoritmos EM para PCA y SPCA .
fuente