html
Comprendiendo K-Nearest Neighbors (KNN) para Clasificación y Regresión
Tabla de Contenidos
- 1. Introducción a K-Nearest Neighbors
- 2. Cómo Funciona KNN
- 3. Elegir el Valor Correcto de 'K'
- 4. KNN para Clasificación
- 5. KNN para Regresión
- 6. Ventajas y Desventajas de KNN
- 7. Implementando KNN en Python
- 8. Ejemplo Práctico
- 9. Conclusión
- 10. Referencias
1. Introducción a K-Nearest Neighbors
K-Nearest Neighbors (KNN) es un algoritmo de aprendizaje automático supervisado simple, pero poderoso, utilizado tanto para tareas de clasificación como de regresión. La idea principal es predecir la etiqueta de un nuevo punto de datos basándose en las etiquetas de sus 'K' vecinos más cercanos en el espacio de características.
¿Por qué KNN?
- Simplicidad: Fácil de entender e implementar.
- Sin Fase de Entrenamiento: KNN es un aprendizaje perezoso, lo que significa que no entrena explícitamente un modelo sino que toma decisiones basándose en todo el conjunto de datos.
- Versatilidad: Aplicable a varios tipos de problemas, incluyendo clasificación, regresión e incluso detección de anomalías.
2. Cómo Funciona KNN
KNN opera bajo el principio de que puntos de datos similares probablemente tengan resultados similares. A continuación se presenta un desglose paso a paso de cómo funciona el algoritmo:
Representación de Datos
Imagina un espacio bidimensional donde cada punto de datos representa un automóvil basado en dos características:
- Tiempo de Fabricación (Eje X)
- Costo de Fabricación (Eje Y)
Los puntos de datos están codificados por colores:
- Puntos Rojos: Coches de gasolina
- Puntos Azules: Coches eléctricos
Métricas de Distancia
Para determinar la "cercanía" de los puntos de datos, KNN utiliza métricas de distancia. Las métricas más comúnmente usadas son:
- Distancia Euclidiana
\[
d(p, q) = \sqrt{\sum_{i=1}^{n} (q_i - p_i)^2}
\]
- Se Usa Cuando: Los datos están en un espacio continuo.
- Consejo Profesional: La distancia euclidiana es la métrica predeterminada en muchas implementaciones de KNN, incluyendo scikit-learn.
- Distancia Manhattan
\[
d(p, q) = \sum_{i=1}^{n} |q_i - p_i|
\]
- Se Usa Cuando: Los datos están en forma de cuadrícula y el movimiento está restringido a caminos horizontales y verticales.
- Distancia Minkowski
Una generalización de las distancias Euclidiana y Manhattan.
\[
d(p, q) = \left( \sum_{i=1}^{n} |q_i - p_i|^p \right)^{1/p}
\]
- Cuando \( p = 1 \): Equivalente a la distancia Manhattan.
- Cuando \( p = 2 \): Equivalente a la distancia Euclidiana.
3. Elegir el Valor Correcto de 'K'
El parámetro 'K' determina el número de vecinos a considerar al hacer una predicción. Seleccionar el valor óptimo de 'K' es crucial para el rendimiento del algoritmo KNN.
Impacto de 'K'
- 'K' Pequeño (p.ej., K=1):
- Mayor sensibilidad al ruido.
- Puede llevar a sobreajuste.
- 'K' Grande (p.ej., K=20):
- Frontera de decisión más suave.
- Puede llevar a subajuste al simplificar en exceso los datos.
Mejores Prácticas
- Validación Cruzada: Utiliza técnicas como la validación cruzada para encontrar el valor de 'K' que ofrezca la mejor precisión.
- Números Impares: Al tratar con clasificación binaria, usar valores impares de 'K' ayuda a evitar empates.
4. KNN para Clasificación
En clasificación, KNN asigna la clase más común entre sus 'K' vecinos más cercanos al nuevo punto de datos.
Escenario de Ejemplo
Considera un nuevo punto de datos de un automóvil con un tiempo y costo de fabricación específicos. El algoritmo KNN hará lo siguiente:
- Calcular la distancia desde este punto a todos los demás puntos en el conjunto de datos.
- Identificar los 'K' vecinos más cercanos.
- Asignar la clase (Eléctrico o Gasolina) basándose en la mayoría de votos entre estos vecinos.
Sensibilidad a 'K'
Como se demostró en la transcripción, variar 'K' puede cambiar el resultado de la clasificación. Por ejemplo:
- K=1: El nuevo punto se clasifica basándose en su único vecino más cercano.
- K=5: La mayoría de votos entre cinco vecinos determina la clasificación.
5. KNN para Regresión
Si bien KNN se usa predominantemente para clasificación, también puede realizar tareas de regresión prediciendo el valor promedio de los 'K' vecinos más cercanos.
Desafíos en Regresión
- Sobreajuste: Valores de 'K' más bajos pueden llevar a sobreajuste.
- Subajuste: Valores de 'K' más altos pueden simplificar en exceso el modelo.
Perspectivas de Implementación
En el Jupyter Notebook proporcionado, se aplicó regresión KNN para predecir precios de diamantes. Aquí hay una breve descripción:
- Preprocesamiento de Datos:
- Mapeó variables categóricas a valores numéricos.
- Escaló las características usando estandarización.
- Entrenamiento del Modelo:
- Entrenó el regresor KNN con valores variables de 'K' para determinar el rendimiento óptimo.
- Evaluación:
- Logró una puntuación de precisión máxima de aproximadamente 98.05% en K=4.
- Visualizó precios reales vs. predichos usando Plotly para una mejor interpretabilidad.
6. Ventajas y Desventajas de KNN
Ventajas
- Simple e Intuitivo: Fácil de entender e implementar.
- Sin Fase de Entrenamiento: Reduce el costo computacional durante el entrenamiento.
- Adaptable: Adecuado tanto para clasificación como para regresión.
Desventajas
- Intensivo Computacionalmente: Realiza predicciones usando todo el conjunto de datos, lo cual puede ser lento para conjuntos de datos grandes.
- Sensible a Características Irrelevantes: Características irrelevantes o redundantes pueden degradar el rendimiento.
- Elegir 'K': Seleccionar el valor óptimo de 'K' puede ser un desafío.
7. Implementando KNN en Python
Aprovechar la biblioteca scikit-learn de Python simplifica la implementación de KNN. A continuación, describimos los pasos clave desde el preprocesamiento de datos hasta la evaluación del modelo.
Preprocesamiento de Datos
Antes de aplicar KNN, es esencial preparar los datos:
- Manejo de Variables Categóricas:
- Convertir datos de texto categóricos en valores numéricos usando diccionarios de mapeo.
12345678
cut_dict = {'Fair': 1, 'Good': 2, 'Very Good': 3, 'Premium': 4, 'Ideal': 5}clarity_dict = {'I1': 1, 'SI2': 2, 'SI1': 3, 'VS2': 4, 'VS1': 5, 'VVS2': 6, 'VVS1': 7, 'IF': 8}color_dict = {'D':7, 'E':6, 'F':5, 'G':4, 'H':3, 'I':2, 'J':1} df['cut'] = df['cut'].map(cut_dict)df['clarity'] = df['clarity'].map(clarity_dict)df['color'] = df['color'].map(color_dict)df = df.drop('Unnamed: 0', axis=1)
- Escalado de Características:
- Normalizar el conjunto de características para asegurar que todas contribuyan por igual a los cálculos de distancia.
123456
from sklearn import preprocessing X = df.drop(['price'], axis=1).valuesX = preprocessing.scale(X)y = df['price'].valuesy = preprocessing.scale(y)
Entrenamiento y Evaluación del Modelo
- División del Conjunto de Datos:
12345678
from sklearn.utils import shuffle df = shuffle(df, random_state=42)test_size = 200X_train = X[:-test_size]y_train = y[:-test_size]X_test = X[-test_size:]y_test = y[-test_size:]
- Entrenamiento del Regresor KNN:
1234567
from sklearn.neighbors import KNeighborsRegressor score = []for k in range(1, 20): clf = KNeighborsRegressor(n_neighbors=k, weights='distance', p=1) clf.fit(X_train, y_train) score.append(clf.score(X_test, y_test))
- Visualización del Rendimiento:
12345678910111213141516
import plotly.graph_objs as gofrom plotly.offline import iplot trace0 = go.Scatter( y=score, x=np.arange(1, len(score)+1), mode='lines+markers', marker=dict(color='rgb(100, 200, 150)'))layout = go.Layout( title='K Value vs. Accuracy Score', xaxis=dict(title='K Value', tickmode='linear'), yaxis=dict(title='Score'))fig = go.Figure(data=[trace0], layout=layout)iplot(fig, filename='basic-line')
- Determinación del 'K' Óptimo:
12
k_max = score.index(max(score)) + 1print(f"At K = {k_max}, Max Accuracy = {max(score) * 100:.2f}%")
Salida:
1
At K = 4, Max Accuracy = 98.05%
- Evaluación Final del Modelo:
1234
clf = KNeighborsRegressor(n_neighbors=50)clf.fit(X_train, y_train)print(clf.score(X_test, y_test))y_pred = clf.predict(X_test)
Salida:
1
0.9543611406331687
- Comparación de Precios Reales vs. Predichos:
1234567891011121314151617181920212223242526
import plotly.graph_objs as gofrom plotly.offline import iplot trace0 = go.Scatter( y=y_test, x=np.arange(200), mode='lines+markers', name='Actual Price', marker=dict(color='rgb(110, 10, 150)')) trace1 = go.Scatter( y=y_pred, x=np.arange(200), mode='lines+markers', name='Predicted Price', line=dict(color='rgb(200, 50, 10)', dash='dot')) layout = go.Layout( xaxis=dict(title='Index'), yaxis=dict(title='Normalized Price')) figure = go.Figure(data=[trace0, trace1], layout=layout)iplot(figure)
Esta visualización ayuda a evaluar la precisión de la predicción del modelo superponiendo valores de precios reales y predichos.
8. Ejemplo Práctico
Recorremos una implementación práctica utilizando la biblioteca scikit-learn de Python, como se describe en el Jupyter Notebook proporcionado.
Paso 1: Importación de Bibliotecas Necesarias
12345678
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsfrom sklearn import preprocessing, utilsfrom sklearn.neighbors import KNeighborsRegressorimport plotly.graph_objs as gofrom plotly.offline import iplot
Paso 2: Cargando y Explorando el Conjunto de Datos
1234
df = pd.read_csv('diamonds.csv')print(df.head())sns.FacetGrid(df, hue='cut', height=6).map(sns.distplot, 'price').add_legend()plt.show()
Paso 3: Preprocesamiento de Datos
Convertir variables categóricas a numéricas y escalar las características.
12345678
cut_dict = {'Fair': 1, 'Good': 2, 'Very Good': 3, 'Premium': 4, 'Ideal': 5}clarity_dict = {'I1': 1, 'SI2': 2, 'SI1': 3, 'VS2': 4, 'VS1': 5, 'VVS2': 6, 'VVS1': 7, 'IF': 8}color_dict = {'D':7, 'E':6, 'F':5, 'G':4, 'H':3, 'I':2, 'J':1} df['cut'] = df['cut'].map(cut_dict)df['clarity'] = df['clarity'].map(clarity_dict)df['color'] = df['color'].map(color_dict)df = df.drop('Unnamed: 0', axis=1)
Paso 4: Escalado de Características y Mezcla de Datos
12345
df = utils.shuffle(df, random_state=42)X = df.drop(['price'], axis=1).valuesX = preprocessing.scale(X)y = df['price'].valuesy = preprocessing.scale(y)
Paso 5: División del Conjunto de Datos
12345
test_size = 200X_train = X[:-test_size]y_train = y[:-test_size]X_test = X[-test_size:]y_test = y[-test_size:]
Paso 6: Entrenamiento del Regresor KNN y Evaluación del Rendimiento
12345
score = []for k in range(1, 20): clf = KNeighborsRegressor(n_neighbors=k, weights='distance', p=1) clf.fit(X_train, y_train) score.append(clf.score(X_test, y_test))
Paso 7: Visualización de las Puntuaciones de Precisión
12345678910111213
trace0 = go.Scatter( y=score, x=np.arange(1, len(score)+1), mode='lines+markers', marker=dict(color='rgb(100, 200, 150)'))layout = go.Layout( title='K Value vs. Accuracy Score', xaxis=dict(title='K Value', tickmode='linear'), yaxis=dict(title='Score'))fig = go.Figure(data=[trace0], layout=layout)iplot(fig, filename='basic-line')
Paso 8: Determinando el Valor Óptimo de 'K'
12
k_max = score.index(max(score)) + 1print(f"At K = {k_max}, Max Accuracy = {max(score) * 100:.2f}%")
Paso 9: Entrenamiento Final del Modelo y Predicción
1234
clf = KNeighborsRegressor(n_neighbors=50)clf.fit(X_train, y_train)print(clf.score(X_test, y_test))y_pred = clf.predict(X_test)
Paso 10: Comparando Valores Reales vs. Predichos
1234567891011121314151617181920212223
trace0 = go.Scatter( y=y_test, x=np.arange(200), mode='lines+markers', name='Actual Price', marker=dict(color='rgb(110, 10, 150)')) trace1 = go.Scatter( y=y_pred, x=np.arange(200), mode='lines+markers', name='Predicted Price', line=dict(color='rgb(200, 50, 10)', dash='dot')) layout = go.Layout( xaxis=dict(title='Index'), yaxis=dict(title='Normalized Price')) figure = go.Figure(data=[trace0, trace1], layout=layout)iplot(figure)
Los gráficos generados proporcionan una representación visual de cuán bien el modelo KNN predice los precios de los diamantes basándose en el valor de 'K' seleccionado.
9. Conclusión
El algoritmo K-Nearest Neighbors es una herramienta de aprendizaje automático versátil y sencilla, adecuada para diversas aplicaciones en clasificación y regresión. Su efectividad depende en gran medida de la elección de 'K' y de la métrica de distancia utilizada. El preprocesamiento adecuado de los datos y el escalado de las características son pasos cruciales para mejorar el rendimiento del modelo. Aunque KNN es computacionalmente intensivo para conjuntos de datos grandes, su simplicidad lo convierte en un excelente punto de partida para los profesionales del aprendizaje automático.
10. Referencias
- Documentación de Scikit-learn: KNN
- Métricas de Distancia en KNN
- Manual de Ciencia de Datos con Python
Esperamos que esta guía te haya proporcionado una comprensión clara del algoritmo K-Nearest Neighbors. Mantente atento para más tutoriales detallados e información sobre técnicas de aprendizaje automático.