Introducción
En este laboratorio, aprenderemos sobre Análisis Discriminante Lineal y Cuadrático (LDA y QDA). El LDA y el QDA son algoritmos de clasificación que se utilizan para encontrar un límite de decisión lineal y cuadrático, respectivamente, entre dos o más clases. Utilizaremos la biblioteca scikit-learn para implementar estos algoritmos y visualizar los límites de decisión.
Consejos sobre la VM
Una vez que se haya iniciado la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.
A veces, es posible que tenga que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de las operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.
Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje sus comentarios después de la sesión y lo resolveremos rápidamente para usted.
Importar bibliotecas y generar conjuntos de datos
Primero, importaremos las bibliotecas necesarias y generaremos dos conjuntos de datos: uno con una covarianza fija y otro con covarianzas variables.
import numpy as np
import matplotlib.pyplot as plt
from scipy import linalg
from matplotlib import colors
import matplotlib as mpl
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis
## generar conjunto de datos con covarianza fija
def dataset_fixed_cov():
n, dim = 300, 2
np.random.seed(0)
C = np.array([[0.0, -0.23], [0.83, 0.23]])
X = np.r_[np.dot(np.random.randn(n, dim), C), np.dot(np.random.randn(n, dim), C) + np.array([1, 1])]
y = np.hstack((np.zeros(n), np.ones(n)))
return X, y
## generar conjunto de datos con covarianzas variables
def dataset_cov():
n, dim = 300, 2
np.random.seed(0)
C = np.array([[0.0, -1.0], [2.5, 0.7]]) * 2.0
X = np.r_[np.dot(np.random.randn(n, dim), C), np.dot(np.random.randn(n, dim), C.T) + np.array([1, 4])]
y = np.hstack((np.zeros(n), np.ones(n)))
return X, y
Crear mapa de colores
Crearemos un mapa de colores personalizado para utilizar en nuestras visualizaciones.
cmap = colors.LinearSegmentedColormap(
"red_blue_classes",
{
"red": [(0, 1, 1), (1, 0.7, 0.7)],
"green": [(0, 0.7, 0.7), (1, 0.7, 0.7)],
"blue": [(0, 0.7, 0.7), (1, 1, 1)],
},
)
plt.cm.register_cmap(cmap=cmap)
Funciones de trazado
Definiremos dos funciones para trazar los datos y las elipses.
def plot_data(lda, X, y, y_pred, fig_index):
splot = plt.subplot(2, 2, fig_index)
if fig_index == 1:
plt.title("Análisis Discriminante Lineal")
plt.ylabel("Datos con\n covarianza fija")
elif fig_index == 2:
plt.title("Análisis Discriminante Cuadrático")
elif fig_index == 3:
plt.ylabel("Datos con\n covarianzas variables")
tp = y == y_pred ## Verdadero Positivo
tp0, tp1 = tp[y == 0], tp[y == 1]
X0, X1 = X[y == 0], X[y == 1]
X0_tp, X0_fp = X0[tp0], X0[~tp0]
X1_tp, X1_fp = X1[tp1], X1[~tp1]
## clase 0: puntos
plt.scatter(X0_tp[:, 0], X0_tp[:, 1], marker=".", color="red")
plt.scatter(X0_fp[:, 0], X0_fp[:, 1], marker="x", s=20, color="#990000") ## rojo oscuro
## clase 1: puntos
plt.scatter(X1_tp[:, 0], X1_tp[:, 1], marker=".", color="blue")
plt.scatter(X1_fp[:, 0], X1_fp[:, 1], marker="x", s=20, color="#000099") ## azul oscuro
## clase 0 y 1 : áreas
nx, ny = 200, 100
x_min, x_max = plt.xlim()
y_min, y_max = plt.ylim()
xx, yy = np.meshgrid(np.linspace(x_min, x_max, nx), np.linspace(y_min, y_max, ny))
Z = lda.predict_proba(np.c_[xx.ravel(), yy.ravel()])
Z = Z[:, 1].reshape(xx.shape)
plt.pcolormesh(xx, yy, Z, cmap="red_blue_classes", norm=colors.Normalize(0.0, 1.0), zorder=0)
plt.contour(xx, yy, Z, [0.5], linewidths=2.0, colors="white")
## medias
plt.plot(lda.means_[0][0], lda.means_[0][1], "*", color="yellow", markersize=15, markeredgecolor="grey")
plt.plot(lda.means_[1][0], lda.means_[1][1], "*", color="yellow", markersize=15, markeredgecolor="grey")
return splot
def plot_ellipse(splot, mean, cov, color):
v, w = linalg.eigh(cov)
u = w[0] / linalg.norm(w[0])
angle = np.arctan(u[1] / u[0])
angle = 180 * angle / np.pi ## convertir a grados
## Gaussiana rellena a 2 desviaciones estándar
ell = mpl.patches.Ellipse(mean, 2 * v[0] ** 0.5, 2 * v[1] ** 0.5, angle=180 + angle, facecolor=color, edgecolor="black", linewidth=2)
ell.set_clip_box(splot.bbox)
ell.set_alpha(0.2)
splot.add_artist(ell)
splot.set_xticks(())
splot.set_yticks(())
Trazar elipses de covarianza del LDA
Traza los elipsoides de covarianza para el LDA.
def plot_lda_cov(lda, splot):
plot_ellipse(splot, lda.means_[0], lda.covariance_, "red")
plot_ellipse(splot, lda.means_[1], lda.covariance_, "blue")
Trazar elipses de covarianza del QDA
Traza los elipsoides de covarianza para el QDA.
def plot_qda_cov(qda, splot):
plot_ellipse(splot, qda.means_[0], qda.covariance_[0], "red")
plot_ellipse(splot, qda.means_[1], qda.covariance_[1], "blue")
Visualizar los límites de decisión
Utilizaremos los conjuntos de datos generados en el Paso 1 para visualizar los límites de decisión para el LDA y el QDA.
plt.figure(figsize=(10, 8), facecolor="white")
plt.suptitle("Análisis Discriminante Lineal vs Análisis Discriminante Cuadrático", y=0.98, fontsize=15)
for i, (X, y) in enumerate([dataset_fixed_cov(), dataset_cov()]):
## Análisis Discriminante Lineal
lda = LinearDiscriminantAnalysis(solver="svd", store_covariance=True)
y_pred = lda.fit(X, y).predict(X)
splot = plot_data(lda, X, y, y_pred, fig_index=2 * i + 1)
plot_lda_cov(lda, splot)
plt.axis("tight")
## Análisis Discriminante Cuadrático
qda = QuadraticDiscriminantAnalysis(store_covariance=True)
y_pred = qda.fit(X, y).predict(X)
splot = plot_data(qda, X, y, y_pred, fig_index=2 * i + 2)
plot_qda_cov(qda, splot)
plt.axis("tight")
plt.tight_layout()
plt.subplots_adjust(top=0.92)
plt.show()
Resumen
En este laboratorio, aprendimos sobre el Análisis Discriminante Lineal y Cuadrático (LDA y QDA). Generamos dos conjuntos de datos y utilizamos el LDA y el QDA para encontrar los límites de decisión lineales y cuadráticos, respectivamente. Visualizamos los límites de decisión y los elipsoides de covarianza para cada algoritmo.