Algoritmo KNN – cómo funciona y ejemplos en Python

El algoritmo KNN (K Nearest Neighbors) es un método de Machine Learning muy conocido, debido su simplicidad, ya que es muy fácil de entender y utilizar. Si te estas iniciando en el mundillo, es muy probable que hayas oído hablar de este algoritmo. KNN pertenece al conjunto de algoritmos de Aprendizaje Supervisado, si te preguntas cómo funciona y cómo puedes utilizarlo en Python, en este post te explicaremos todo lo que necesitas saber.

¿ Cómo funciona el modelo KNN ?

El algoritmo K-NN (K Nearest Neighbors) o en español, K Vecinos Más Cercanos, trata de buscar los K puntos más cercanos a un punto concreto para poder inferir su valor. Este algoritmo pertenece al conjunto de técnicas del aprendizaje automático supervisado, y puede ser utilizado tanto para problemas de clasificación, como de regresión.

Esto lo veremos mejor con un ejemplo. Imaginemos que tenemos la altura y el peso de cinco personas, junto con su respectivo género (Hombre o mujer).

Ejemplo de puntos en un eje cartesiano

Si nos dieran datos de una sexta persona, pero no nos dieran su género, ¿Podríamos adivinarlo de alguna forma? Aquí es donde entra la fuerza del algoritmo KNN. Como tenemos 5 personas, de las que sí conocemos su género, cogeremos K igual a 3, para coger los 3 puntos (o vecinos) más cercanos a nuestro nuevo punto negro. ¿Por qué cogemos 3? Simplemente porque vamos a coger las categorías de los 3 elementos más cercanos y cogeremos la mayoría de estas categorías.

Ejemplo de algoritmo KNN en un eje cartesiano

Se puede observar que los dos puntos más cercanos son hombres, son de color rojo, y que el tercer punto más cercano es una mujer, punto azul, por lo que si hacemos un voto por mayoría, tenemos 2 hombres y 1 mujer, por lo que diremos que el voto más frecuente es hombre, así que clasificaremos nuestro nuevo punto como hombre. ¡Y ya está!, ya hemos utilizado el algoritmo KNN para predecir la clase de un punto cuya categoría desconocíamos.

Esto ha sido un ejemplo de KNN para problemas de clasificación, pero también podríamos haberlo utilizado para un problema de regresión. La diferencia sería que en vez de calcular la mayoría de la clase que conocemos, calcularíamos la media de los valores que queremos predecir.

Funcionamiento paso a paso del algoritmo k-NN

  1. Calcular la distancia de todos los elementos con nuestro punto

    Tenemos que haber definido la función que vamos a utilizar para calcular la distancia. Lo más normal si trabajas con valores numéricos es utilizar la distancia euclídea.

  2. Ordenar las distancias de menor a mayor

    Coloca todas las distancias de nuestro punto con el resto y ordénalos de menor a mayor, se hace así para saber cuáles son los más cercanos y los más alejados.

  3. Seleccionar los K elementos más cercanos

    Una vez se ha definido el valor de K, nos quedamos con esta cantidad de valores, con la menor distancia. Que representa los valores más parecidos a nuestro punto.

  4. Obtenemos la predicción del algoritmo

    En el caso de ser un problema de regresión, obtenemos la media de los K valores más cercanos, mientras que si fuera de clasificación, nos quedaríamos con la categoría más votada.

Lazy Learning

El algoritmo KNN se encuentra bajo la categoría de métodos denominados Lazy Learning (Aprendizaje Vago). Se llaman así, ya que este tipo de algoritmos no entrena un modelo, es decir, no se optimizan unos pesos, sino que simplemente compara como de parecidos son los puntos que conocemos, con los puntos nuevos, para obtener así una predicción.

Distancia

Hemos puesto un ejemplo sencillo de uso del algoritmo KNN, pero ¿qué pasaría si tuviéramos más de dos variables? Si tenemos más de dos variables, sería imposible decir a ojo qué puntos están más cerca de otros. Necesitaríamos para esto un método para poder calcular la distancia entre los puntos.

Distancia Euclídea o distancia euclidiana

La distancia euclídea o distancia euclidiana es una de las distancias más básicas, pero a la vez, de las más utilizadas en el mundo del Machine Learning. Esta distancia está pensada solo para variables numéricas. Si quisiéramos utilizar una variable categórica, tendríamos que utilizar alguna técnica de encoding, u otra distancia que sí permita este tipo de variables.

d_{E}(P_{1}, P_{2})=\sqrt{(x_{2} - x_{1})^2 + (y_{2} - y_{1})^2}

Calculando la distancia euclidiana en Python

Si necesitas calcular esta distancia euclídea en el lenguaje Python, aquí te dejo un ejemplo utilizando la librería numpy.

import numpy as np
punto_1 = np.array([2, 4, 6])
punto_2 = np.array([3, 5, 7])
# Calculando la distancia euclidea
distancia_euclidea = np.linalg.norm(point1 - point2)

Escalar variables

¿Tiene sentido calcular la distancia de variables que tengan rangos muy diferentes? La respuesta es que no, ya que si tuviéramos dos variables, una con un rango en 0 y 1, y otra con valores entre 0 y 1000, la segunda variable influiría mucho más que la primera en el cálculo de la distancia. Para solucionar este tipo de problemas, entra en juego la normalización de variables.

Normalizar variables consiste simplemente en hacer que los rangos de valores que pueden tomar una serie de variables sea similar, para que como hemos dicho antes, no haya una que influya mucho más que otra.

Utilizando KNN en PythonEjemplo

Ahora veremos un ejemplo de cómo utilizar el modelo KNN en Python para un problema de clasificación mediante la librería Scikit-learn.

Usando el Clasificador KNN

Primero cargamos todas las librerías necesarias. Entre ellas cargamos la clase KNeighborsClassifier, para poder utilizar el algoritmo KNN para problemas de clasificación.

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from sklearn.neighbors import KNeighborsClassifier

Primero crearemos unos datos de prueba, de los que sabemos la categoría y creamos un punto nuevo, del que no sabemos su género y visualizamos todos los puntos.

data = {'Masa': [50, 80, 90, 45, 60],
        'Altura': [1.48, 1.82, 1.85, 1.55, 1.60],
        'Genero': ['m', 'h', 'h', 'm', 'm']}
punto_nuevo = {'Masa': [70],
               'Altura': [1.82]}
df = pd.DataFrame(data)
punto_nuevo = pd.DataFrame(punto_nuevo)
# sns.scatterplot(df['Masa'], df['Altura'], hue=df['sex'])
ax = plt.axes()
ax.scatter(df.loc[df['Genero'] == 'h', 'Masa'],
           df.loc[df['Genero'] == 'h', 'Altura'],
           c="red",
           label="Hombre")
ax.scatter(df.loc[df['Genero'] == 'm', 'Masa'],
           df.loc[df['Genero'] == 'm', 'Altura'],
           c="blue",
           label="Mujer")
ax.scatter(punto_nuevo['Masa'],
           punto_nuevo['Altura'],
           c="black")
plt.xlabel("Masa")
plt.ylabel("Altura")
ax.legend()
plt.show()

A continuación entrenamos el algoritmo KNN con los datos para los que tenemos etiquetas. Posteriormente predecimos la clase del punto para el que no tenemos etiqueta.

from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
X = df[['Masa', 'Altura']]
y = df[['Genero']]
knn.fit(X, y)
prediccion = knn.predict(punto_nuevo)
print(prediccion)

Conclusiones

En este post hemos hablado del algoritmo KNN. Hemos explicado cómo funciona y hemos puesto un ejemplo de uso en Python. Si además quisieras comprobar cómo desempeña este algoritmo para tu problema, te dejo por aquí un enlace a un artículo donde puedes descubrir qué métricas se pueden obtener a partir de una matriz de confusión.

Esperamos que les haya gustado. Si tienen cualquier duda, no duden en dejarla en los comentarios.