resueltos principales paso mano funciona ejercicios ejemplo componentes como calcular analisis algoritmo python numpy machine-learning scikit-learn pca

python - principales - pca como funciona



AnĂ¡lisis de componentes principales(PCA) en Python (9)

Tengo una matriz (26424 x 144) y quiero realizar una PCA con Python. Sin embargo, no hay un lugar particular en la web que explique cómo lograr esta tarea (hay algunos sitios que solo hacen PCA de acuerdo con los suyos, no hay una forma generalizada de hacerlo que pueda encontrar). Cualquiera con algún tipo de ayuda lo hará genial.


Además de todas las otras respuestas, aquí hay un código para trazar el biplot usando sklearn y matplotlib .

import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.decomposition import PCA import pandas as pd from sklearn.preprocessing import StandardScaler iris = datasets.load_iris() X = iris.data y = iris.target #In general a good idea is to scale the data scaler = StandardScaler() scaler.fit(X) X=scaler.transform(X) pca = PCA() x_new = pca.fit_transform(X) def myplot(score,coeff,labels=None): xs = score[:,0] ys = score[:,1] n = coeff.shape[0] scalex = 1.0/(xs.max() - xs.min()) scaley = 1.0/(ys.max() - ys.min()) plt.scatter(xs * scalex,ys * scaley, c = y) for i in range(n): plt.arrow(0, 0, coeff[i,0], coeff[i,1],color = ''r'',alpha = 0.5) if labels is None: plt.text(coeff[i,0]* 1.15, coeff[i,1] * 1.15, "Var"+str(i+1), color = ''g'', ha = ''center'', va = ''center'') else: plt.text(coeff[i,0]* 1.15, coeff[i,1] * 1.15, labels[i], color = ''g'', ha = ''center'', va = ''center'') plt.xlim(-1,1) plt.ylim(-1,1) plt.xlabel("PC{}".format(1)) plt.ylabel("PC{}".format(2)) plt.grid() #Call the function. Use only the 2 PCs. myplot(x_new[:,0:2],np.transpose(pca.components_[0:2, :])) plt.show()


Aquí hay opciones de scikit-learn. Con ambos métodos, se utilizó StandardScaler porque PCA se efectúa por escala

Método 1: haga que scikit-learn elija la cantidad mínima de componentes principales, de modo que al menos x% (90% en el ejemplo a continuación) de la varianza se conserve.

from sklearn.datasets import load_iris from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler iris = load_iris() # mean-centers and auto-scales the data standardizedData = StandardScaler().fit_transform(iris.data) pca = PCA(.90) principalComponents = pca.fit_transform(X = standardizedData) # To get how many principal components was chosen print(pca.n_components_)

Método 2: elija la cantidad de componentes principales (en este caso, se eligió 2)

from sklearn.datasets import load_iris from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler iris = load_iris() standardizedData = StandardScaler().fit_transform(iris.data) pca = PCA(n_components=2) principalComponents = pca.fit_transform(X = standardizedData) # to get how much variance was retained print(pca.explained_variance_ratio_.sum())

Fuente: https://towardsdatascience.com/pca-using-python-scikit-learn-e653f8989e60


Este es un trabajo para numpy .

Y aquí hay un tutorial que demuestra cómo el análisis de componentes principales se puede hacer usando los numpy incorporados de numpy como mean,cov,double,cumsum,dot,linalg,array,rank .

http://glowingpython.blogspot.sg/2011/07/principal-component-analysis-with-numpy.html

Observe que scipy también tiene una explicación larga aquí - https://github.com/scikit-learn/scikit-learn/blob/babe4a5d0637ca172d47e1dfdd2f6f3c3ecb28db/scikits/learn/utils/extmath.py#L105

con la biblioteca scikit-learn con más ejemplos de código - https://github.com/scikit-learn/scikit-learn/blob/babe4a5d0637ca172d47e1dfdd2f6f3c3ecb28db/scikits/learn/utils/extmath.py#L105


He hecho un pequeño guión para comparar las diferentes PCA que aparecieron como respuesta aquí:

import numpy as np from scipy.linalg import svd shape = (26424, 144) repeat = 20 pca_components = 2 data = np.array(np.random.randint(255, size=shape)).astype(''float64'') # data normalization # data.dot(data.T) # (U, s, Va) = svd(data, full_matrices=False) # data = data / s[0] from fbpca import diffsnorm from timeit import default_timer as timer from scipy.linalg import svd start = timer() for i in range(repeat): (U, s, Va) = svd(data, full_matrices=False) time = timer() - start err = diffsnorm(data, U, s, Va) print(''svd time: %.3fms, accuracy: %E'' % (time*1000/repeat, err)) from matplotlib.mlab import PCA start = timer() _pca = PCA(data) for i in range(repeat): U = _pca.project(data) time = timer() - start err = diffsnorm(data, U, _pca.fracs, _pca.Wt) print(''matplotlib PCA time: %.3fms, accuracy: %E'' % (time*1000/repeat, err)) from fbpca import pca start = timer() for i in range(repeat): (U, s, Va) = pca(data, pca_components, True) time = timer() - start err = diffsnorm(data, U, s, Va) print(''facebook pca time: %.3fms, accuracy: %E'' % (time*1000/repeat, err)) from sklearn.decomposition import PCA start = timer() _pca = PCA(n_components = pca_components) _pca.fit(data) for i in range(repeat): U = _pca.transform(data) time = timer() - start err = diffsnorm(data, U, _pca.explained_variance_, _pca.components_) print(''sklearn PCA time: %.3fms, accuracy: %E'' % (time*1000/repeat, err)) start = timer() for i in range(repeat): (U, s, Va) = pca_mark(data, pca_components) time = timer() - start err = diffsnorm(data, U, s, Va.T) print(''pca by Mark time: %.3fms, accuracy: %E'' % (time*1000/repeat, err)) start = timer() for i in range(repeat): (U, s, Va) = pca_doug(data, pca_components) time = timer() - start err = diffsnorm(data, U, s[:pca_components], Va.T) print(''pca by doug time: %.3fms, accuracy: %E'' % (time*1000/repeat, err))

pca_mark es el pca en la respuesta de Marcos .

pca_doug es la respuesta de pca en doug .

Aquí hay un ejemplo de salida (pero el resultado depende en gran medida del tamaño de los datos y de los componentes pca, por lo que recomendaría ejecutar su propia prueba con sus propios datos. Además, el pca de Facebook está optimizado para datos normalizados, por lo que será más rápido y más preciso en ese caso):

svd time: 3212.228ms, accuracy: 1.907320E-10 matplotlib PCA time: 879.210ms, accuracy: 2.478853E+05 facebook pca time: 485.483ms, accuracy: 1.260335E+04 sklearn PCA time: 169.832ms, accuracy: 7.469847E+07 pca by Mark time: 293.758ms, accuracy: 1.713129E+02 pca by doug time: 300.326ms, accuracy: 1.707492E+02


Otra PCA Python usando numpy. La misma idea que @doug pero esa no se ejecutó.

from numpy import array, dot, mean, std, empty, argsort from numpy.linalg import eigh, solve from numpy.random import randn from matplotlib.pyplot import subplots, show def cov(data): """ Covariance matrix note: specifically for mean-centered data note: numpy''s `cov` uses N-1 as normalization """ return dot(X.T, X) / X.shape[0] # N = data.shape[1] # C = empty((N, N)) # for j in range(N): # C[j, j] = mean(data[:, j] * data[:, j]) # for k in range(j + 1, N): # C[j, k] = C[k, j] = mean(data[:, j] * data[:, k]) # return C def pca(data, pc_count = None): """ Principal component analysis using eigenvalues note: this mean-centers and auto-scales the data (in-place) """ data -= mean(data, 0) data /= std(data, 0) C = cov(data) E, V = eigh(C) key = argsort(E)[::-1][:pc_count] E, V = E[key], V[:, key] U = dot(data, V) # used to be dot(V.T, data.T).T return U, E, V """ test data """ data = array([randn(8) for k in range(150)]) data[:50, 2:4] += 5 data[50:, 2:5] += 5 """ visualize """ trans = pca(data, 3)[0] fig, (ax1, ax2) = subplots(1, 2) ax1.scatter(data[:50, 0], data[:50, 1], c = ''r'') ax1.scatter(data[50:, 0], data[50:, 1], c = ''b'') ax2.scatter(trans[:50, 0], trans[:50, 1], c = ''r'') ax2.scatter(trans[50:, 0], trans[50:, 1], c = ''b'') show()

Lo cual produce lo mismo que el mucho más corto

from sklearn.decomposition import PCA def pca2(data, pc_count = None): return PCA(n_components = 4).fit_transform(data)

Tal como lo entiendo, usar valores propios (primera vía) es mejor para datos de alta dimensión y menos muestras, mientras que el uso de la descomposición de valores singulares es mejor si tiene más muestras que dimensiones.


Por el bien def plot_pca(data): funcionará, es necesario reemplazar las líneas

data_resc, data_orig = PCA(data) ax1.plot(data_resc[:, 0], data_resc[:, 1], ''.'', mfc=clr1, mec=clr1)

con líneas

newData, data_resc, data_orig = PCA(data) ax1.plot(newData[:, 0], newData[:, 1], ''.'', mfc=clr1, mec=clr1)


Publiqué mi respuesta a pesar de que ya se ha aceptado otra respuesta; la respuesta aceptada se basa en una matplotlib.org/api/… ; adicionalmente, esta función en desuso se basa en la Descomposición de Valor Singular (SVD), que (aunque es perfectamente válida) es mucho más intensiva en memoria y procesador de las dos técnicas generales para calcular PCA. Esto es particularmente relevante aquí debido al tamaño de la matriz de datos en el PO. Usando una PCA basada en covarianza, la matriz utilizada en el flujo de cálculo es solo 144 x 144 , en lugar de 26424 x 144 (las dimensiones de la matriz de datos original).

Aquí hay una implementación simple de trabajo de PCA usando el módulo linalg de SciPy . Debido a que esta implementación primero calcula la matriz de covarianza y luego realiza todos los cálculos posteriores en esta matriz, usa mucha menos memoria que la PCA basada en SVD.

(El módulo linalg en NumPy también se puede usar sin cambios en el código a continuación, aparte de la declaración de importación, que sería desde numpy import linalg como LA ).

Los dos pasos clave en esta implementación de PCA son:

  • calcular la matriz de covarianza ; y

  • tomando los eivenvectors y valores propios de esta matriz de cov

En la función siguiente, el parámetro dims_rescaled_data se refiere a la cantidad deseada de dimensiones en la matriz de datos redimensionados ; este parámetro tiene un valor predeterminado de solo dos dimensiones, pero el código siguiente no está limitado a dos, pero podría ser cualquier valor menor que el número de columna de la matriz de datos original.

def PCA(data, dims_rescaled_data=2): """ returns: data transformed in 2 dims/columns + regenerated original data pass in: data as 2D NumPy array """ import numpy as NP from scipy import linalg as LA m, n = data.shape # mean center the data data -= data.mean(axis=0) # calculate the covariance matrix R = NP.cov(data, rowvar=False) # calculate eigenvectors & eigenvalues of the covariance matrix # use ''eigh'' rather than ''eig'' since R is symmetric, # the performance gain is substantial evals, evecs = LA.eigh(R) # sort eigenvalue in decreasing order idx = NP.argsort(evals)[::-1] evecs = evecs[:,idx] # sort eigenvectors according to same index evals = evals[idx] # select the first n eigenvectors (n is desired dimension # of rescaled data array, or dims_rescaled_data) evecs = evecs[:, :dims_rescaled_data] # carry out the transformation on the data using eigenvectors # and return the re-scaled data, eigenvalues, and eigenvectors return NP.dot(evecs.T, data.T).T, evals, evecs def test_PCA(data, dims_rescaled_data=2): '''''' test by attempting to recover original data array from the eigenvectors of its covariance matrix & comparing that ''recovered'' array with the original data '''''' _ , _ , eigenvectors = PCA(data, dim_rescaled_data=2) data_recovered = NP.dot(eigenvectors, m).T data_recovered += data_recovered.mean(axis=0) assert NP.allclose(data, data_recovered) def plot_pca(data): from matplotlib import pyplot as MPL clr1 = ''#2026B2'' fig = MPL.figure() ax1 = fig.add_subplot(111) data_resc, data_orig = PCA(data) ax1.plot(data_resc[:, 0], data_resc[:, 1], ''.'', mfc=clr1, mec=clr1) MPL.show() >>> # iris, probably the most widely used reference data set in ML >>> df = "~/iris.csv" >>> data = NP.loadtxt(df, delimiter='','') >>> # remove class labels >>> data = data[:,:-1] >>> plot_pca(data)

El siguiente diagrama es una representación visual de esta función PCA en los datos del iris. Como puede ver, una transformación en 2D separa limpiamente la clase I de la clase II y la clase III (pero no la clase II de la clase III, que de hecho requiere otra dimensión).


Puede encontrar una función PCA en el módulo matplotlib:

import numpy as np from matplotlib.mlab import PCA data = np.array(np.random.randint(10,size=(10,3))) results = PCA(data)

los resultados almacenarán los diversos parámetros de la PCA. Es de la parte mlab de matplotlib, que es la capa de compatibilidad con la sintaxis de MATLAB

EDIT: en el blog nextgenetics , encontré una maravillosa demostración de cómo realizar y mostrar una PCA con el módulo matplotlib mlab, ¡diviértanse y revisen ese blog!


ACTUALIZACIÓN: matplotlib.mlab.PCA desde la versión 2.2 (2018-03-06) de hecho en deprecated .

La biblioteca matplotlib.mlab.PCA (utilizada en esta respuesta ) no está en desuso. Entonces, para toda la gente que llega aquí a través de Google, publicaré un ejemplo de trabajo completo probado con Python 2.7.

Utilice el siguiente código con cuidado ya que utiliza una biblioteca ahora en desuso.

from matplotlib.mlab import PCA import numpy data = numpy.array( [[3,2,5], [-2,1,6], [-1,0,4], [4,3,4], [10,-5,-6]] ) pca = PCA(data)

Ahora en `pca.Y ''está la matriz de datos original en términos de los principales vectores de base de componentes. Más detalles sobre el objeto PCA se pueden encontrar here .

>>> pca.Y array([[ 0.67629162, -0.49384752, 0.14489202], [ 1.26314784, 0.60164795, 0.02858026], [ 0.64937611, 0.69057287, -0.06833576], [ 0.60697227, -0.90088738, -0.11194732], [-3.19578784, 0.10251408, 0.00681079]])

Puede usar matplotlib.pyplot para dibujar estos datos, solo para convencerse de que PCA produce "buenos" resultados. La lista de names solo se usa para anotar nuestros cinco vectores.

import matplotlib.pyplot names = [ "A", "B", "C", "D", "E" ] matplotlib.pyplot.scatter(pca.Y[:,0], pca.Y[:,1]) for label, x, y in zip(names, pca.Y[:,0], pca.Y[:,1]): matplotlib.pyplot.annotate( label, xy=(x, y), xytext=(-2, 2), textcoords=''offset points'', ha=''right'', va=''bottom'' ) matplotlib.pyplot.show()

Al mirar nuestros vectores originales, veremos que los datos [0] ("A") y los datos [3] ("D") son bastante similares, como lo son los datos [1] ("B") y los datos [2] (" DO"). Esto se refleja en el gráfico 2D de nuestros datos transformados PCA.