🔍 ¿Qué es KNN?
El algoritmo K-Vecinos Más Cercanos (KNN) es un método sencillo y muy útil para la clasificación y la regresión. Su principio fundamental se basa en la idea de que «dime con quién andas y te diré cómo eres«, lo que significa que para predecir una clase o un valor, se consideran las observaciones más cercanas en el conjunto de datos de entrenamiento.
Con este algoritmo podríamos resolver un problema de clasificación de tumores, para predecir si un tumor es benigno o maligno. Asimismo, también podríamos predecir el precio de una casa, lo que corresponde a un problema de regresión.
🚀¿Cómo funciona este algoritmo?
Cuando tenemos un dato que queremos predecir:
- El algoritmo busca observaciones similares al nuevo dato dentro del dataset de entrenamiento.
Utiliza estas observaciones cercanas para realizar la predicción.
Por ejemplo, en un caso de predicción de churn (abandono de clientes):
- Imaginemos que tenemos una empresa y queremos predecir si un cliente dejará o no la compañía.
- Contamos con datos como: tiempo que lleva en la empresa, número de reclamaciones y si sigue o no en la empresa.
- Si entra un nuevo cliente, podríamos predecir su comportamiento en función de los 3 vecinos más cercanos, por ejemplo.
- Si la mayoría de estos vecinos siguen en la empresa, la predicción será que el nuevo cliente también continuará.
🧮¿Cómo encontramos a nuestros vecinos más cercanos?
Básicamente, se trata de hacer comparaciones con respecto a los puntos o vecinos más cercanos y realizar una predicción. Sin embargo, ¿cómo lo hacemos?
El concepto de vecinos más cercanos está directamente relacionado con el cálculo de la distancia entre puntos. Existen diferentes métricas para esto, algunas de ellas son:
Distancia Euclídea:
Es la distancia en línea recta más corta entre dos puntos.
Es la más utilizada.
Distancia Manhattan:
Se calcula sumando los dos catetos de un triángulo rectángulo.
Tiene sentido cuando se mide en entornos como una ciudad, donde los desplazamientos son en líneas rectas y perpendiculares (como las calles de Manhattan).
- Distancia del Coseno:
Se basa en el ángulo entre dos vectores, de forma que, si dos observaciones apuntan en la misma dirección, la distancia será pequeña.
Es útil cuando hay muchas variables, ya que en estos casos la distancia euclídea puede perder efectividad.
💻 ¿Qué proceso debemos seguir para implementarlo?
Ahora que sabemos qué es el algoritmo KNN y cómo funciona, vamos a ver cuál es el proceso que debemos seguir para implementarlo.
Programar las métricas de distancia que queramos utilizar (Euclídea, Manhattan, Coseno, etc.).
Calcular la distancia entre el nuevo dato y todos los puntos del dataset de entrenamiento.
Ordenar las distancias de menor a mayor.
Seleccionar los k vecinos más cercanos (en el ejemplo del churn, hemos escogido un k=3, de forma que comparamos nuestro input con 3 datos del dataset).
Realizar la predicción:
En un problema de clasificación, la predicción vendrá determinada según la clase mayoritaria de los vecinos. Por ejemplo, si la mayoría de los vecinos de nuestro input señalan que el cliente se irá de la compañía, el algoritmo clasificará a nuestro cliente objetivo como un posible caso de churn.
En un problema de regresión, la predicción vendrá determinada según el promedio de los valores de los vecinos. Por ejemplo, si queremos predecir el precio de una casa en concreto, este corresponderá a la media calculada con respecto a los precios de las casas más cercanas a nuestra casa objetivo.
⚡El principal desafío de KNN en datasets grandes es el coste computacional, ya que, como hemos visto, para cada nueva predicción, el algoritmo debe calcular la distancia con todos los puntos del dataset, lo cual puede ser lento. Por ello, en datasets grandes, podemos mejorar la eficiencia del algoritmo con técnicas de optimización como KD-Trees, Ball-Trees, o algoritmos de búsqueda aproximada para mejorar la eficiencia.
Estos métodos permiten que KNN siga siendo efectivo incluso en entornos con grandes volúmenes de datos.
📌Implementación de KNN paso a paso con Python
Para entender mejor el algoritmo K-Vecinos Más Cercanos (KNN), veamos cómo implementarlo desde cero en Python utilizando la librería scikit-learn. Seguiremos un enfoque práctico con el dataset de Iris, que es ampliamente usado en problemas de clasificación.
1️⃣ Cargar el dataset y dividirlo en entrenamiento y prueba
Primero, cargamos el dataset Iris y seleccionamos solo dos características para visualizar mejor cómo funciona el modelo. A continuación, dividimos nuestro dataset para el entrenamiento y el test.
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# Cargar el dataset Iris
iris = load_iris(as_frame=True) # Carga el dataset en formato Pandas DataFrame
# Seleccionar dos características para una mejor visualización
X = iris.data[[«sepal length (cm)», «sepal width (cm)»]]
y = iris.target # Variable objetivo (clase de la flor)
# Dividir en datos de entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)
📌 Nota: la opción stratify=y asegura que la proporción de clases en el conjunto de prueba sea similar a la del conjunto original.
2️⃣ Normalizar los datos y definir el modelo KNN
El algoritmo KNN usa distancias para encontrar los vecinos más cercanos. Si las variables tienen diferentes escalas, una puede influir más que la otra. Por eso, normalizamos los datos con StandardScaler.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
# Crear un pipeline que normaliza los datos y luego aplica KNN con 11 vecinos
clf = Pipeline([
(«scaler», StandardScaler()),
(«knn», KNeighborsClassifier(n_neighbors=11))
])
📌 Tip: elegimos k=11 para evitar sobreajuste. Siempre es recomendable que k sea impar para evitar empates en la clasificación.
3️⃣ Entrenar el modelo y visualizar la frontera de decisión
Ahora entrenamos el modelo y visualizamos cómo se comporta en distintas configuraciones de pesos.
import matplotlib.pyplot as plt
from sklearn.inspection import DecisionBoundaryDisplay
_, axs = plt.subplots(ncols=2, figsize=(12, 5))
for ax, weights in zip(axs, («uniform», «distance»)):
clf.set_params(knn__weights=weights).fit(X_train, y_train) # Ajustar modelo con distintos pesos
disp = DecisionBoundaryDisplay.from_estimator(
clf,
X_test,
response_method=»predict»,
plot_method=»pcolormesh»,
xlabel=iris.feature_names[0],
ylabel=iris.feature_names[1],
shading=»auto»,
alpha=0.5,
ax=ax,
)
scatter = disp.ax_.scatter(X.iloc[:, 0], X.iloc[:, 1], c=y, edgecolors=»k»)
disp.ax_.legend(
scatter.legend_elements()[0],
iris.target_names,
loc=»lower left»,
title=»Clases»,
)
ax.set_title(f»Clasificación con KNN\n(k={clf[-1].n_neighbors}, weights={weights})»)
plt.show()
🎨 ¿Qué estamos haciendo?
Mostramos dos gráficos comparando weights=»uniform» (todos los vecinos pesan igual) vs. weights=»distance» (los más cercanos tienen mayor peso).
La frontera de decisión muestra cómo el modelo divide las clases.
4️⃣ Introducir un nuevo dato y hacer una predicción
Ahora, supongamos que queremos clasificar una nueva observación con medidas específicas.
# Definir un nuevo dato para clasificar
nuevo_dato = [[5.0, 3.5]] # Longitud y ancho del sépalo
# Normalizar y predecir la clase del nuevo dato
prediccion = clf.predict(nuevo_dato)
print(f»La clase predicha para el nuevo dato es: {iris.target_names[prediccion[0]]}»)
📌Tip: este mismo proceso puede aplicarse a cualquier dataset. Solo necesitamos normalizar los datos y aplicar el modelo entrenado.
Conclusión
Hemos implementado el algoritmo KNN paso a paso, desde la carga de datos hasta la predicción de un nuevo caso. Este método es fácil de entender y útil para problemas de clasificación y regresión. Sin embargo, en grandes volúmenes de datos, es recomendable optimizarlo con estructuras como KD-Trees o Ball-Trees.