Bienvenido, soy Luis y en esta ocasión les traigo un nuevo tutorial.
Índice
k-Vecinos más cercanos
Los vecinos más cercanos k (KNN)
es un algoritmo de aprendizaje automático supervisado que se puede utilizar para tareas de regresión o clasificación. KNN
no es paramétrico, lo que significa que el algoritmo no hace suposiciones sobre las distribuciones subyacentes de los datos.
KNN
tiene la ventaja de ser bastante intuitivo de entender. Cuando se utiliza para la clasificación, un punto de consulta (o punto de prueba) se clasifica según el k
puntos de entrenamiento etiquetados que están más cerca de ese punto de consulta.
Para obtener un ejemplo simplificado, consulte la figura siguiente. El panel de la izquierda muestra una gráfica en 2-d
de dieciséis puntos de datos: ocho están etiquetados como verdes y ocho están etiquetados como morados.
Ahora, el panel derecho muestra cómo clasificaríamos un nuevo punto (la cruz negra), usando KNN
cuando k= 3
. Encontramos los tres puntos más cercanos y contamos cuántos 'votos'
tiene cada color dentro de esos tres puntos. En este caso, dos de los tres puntos son de color púrpura, por lo que la cruz negra se etiquetará como púrpura.
La distancia entre puntos se determina utilizando una de varias versiones de la ecuación de distancia de Minkowski. La fórmula generalizada para la distancia de Minkowski se puede representar de la siguiente manera:
Dónde X
y Y
son puntos de datos, north
es el número de dimensiones, y pag
es el parámetro de potencia de Minkowski. Cuando pag = 1
, la distancia se conoce a la distancia de Manhattan (o taxi), y cuando pag= 2
la distancia se conoce como distancia euclidiana.
En dos dimensiones, las distancias de Manhattan y euclidiana entre dos puntos son fáciles de visualizar (ver el gráfico a continuación), sin embargo en órdenes superiores de pag
, la distancia de Minkowski se vuelve más abstracta.
KNN en Python
Para implementar mi propia versión del clasificador KNN
en Python, primero querré importar algunas bibliotecas comunes para ayudar.
Cargando datos
Para probar el clasificador KNN
, usaré el conjunto de datos de iris de sklearn.datasets
. El conjunto de datos tiene medidas ( Longitud del sépalo, Ancho del sépalo, Longitud del pétalo, Ancho del pétalo ) para 150 plantas de iris, divididas uniformemente entre tres especies (0 = setosa
, 1 = versicolor
y 2 = virginica
).
A continuación, cargo los datos y los guardo en un marco de datos.
También separaré los datos en características (X)
y la variable objetivo (y)
, que es la etiqueta de especie para cada planta.
Construyendo el marco KNN
La creación de un clasificador KNN
funcional se puede dividir en varios pasos. Si bien KNN
incluye un poco más de matices que esto, aquí está mi lista básica de tareas pendientes:
- Definir una función para calcular la distancia entre dos puntos.
- Utilice la función de distancia para obtener la distancia entre un punto de prueba y todos los puntos de datos conocidos.
- Ordene las mediciones de distancia para encontrar los puntos más cercanos al punto de prueba (es decir, encuentre los vecinos más cercanos).
- Utilice etiquetas de clase mayoritaria de los puntos más cercanos para predecir la etiqueta del punto de prueba.
- Repita los pasos 1 a 4 hasta que todos los puntos de datos de prueba estén clasificados.
Primero, defino una función llamada minkowski_distance
, que toma una entrada de dos puntos de datos (una Y
segundo) y un parámetro de potencia de Minkowski pag
, y devuelve la distancia entre los dos puntos.
Tenga en cuenta que esta función calcula la distancia exactamente como la fórmula de Minkowski que mencioné anteriormente.
Haciendo pag
un parámetro ajustable, puedo decidir si quiero calcular la distancia de Manhattan (p = 1)
, la distancia euclidiana (p = 2)
o algún orden superior de la distancia de Minkowski.
0.6999999999999993
Para el paso 2
, simplemente repito el minkowski_distance
cálculo para todos los puntos etiquetados en X
y almacenarlos en un marco de datos.
En el paso 3
, uso los pandas .sort_values ()
para ordenar por distancia y devolver solo los 5
primeros resultados.
Para este paso, utilizo colecciones Contador
para realizar un seguimiento de las etiquetas que coinciden con los puntos vecinos más cercanos. Entonces uso el .más común()
método para devolver la etiqueta más común.
1
En este paso, pongo el código que ya escribí para que funcione y escribo una función para clasificar los datos usando KNN
.
Primero, realizo un train_test_split
en los datos (75% de entrenamiento, 25% de prueba) y luego escale los datos usando Escalador estándar ()
. Dado que KNN
se basa en la distancia, es importante asegurarse de que las características se escalen correctamente antes de introducirlas en el algoritmo.
Además, para evitar la fuga de datos, es una buena práctica escalar las características después de la train_test_split
se ha realizado.
Primero, escale los datos del conjunto de entrenamiento solamente (scaler.fit_transform (X_train)
), y luego use esa información para escalar el conjunto de prueba (scaler.tranform (X_test)
).
De esta manera, puedo asegurarme de que no se utilice información fuera de los datos de entrenamiento para crear el modelo.
A continuación, defino una función llamada knn_predict
que incluye todos los datos de entrenamiento y prueba, k
y pag
, y devuelve las predicciones que hace mi clasificador KNN
para el conjunto de prueba (y_hat_test
).
Esta función realmente no incluye nada nuevo, simplemente aplica lo que ya he trabajado anteriormente. La función debe devolver una lista de predicciones de etiquetas que contenga solo 0
, 1
y 2
.
[0, 1, 1, 0, 2, 1, 2, 0, 0, 2, 1, 0, 2, 1, 1, 0, 1, 1, 0, 0, 1, 1, 2, 0, 2, 1, 0, 0, 1, 2, 1, 2, 1, 2, 2, 0, 1, 0]
¡Y ahí están! Estas son las predicciones que este clasificador KNN
casero ha hecho en el equipo de prueba. Veamos qué tan bien funcionó:
0.9736842105263158
Parece que el clasificador logró un 97% de precisión en el equipo de prueba. ¡No esta mal del todo! ¿Pero cómo sé si realmente funcionó correctamente? Comprobemos el resultado de sklearn's KNeighborsClassifier
sobre los mismos datos:
# Prueba para ver los resultados de sklearn.neighbors.KNeighborsClassifier de sklearn.neighbors importar KNeighborsClassifier clf = KNeighborsClassifier (n_neighbors = 5, p = 1) clf.fit (X_train, y_train) y_pred_test = clf.predict (X_test) print (f "Precisión de Sklearn KNN: {precision_score (y_test, y_pred_test)}")
Precisión Sklearn KNN: 0.9736842105263158
¡Agradable! La implementación de sklearn del clasificador KNN
nos da exactamente la misma puntuación de precisión.
Explorando el efecto de variar k
Mi clasificador KNN
funcionó bastante bien con el valor seleccionado de k = 5
. KNN
no tiene tantos parámetros ajustables como otros algoritmos como los árboles de decisión o los bosques aleatorios, pero k
pasa a ser uno de ellos. Veamos cómo cambia la precisión de la clasificación cuando varío k
:
En este caso, el uso de casi cualquier k
un valor inferior a 20
da como resultado una gran precisión de clasificación (> 95%) en el equipo de prueba.
Sin embargo cuando k
llega a ser superior a 60
, la precisión realmente comienza a disminuir.
Esto tiene sentido, porque el conjunto de datos solo tiene 150
observaciones, cuando k
es tan alto, el clasificador probablemente esté considerando puntos de datos de entrenamiento etiquetados que están demasiado lejos de los puntos de prueba.
Todos los vecinos tienen un voto
Al escribir mi propio clasificador KNN
, elegí pasar por alto una clara oportunidad de ajuste de hiperparámetros: el peso que cada uno de los k
puntos más cercanos tiene en la clasificación de un punto.
En sklearn's
KNeighborsClassifier, este es el parámetro pesos
, y se puede configurar en 'uniforme'
, 'distancia'
, u otra función definida por el usuario.
- Cuando se establece en
'uniforme'
, cada uno de los k vecinos más cercanos obtiene el mismo voto al etiquetar un nuevo punto. - Cuando se establece en
'distancia'
, los vecinos más cercanos al nuevo punto tienen más peso que los vecinos más lejanos. - Ciertamente hay casos en los que la ponderación por
'distancia'
produciría mejores resultados, y la única forma de averiguarlo es mediante el ajuste de hiperparámetros.
Sin embargo, me pareció un ejercicio valioso trabajar con KNN
desde 'cero'
, y solo ha solidificado mi comprensión del algoritmo. ¡Espero que haya hecho lo mismo por ti!
Gracias por leer este artículo.
Hola, en primera instancia, agradecer la orientación y tengo una duda. Soy principiante en estos temas y requiero saber cómo clasificar elementos si mi base de datos tiene múltiples entradas categóricas (ej: género, deporte preferido, estado civil, lugar de residencia -rural o urbano-, entre otros) y otras numéricas (edad, peso, estatura…etc)… adicional, en este post, el ejemplo es muy útil pero la parte de graficación para ver cómo se clasifican x datos, no la veo… agradezco cualquier ayuda al respecto…