2012-10-02 25 views
15

Tengo un gran conjunto de datos multidimensionales (132 dimensiones).Matlab - Análisis de PCA y reconstrucción de datos multidimensionales

Soy un principiante en la realización de minería de datos y deseo aplicar el Análisis de componentes principales mediante el uso de Matlab. Sin embargo, he visto que hay muchas funciones explicadas en la web, pero no entiendo cómo se deben aplicar.

Básicamente, deseo aplicar PCA y obtener los vectores propios y sus autovalores correspondientes fuera de mis datos.

Después de este paso, quiero poder hacer una reconstrucción de mis datos en función de una selección de los vectores propios obtenidos.

Puedo hacerlo manualmente, pero me preguntaba si hay funciones predefinidas que puedan hacer esto porque ya deberían estar optimizadas.

Mis datos iniciales son algo así como: size(x) = [33800 132]. Así que, básicamente, tengo 132 características (dimensiones) y 33800 puntos de datos. Y quiero realizar PCA en este conjunto de datos.

Cualquier ayuda o sugerencia sería suficiente.

Respuesta

41

He aquí un breve tutorial. Primero creamos una matriz de sus variables ocultas (o "factores"). Tiene 100 observaciones y hay dos factores independientes.

>> factors = randn(100, 2); 

Ahora cree una matriz de cargas. Esto va a mapear las variables ocultas en sus variables observadas. Supongamos que las variables observadas tienen cuatro características. Luego, su matriz de cargas debe ser 4 x 2

>> loadings = [ 
     1 0 
     0 1 
     1 1 
     1 -1 ]; 

que te dice que las primeras cargas variables observadas en el primer factor, la segunda carga en el segundo factor, la tercera cargas variables sobre la suma de los factores y la cuarta variable cargas sobre la diferencia de los factores.

Ahora crear sus observaciones:

>> observations = factors * loadings' + 0.1 * randn(100,4); 

que añade una pequeña cantidad de ruido aleatorio para simular el error experimental. Ahora realizamos la PCA utilizando la función pca de la caja de herramientas estadísticas:

>> [coeff, score, latent, tsquared, explained, mu] = pca(observations); 

La variable score es la matriz de los principales puntuaciones de los componentes. Estos serán ortogonal por construcción, que se puede comprobar -

>> corr(score) 
ans = 
    1.0000 0.0000 0.0000 0.0000 
    0.0000 1.0000 0.0000 0.0000 
    0.0000 0.0000 1.0000 0.0000 
    0.0000 0.0000 0.0000 1.0000 

La combinación score * coeff' se reproduce la versión centrada de sus observaciones. La media mu se resta antes de realizar PCA. Para reproducir sus observaciones originales que hay que añadir de nuevo en,

>> reconstructed = score * coeff' + repmat(mu, 100, 1); 
>> sum((observations - reconstructed).^2) 
ans = 
    1.0e-27 * 
    0.0311 0.0104 0.0440 0.3378 

para obtener una aproximación a los datos originales, se puede comenzar a caer las columnas de los componentes principales calculadas.Para tener una idea de las columnas que se caen, se examinan las variables explained

>> explained 
explained = 
    58.0639 
    41.6302 
    0.1693 
    0.1366 

Las entradas que indican qué porcentaje de la varianza explicada por cada uno de los componentes principales. Podemos ver claramente que los primeros dos componentes son más importantes que los dos segundos (explican más del 99% de la varianza entre ellos). El uso de los dos primeros componentes para reconstruir las observaciones da el rango-2 aproximación,

>> approximationRank2 = score(:,1:2) * coeff(:,1:2)' + repmat(mu, 100, 1); 

Ahora podemos probar el trazado:

>> for k = 1:4 
     subplot(2, 2, k); 
     hold on; 
     grid on 
     plot(approximationRank2(:, k), observations(:, k), 'x'); 
     plot([-4 4], [-4 4]); 
     xlim([-4 4]); 
     ylim([-4 4]); 
     title(sprintf('Variable %d', k)); 
    end 

enter image description here

obtenemos una reproducción casi perfecta del original observaciones. Si quisiéramos una aproximación gruesa, podríamos utilizar el primer componente principal:

>> approximationRank1 = score(:,1) * coeff(:,1)' + repmat(mu, 100, 1); 

y la trama que,

>> for k = 1:4 
     subplot(2, 2, k); 
     hold on; 
     grid on 
     plot(approximationRank1(:, k), observations(:, k), 'x'); 
     plot([-4 4], [-4 4]); 
     xlim([-4 4]); 
     ylim([-4 4]); 
     title(sprintf('Variable %d', k)); 
    end 

enter image description here

Esta vez, la reconstrucción no es tan buena. Eso es porque deliberadamente construimos nuestros datos para tener dos factores, y solo lo estamos reconstruyendo a partir de uno de ellos.

Tenga en cuenta que a pesar de la similitud entre la sugerente forma en que construimos los datos originales y su reproducción,

>> observations = factors * loadings' + 0.1 * randn(100,4); 
>> reconstructed = score * coeff'  + repmat(mu, 100, 1); 

no hay necesariamente ninguna correspondencia entre factors y score, o entre loadings y coeff. El algoritmo PCA no sabe nada sobre la forma en que se construyen sus datos; simplemente trata de explicar la mayor varianza posible con cada componente sucesivo.


El usuario @Mari preguntó en los comentarios cómo podría trazar el error de reconstrucción en función del número de componentes principales. Usar la variable explained arriba es bastante fácil. Voy a generar algunos datos con una estructura de factores más interesante para ilustrar el efecto -

>> factors = randn(100, 20); 
>> loadings = chol(corr(factors * triu(ones(20))))'; 
>> observations = factors * loadings' + 0.1 * randn(100, 20); 

Ahora todas las observaciones carga en un factor común significativa, con otros factores de importancia decreciente. Podemos obtener la descomposición PCA como antes

>> [coeff, score, latent, tsquared, explained, mu] = pca(observations); 

y trazar el porcentaje de varianza explicada de la siguiente manera,

>> cumexplained = cumsum(explained); 
    cumunexplained = 100 - cumexplained; 
    plot(1:20, cumunexplained, 'x-'); 
    grid on; 
    xlabel('Number of factors'); 
    ylabel('Unexplained variance') 

enter image description here

+0

muy gran respuesta, sólo quería darle las gracias. –

+0

Awesome answer. Gracias Chris! – rayryeng

+0

Genial para aprender. Muchas gracias. Sin embargo, tengo una pequeña duda, ¿por qué tenemos que crear variables ocultas al principio? ¿Puedo comenzar con '[w pc ev] = princomp (X);' para analizar mis datos originales? Gracias de nuevo. – Mari