# aprendizaje-automatico-no-supervisado-con-python
Aprendizaje Automático No Supervisado con Python
Volver a la portada del cursoNotebook: Clustering con Scikit-learn
Sección 2 · Clustering con Python
Notebook: clustering con scikit-learn
En los videos viste cómo trabaja K-means y cómo se arma un dendrograma. En este notebook lo haces tú, de principio a fin, con las 1500 sesiones de PyShop: preparas los datos, agrupas con K-means, eliges k, pones nombre a cada grupo, clasificas sesiones nuevas y comparas con el clustering jerárquico. Esta guía acompaña al notebook clustering-con-scikit-learn y te dice qué buscar en cada sección y qué resultados debes obtener.
Objetivos
- Escalar las 8 columnas de comportamiento y entender por qué.
- Ajustar
KMeansy leerlabels_,cluster_centers_einertia_. - Elegir
kcon el codo de la inercia y con silhouette. - Traducir los centros a unidades originales y nombrar los grupos.
- Comparar K-means con
AgglomerativeClusteringusando el índice de Rand ajustado (ARI).
1. Datos y escalado
La primera celda define generar_sesiones() y la lista COLUMNAS; el notebook es autocontenido. Se separa X = df[COLUMNAS] (sin dispositivo, que es contexto) y se escala:
from sklearn.preprocessing import StandardScaler
df = generar_sesiones()
X = df[COLUMNAS]
sc = StandardScaler()
Xs = sc.fit_transform(X)
print(X.var().round(1).tail(2))
Mira las varianzas: monto_carrito_mxn tiene 3,722,205 y pct_ofertas 0.1. El notebook ajusta K-means con y sin escalar para que veas la diferencia: sin escalar, los tamaños son [1051, 132, 281, 36] y los centros solo se separan por monto; escalado, [310, 617, 375, 198].
2. K-means con cuatro grupos
import numpy as np
from sklearn.cluster import KMeans
km = KMeans(n_clusters=4, n_init=10, random_state=42).fit(Xs)
print(np.bincount(km.labels_)) # [310 617 375 198]
print(round(km.inertia_, 1), km.n_iter_) # 3513.2 9
labels_ tiene el grupo de cada sesión; inertia_ es la suma de distancias al cuadrado de cada sesión a su centro (3513.2); el algoritmo convergió en 9 iteraciones. n_init=10 repite el ajuste con 10 inicios distintos y se queda con el de menor inercia.
3. Elegir k: codo y silhouette
El notebook recorre k de 2 a 8 y grafica la inercia y el silhouette promedio. El silhouette de una sesión compara $a$, la distancia media a su propio grupo, con $b$, la distancia media al grupo vecino más cercano:
$$s = \frac{b - a}{\max(a, b)}$$
Vale entre −1 y 1; cerca de 1, la sesión está bien metida en su grupo. Resultados esperados:
| k | Inercia | Silhouette |
|---|---|---|
| 2 | 6983.2 | 0.456 |
| 3 | 5063.0 | 0.414 |
| 4 | 3513.2 | 0.479 |
| 5 | 3190.4 | 0.449 |
| 6 | 2900.5 | 0.401 |
| 8 | 2477.5 | 0.385 |
La inercia siempre baja al aumentar k; lo que importa es dónde deja de bajar mucho. De 3 a 4 cae 1549.8; de 4 a 5, solo 322.8. El codo y el máximo de silhouette coinciden en 4.
4. Nombrar los grupos
Los centros están en unidades escaladas. sc.inverse_transform(km.cluster_centers_) los devuelve a páginas, minutos y pesos. Debes obtener estos perfiles:
- Grupo 0, cazadores de ofertas (310): 11.2 páginas, 9.1 minutos, 70 % de páginas de ofertas, 731 MXN en el carrito.
- Grupo 1, visitas rápidas (617): 2.6 páginas, 2.5 minutos, 1.0 productos vistos.
- Grupo 2, comparadores (375): 24.4 páginas, 19.5 minutos, 14.5 productos, 6.6 reseñas leídas.
- Grupo 3, compradores decididos (198): 5.8 páginas, 3.7 productos al carrito, 5158 MXN.
Los nombres los pones tú, mirando estas cifras; el algoritmo solo entrega números.
5. Clasificar sesiones nuevas
Una sesión nueva se escala con el mismo sc (transform, nunca fit_transform) y se pasa a predict. El notebook prueba tres: 3 páginas en 1.5 minutos sin carrito da el grupo 1; 30 páginas, 25 minutos y 9 reseñas da el 2; 12 páginas con 80 % de ofertas y 2400 MXN en el carrito da el 0.
6. Clustering jerárquico
from sklearn.cluster import AgglomerativeClustering
from sklearn.metrics import adjusted_rand_score
ward = AgglomerativeClustering(n_clusters=4, linkage="ward")
lab_w = ward.fit_predict(Xs)
print(np.bincount(lab_w)) # [679 379 305 137]
print(round(adjusted_rand_score(km.labels_, lab_w), 3)) # 0.89
El ARI mide cuánto coinciden dos particiones sin importar cómo se numeren los grupos: 1 es coincidencia total y cerca de 0 es azar. Ward y K-means coinciden en 0.890. El notebook también dibuja el dendrograma de una muestra de 30 sesiones y calcula el completo con scipy.cluster.hierarchy.linkage(Xs, "ward"): sus últimas fusiones ocurren a 26.6, 55.5, 60.4 y 100.1, así que cortar a altura 40 con fcluster deja 4 grupos. Con linkage="single", en cambio, sale [1497, 1, 1, 1]: el enlace importa.
7. Comprobación final
La última sección genera los datos con con_tipo=True y cruza los grupos con el tipo real, que en un problema real no existiría. ARI de K-means: 0.849. Los curiosos caen todos en el grupo 1 y los comparadores casi todos en el 2, pero 88 compradores decididos que agregaron poco al carrito quedan en «visitas rápidas».
Qué debes obtener
Tamaños [310, 617, 375, 198], inercia 3513.2, silhouette 0.479 y los cuatro perfiles de arriba. Si tus números difieren, revisa la semilla de los datos, random_state=42 y que dispositivo no haya entrado en X. Como práctica, repite el ajuste con k=5 y describe qué grupo se parte en dos.