Importamos las librerias necesarias:
%matplotlib inline
# importamos las librerías básicas
import random
import numpy as np
import matplotlib.pyplot as plt
Creamos un conjunto de muestras con las que trabajar en el siguiente ejemplo. 5 muestras semi-alineadas para percibir bien la proyección de los datos en el nuevo espacio de dimensión reducida:
X = np.matrix([[-4., -5.],
[-3.5, -2.],
[1., 1.],
[1.5, 2.3],
[3., 3.2]])
Dibujamos el conjunto de muestras creado:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(X[:,0], X[:,1], "ro")
ax.axis([-4.2, 3.2, -5.2, 3.5])
ax.set_title("Muestras X")
ax.set_xlabel("x1")
ax.set_ylabel("x2")
plt.show()
Tratamos los datos, normalizamos y escalamos:
# normalizamos los datos
X -= np.mean(X, 0)
# escalamos las características
X /= np.std(X, 0)
# escalamos todos los datos a 1
X /= np.abs(X).max()
Dibujamos el nuevo conjunto de datos obtimizado:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(X[:,0], X[:,1], "co")
ax.axis([-1, 1, -1.5, 1])
ax.set_title("Muestras X escaladas")
ax.set_xlabel('x1')
ax.set_ylabel('x2')
plt.show()
Aplicamos el algoritmo PCA (Principal component analysis).
Calculamos e imprimimos la matriz de covarianza, autovectores y autovalores de los datos optimizados:
# matriz covarianza
C = np.cov(X.T)
print "Matriz de covarianza de X:"
print C
# descomposición en valores singulares
U, s, V = np.linalg.svd(C)
print "Autovalores:"
print s
print "Autovectores:"
print U
Matriz de covarianza de X: [[ 0.47355269 0.45525517] [ 0.45525517 0.47355269]] Autovalores: [ 0.92880785 0.01829752] Autovectores: [[-0.70710678 -0.70710678] [-0.70710678 0.70710678]]
Dibujamos los autovectores sobre los datos:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(X[:,0], X[:,1], "co")
ax.axis([-1, 1, -1.5, 1])
ax.quiver((0, 0), (0, 0), (U[0,0], U[1,0]), (U[0,1], U[1,1]), angles='xy', scale_units='xy', scale=1)
ax.set_title("Muestras X escaladas y autovectores")
ax.set_xlabel('x1')
ax.set_ylabel('x2')
plt.show()
Calculamos las nuevas 'k' dimensiones según la varianza que queramos mantener de los datos originales:
def dim_reduction(s, var):
for k in range(1,1000):
variance_retaines = sum(s[0:k]) / sum(s)
if variance_retaines >= var:
return k
k = dim_reduction(s, .98)
print "Reducción de dimensiones. De 2D a " + str(k) + "D"
Reducción de dimensiones. De 2D a 1D
Dibujamos la proyección de los datos en el nuevo espacio 1D:
U_reduced = U[:, :k]
Z = U_reduced.T.dot(X.T)
Z = -Z
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(Z, 0, "go")
ax.set_title("Datos en el nuevo espacio 1D")
ax.set_xlabel('z1')
plt.show()