¿Hará falta otra persona mañana?
El encargado no necesita saber cuántas bicis exactas saldrán mañana. Le basta una respuesta: ¿será un día lleno o tranquilo? Si es lleno, llama a una segunda persona.
Una idea sencilla sirve: busca en el pasado los días con un tiempo parecido y mira qué pasó en ellos.
Al final de esta lección
Nota
Puedo clasificar un punto por sus vecinos y medir cuántas veces acierta.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Clasificar | poner una etiqueta a una fila | busy o quiet |
| Etiqueta | la respuesta conocida de una fila de entrenamiento | |
| Vecino más cercano | la fila conocida a menor distancia de la nueva | |
| k | cuántos vecinos votan | n_neighbors=5 |
| Exactitud | la parte de respuestas acertadas (accuracy en inglés) | |
| Matriz de confusión | una tabla de aciertos y fallos por etiqueta |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Los vecinos más cercanos votan
k vecinos más cercanos, o kNN, no aprende ninguna fórmula. Guarda los días conocidos con su etiqueta.
Para un día nuevo, mide la distancia a cada día conocido. La distancia entre dos puntos es la raíz de la suma de las diferencias al cuadrado. Elige los k días más cercanos y deja que voten. Gana la etiqueta con más votos.
Ejemplo resuelto: un día de 12 grados
| Día conocido | Etiqueta | Distancia a 12 grados, 0 mm | Puesto |
|---|---|---|---|
| 13 grados, 1 mm | lleno | 1,41 | 1.º |
| 10 grados, 0 mm | tranquilo | 2,00 | 2.º |
| 15 grados, 0 mm | lleno | 3,00 | 3.º |
| 6 grados, 2 mm | tranquilo | 6,32 | 4.º |
| 8 grados, 6 mm | tranquilo | 7,21 | 5.º |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Distancias y votos a mano
# Cinco días conocidos: temperatura, lluvia y etiqueta.
known = [[10.0, 0.0, "tranquilo"], [13.0, 1.0, "lleno"], [8.0, 6.0, "tranquilo"],
[15.0, 0.0, "lleno"], [6.0, 2.0, "tranquilo"]]
new_day = [12.0, 0.0]
gaps = []
for row in known:
gap = ((row[0] - new_day[0]) ** 2 + (row[1] - new_day[1]) ** 2) ** 0.5
gaps.append([round(gap, 2), row[2]])
for one in sorted(gaps):
print(one)
# Cuenta las etiquetas de las tres primeras líneas.
# Después cambia new_day a [9.0, 3.0] y vuelve a contar.
Escribe esto en tu cuaderno: las etiquetas
import pandas as pd
hires = pd.read_csv("hires.csv")
hires["label"] = "quiet"
hires.loc[hires["hires"] >= 300, "label"] = "busy"
hires["label"].value_counts()
Escribe esto en tu cuaderno: los vecinos
# Un día nuevo: 15 grados y sin lluvia.
gap = ((hires["temp_c"] - 15.0) ** 2 + hires["rain_mm"] ** 2) ** 0.5
hires.assign(gap=gap.round(2)).sort_values("gap", kind="stable").head(5)
La exactitud necesita una referencia
La exactitud es la parte de días de prueba en que la etiqueta acierta. Un 0,815 parece bueno, pero hay que compararlo.
La referencia más sencilla es un modelo perezoso que siempre dice la etiqueta más común. Si casi todos los días son tranquilos, decir siempre «quiet» ya acierta mucho. Un modelo vale la pena solo si mejora esa cifra.
Clasifica los días guardados
docker exec jupyter python3 steps/knn.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error muy común
Advertencia
Mucha gente cree que una exactitud alta significa un buen clasificador. Depende de la referencia: aquí decir siempre «quiet» ya acierta 0,641. Compara siempre con la etiqueta más común, y mira qué fallos comete con la matriz de confusión.
La matriz de confusión enseña los fallos
Una matriz de confusión cruza lo real con lo que dijo el modelo. En knn.py las filas son la verdad y las columnas la respuesta, en el orden busy y quiet.
La diagonal son los aciertos. Fuera de ella están los dos tipos de fallo. No cuestan lo mismo: un día lleno tomado por tranquilo deja al encargado solo con la cola.
Ejemplo resuelto: la matriz de knn.py
| Dijo busy | Dijo quiet | Total | |
|---|---|---|---|
| Era busy | 23, acierto | 10, fallo | 33 |
| Era quiet | 7, fallo | 52, acierto | 59 |
| Total | 30 | 62 | 92 días de prueba |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
k se elige con días que no vio
Con k = 1, el modelo copia a un solo vecino y se deja engañar por un día raro. Con un k enorme, casi siempre gana la etiqueta más común.
knnk.py prueba seis valores de k e imprime dos exactitudes para cada uno: con los días aprendidos y con los guardados. Elige k por la segunda.
Prueba seis valores de k
docker exec jupyter python3 steps/knnk.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Para ir más lejos: el fin de semana
El tiempo no lo explica todo: un sábado tiene más clientes con el mismo tiempo. En tu cuaderno, añade una columna weekend con isin(["Sat", "Sun"]).astype(int).
Repite knn.py con temp_c, rain_mm y weekend, k = 5 y el mismo reparto. ¿Supera 0,815? Prueba también con StandardScaler antes de medir distancias, y explica en una frase por qué cambia.