Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn

Introducción

Agrupamiento de K-medias es uno de los algoritmos de aprendizaje automático no supervisado más utilizados que forman grupos de datos en función de la similitud entre las instancias de datos.

En esta guía, primero veremos un ejemplo simple para comprender cómo funciona el algoritmo K-Means antes de implementarlo con Scikit-Learn. Luego, discutiremos cómo determinar la cantidad de conglomerados (K) en K-Means, y también cubriremos las métricas de distancia, la varianza y las ventajas y desventajas de K-Means.

Motivación

Imagina la siguiente situación. Un día, mientras caminaba por el vecindario, notó que había 10 tiendas de conveniencia y comenzó a preguntarse qué tiendas eran similares, más cercanas entre sí. Mientras buscaba formas de responder esa pregunta, encontró un enfoque interesante que divide las tiendas en grupos según sus coordenadas en un mapa.

Por ejemplo, si una tienda estuviera ubicada 5 km al oeste y 3 km al norte, asignaría (5, 3) coordenadas y representarlo en un gráfico. Grafiquemos este primer punto para visualizar lo que está pasando:

import matplotlib.pyplot as plt

plt.title("Store With Coordinates (5, 3)")
plt.scatter(x=5, y=3)

Este es solo el primer punto, para que podamos hacernos una idea de cómo podemos representar una tienda. Digamos que ya tenemos 10 coordenadas para las 10 tiendas recolectadas. Después de organizarlos en un numpy matriz, también podemos trazar sus ubicaciones:

import numpy as np

points = np.array([[5, 3], [10, 15], [15, 12], [24, 10], [30, 45], [85, 70], [71, 80], [60, 78], [55, 52],[80, 91]])

xs = points[:,0] 
ys = points[:,1]  

plt.title("10 Stores Coordinates")
plt.scatter(x=xs, y=ys)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Cómo implementar manualmente el algoritmo K-Means

Ahora podemos ver las 10 tiendas en un gráfico, y el problema principal es encontrar si hay alguna manera de dividirlas en diferentes grupos según la proximidad. Con solo echar un vistazo rápido al gráfico, probablemente notemos dos grupos de tiendas – uno son los puntos inferiores a la parte inferior izquierda y el otro son los puntos superiores a la derecha. Tal vez, incluso podamos diferenciar esos dos puntos en el medio como un grupo separado, creando así tres grupos diferentes.

En esta sección, repasaremos el proceso de agrupar puntos manualmente, dividiéndolos en el número dado de grupos. De esa manera, repasaremos cuidadosamente todos los pasos del Algoritmo de agrupación de K-Means. Al final de esta sección, obtendrá una comprensión intuitiva y práctica de todos los pasos realizados durante el agrupamiento de K-Means. Después de eso, lo delegaremos a Scikit-Learn.

¿Cuál sería la mejor manera de determinar si hay dos o tres grupos de puntos? Una forma sencilla sería simplemente elegir un número de grupos, por ejemplo, dos, y luego tratar de agrupar puntos en función de esa elección.

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Digamos que hemos decidido que hay dos grupos de nuestras tiendas (puntos). Ahora, necesitamos encontrar una manera de entender qué puntos pertenecen a qué grupo. Esto podría hacerse eligiendo un punto para representar grupo 1 y uno para representar grupo 2. Esos puntos se utilizarán como referencia al medir la distancia de todos los demás puntos a cada grupo.

De esa manera, diga punto (5, 3) acaba perteneciendo al grupo 1, y punto (79, 60) al grupo 2. Al intentar asignar un nuevo punto (6, 3) a grupos, necesitamos medir su distancia a esos dos puntos. En el caso del punto (6, 3) is más cerca En el correo electrónico “Su Cuenta de Usuario en su Nuevo Sistema XNUMXCX”. (5, 3), por lo tanto pertenece al grupo representado por ese punto – grupo 1. De esta manera, podemos agrupar fácilmente todos los puntos en grupos correspondientes.

En este ejemplo, además de determinar el número de grupos (grupos) – también estamos eligiendo algunos puntos para ser un referencia de distancia para nuevos puntos de cada grupo.

Esa es la idea general para entender las similitudes entre nuestras tiendas. Pongámoslo en práctica: primero podemos elegir los dos puntos de referencia en azar. El punto de referencia de grupo 1 se mostrarán (5, 3) y el punto de referencia de grupo 2 se mostrarán (10, 15). Podemos seleccionar ambos puntos de nuestro numpy arreglo por [0] y [1] índices y almacenarlos en g1 (grupo 1) y g2 (grupo 2) variables:

g1 = points[0]
g2 = points[1]

Después de hacer esto, necesitamos calcular la distancia desde todos los demás puntos hasta esos puntos de referencia. Esto plantea una pregunta importante: cómo medir esa distancia. Esencialmente, podemos usar cualquier medida de distancia, pero, para el propósito de esta guía, usemos Euclidean Distance_.

Puede ser útil saber que la medida de la distancia euclidiana se basa en el teorema de Pitágoras:

$$
c ^ 2 = a ^ 2 + b ^ 2
$$

Cuando se adapta a puntos en un plano: (a1, b1) y (a2, b2), la fórmula anterior se convierte en:

$$
c^2 = (a2-a1)^2 + (b2-b1)^2
$$

La distancia será la raíz cuadrada de c, por lo que también podemos escribir la fórmula como:

$$
euclidiana_{dist} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2)]
$$

Nota: También puede generalizar la fórmula de la distancia euclidiana para puntos multidimensionales. Por ejemplo, en un espacio tridimensional, los puntos tienen tres coordenadas; nuestra fórmula lo refleja de la siguiente manera:
$$
euclidiana_{dist} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2 + (c2 – c1) ^2)]
$$
Se sigue el mismo principio sin importar el número de dimensiones del espacio en el que estemos operando.

Hasta ahora, hemos elegido los puntos para representar grupos y sabemos cómo calcular distancias. Ahora, juntemos las distancias y los grupos asignando cada uno de nuestros puntos de tienda recopilados a un grupo.

Para visualizar mejor eso, declararemos tres listas. El primero en almacenar puntos del primer grupo – points_in_g1. El segundo para almacenar puntos del grupo 2 – points_in_g2, y el último - group, a un Label los puntos como 1 (pertenece al grupo 1) o 2 (pertenece al grupo 2):

points_in_g1 = []
points_in_g2 = []
group = []

Ahora podemos iterar a través de nuestros puntos y calcular la distancia euclidiana entre ellos y cada una de las referencias de nuestro grupo. Cada punto será más cerca a uno de dos grupos: en función del grupo más cercano, asignaremos cada punto a la lista correspondiente, al mismo tiempo que agregaremos 1 or 2 En el correo electrónico “Su Cuenta de Usuario en su Nuevo Sistema XNUMXCX”. group lista:

for p in points:
    x1, y1 = p[0], p[1]
    euclidean_distance_g1 = np.sqrt((g1[0] - x1)**2 + (g1[1] - y1)**2)
    euclidean_distance_g2 = np.sqrt((g2[0] - x1)**2 + (g2[1] - y1)**2)
    if euclidean_distance_g1 < euclidean_distance_g2:
        points_in_g1.append(p)
        group.append('1')
    else:
        points_in_g2.append(p)
        group.append('2')

Veamos los resultados de esta iteración para ver qué sucedió:

print(f'points_in_g1:{points_in_g1}n 
npoints_in_g2:{points_in_g2}n 
ngroup:{group}')

Lo que resulta en:

points_in_g1:[array([5, 3])]
 
points_in_g2:[array([10, 15]), array([15, 12]), 
              array([24, 10]), array([30, 45]), 
              array([85, 70]), array([71, 80]),
              array([60, 78]), array([55, 52]), 
              array([80, 91])]
 
group:[1, 2, 2, 2, 2, 2, 2, 2, 2, 2] 

También podemos graficar el resultado de la agrupación, con diferentes colores según los grupos asignados, utilizando Seaborn's scatterplot() con el group como herramienta de edición del hue argumento:

import seaborn as sns

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Es claramente visible que solo nuestro primer punto está asignado al grupo 1, y todos los demás puntos fueron asignados al grupo 2. Ese resultado difiere de lo que habíamos imaginado al principio. Teniendo en cuenta la diferencia entre nuestros resultados y nuestras expectativas iniciales, ¿hay alguna forma de que podamos cambiar eso? ¡Parece que hay!

Un enfoque es repetir el proceso y elegir diferentes puntos para que sean las referencias de los grupos. Con suerte, esto cambiará nuestros resultados, más en línea con lo que habíamos imaginado al principio. Esta segunda vez, podríamos elegirlos no al azar como lo hicimos anteriormente, sino al obtener una personalizado de todos nuestros puntos ya agrupados. De esa manera, esos nuevos puntos podrían colocarse en medio de los grupos correspondientes.

Por ejemplo, si el segundo grupo tuviera solo puntos (10, 15), (30, 45). El nuevo central el punto seria (10 + 30)/2 y (15+45)/2 - que es igual a (20, 30).

Como hemos puesto nuestros resultados en listas, podemos convertirlos primero en numpy arreglos, seleccione sus xs, ys y luego obtenga el personalizado:

g1_center = [np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()]
g2_center = [np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()]
g1_center, g2_center

Consejo: Tratar de usar numpy y matrices NumPy tanto como sea posible. Están optimizados para un mejor rendimiento y simplifican muchas operaciones de álgebra lineal. Siempre que intente resolver algún problema de álgebra lineal, definitivamente debería echar un vistazo a la numpy documentación para comprobar si hay alguna numpy método diseñado para resolver su problema. ¡La posibilidad es que la haya!

Para ayudar a repetir el proceso con nuestros nuevos puntos centrales, transformemos nuestro código anterior en una función, ejecútelo y vea si hubo algún cambio en la forma en que se agrupan los puntos:

def assigns_points_to_two_groups(g1_center, g2_center):
    points_in_g1 = []
    points_in_g2 = []
    group = []

    for p in points:
        x1, y1 = p[0], p[1]
        euclidean_distance_g1 = np.sqrt((g1_center[0] - x1)**2 + (g1_center[1] - y1)**2)
        euclidean_distance_g2 = np.sqrt((g2_center[0] - x1)**2 + (g2_center[1] - y1)**2)
        if euclidean_distance_g1 < euclidean_distance_g2:
            points_in_g1.append(p)
            group.append(1)
        else:
            points_in_g2.append(p)
            group.append(2)
    return points_in_g1, points_in_g2, group

Nota: Si nota que sigue repitiendo el mismo código una y otra vez, debe envolver ese código en una función separada. Se considera una buena práctica organizar el código en funciones, especialmente porque facilitan las pruebas. Es más fácil probar una pieza de código aislada que un código completo sin ninguna función.

Llamemos a la función y almacenemos sus resultados en points_in_g1, points_in_g2y group variables:

points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
points_in_g1, points_in_g2, group

Y también trace el diagrama de dispersión con los puntos coloreados para visualizar la división de grupos:

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Parece que la agrupación de nuestros puntos es mejorando. Pero aún así, hay dos puntos en el medio del gráfico que podrían asignarse a cualquier grupo al considerar su proximidad a ambos grupos. El algoritmo que hemos desarrollado hasta ahora asigna ambos puntos al segundo grupo.

Esto significa que probablemente podamos repetir el proceso una vez más tomando los medios de las X y las Y, creando dos nuevos puntos centrales. (centroides) a nuestros grupos y reasignarlos en función de la distancia.

También creemos una función para actualizar los centroides. Todo el proceso ahora se puede reducir a múltiples llamadas de esa función:

def updates_centroids(points_in_g1, points_in_g2):
    g1_center = np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()
    g2_center = np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()
    return g1_center, g2_center

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Nótese que después de esta tercera iteración, cada uno de los puntos pertenece ahora a diferentes clusters. Parece que los resultados están mejorando, hagámoslo una vez más. Ahora yendo a la cuarta iteración de nuestro método:

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Esta cuarta vez tenemos el mismo resultado como el anterior. Entonces parece que nuestros puntos ya no cambiarán de grupo, nuestro resultado ha alcanzado algún tipo de estabilidad: ha llegado a un estado inmutable, o convergido. Además de eso, tenemos exactamente el mismo resultado que habíamos previsto para los 2 grupos. También podemos ver si esta división alcanzada tiene sentido.

Recapitulemos rápidamente lo que hemos hecho hasta ahora. Hemos dividido nuestras 10 tiendas geográficamente en dos secciones: unas en las regiones del sudoeste inferior y otras en el noreste. Puede ser interesante recopilar más datos además de los que ya tenemos: ingresos, número diario de clientes y muchos más. De esa manera podemos realizar un análisis más rico y posiblemente generar resultados más interesantes.

Los estudios de agrupamiento como este se pueden realizar cuando una marca ya establecida quiere elegir un área para abrir una nueva tienda. En ese caso, se tienen en cuenta muchas más variables además de la ubicación.

¿Qué tiene que ver todo esto con el algoritmo K-Means?

Mientras sigue estos pasos, es posible que se haya preguntado qué tienen que ver con el algoritmo K-Means. El proceso que hemos llevado a cabo hasta ahora es el Algoritmo K-Means. En resumen, determinamos la cantidad de grupos/conglomerados, elegimos puntos iniciales al azar y actualizamos los centroides en cada iteración hasta que los conglomerados convergieron. Básicamente, hemos realizado todo el algoritmo a mano, realizando cuidadosamente cada paso.

La K en K-Means proviene de la número de grupos que deben establecerse antes de iniciar el proceso de iteración. En nuestro caso K = 2. Esta característica se ve a veces como negativas teniendo en cuenta que existen otros métodos de agrupamiento, como el agrupamiento jerárquico, que no necesita tener un número fijo de clústeres de antemano.

Debido a su uso de medios, K-means también se convierte en sensible a valores atípicos y extremos – aumentan la variabilidad y dificultan que nuestros centroides desempeñen su papel. Por lo tanto, sea consciente de la necesidad de realizar valores extremos y análisis de valores atípicos antes de realizar un agrupamiento utilizando el algoritmo K-Means.

Además, observe que nuestros puntos se segmentaron en partes rectas, no hay curvas al crear los grupos. Eso también puede ser una desventaja del algoritmo K-Means.

Nota: Cuando necesite que sea más flexible y adaptable a elipses y otras formas, intente usar un Modelo de mezcla gaussiana de K-medias generalizadas. Este modelo puede adaptarse a clústeres de segmentación elíptica.

K-Means también tiene muchos ventajas! Se desempeña bien en grandes conjuntos de datos que puede volverse difícil de manejar si está utilizando algunos tipos de algoritmos de agrupamiento jerárquico. También garantiza la convergenciay puede fácilmente generalizar y adaptar. Además de eso, es probablemente el algoritmo de agrupamiento más utilizado.

Ahora que hemos repasado todos los pasos realizados en el algoritmo K-Means y entendido todos sus pros y contras, finalmente podemos implementar K-Means utilizando la biblioteca Scikit-Learn.

Cómo implementar el algoritmo K-Means usando Scikit-Aprender

Para verificar dos veces nuestro resultado, hagamos este proceso nuevamente, pero ahora usando 3 líneas de código con sklearn:

from sklearn.cluster import KMeans


kmeans = KMeans(n_clusters=2, random_state=42) 
kmeans.fit(points)
kmeans.labels_

Aquí, las etiquetas son las mismas que en nuestros grupos anteriores. Grafiquemos rápidamente el resultado:

sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

El gráfico resultante es el mismo que el del apartado anterior.

Consulte nuestra guía práctica y práctica para aprender Git, con las mejores prácticas, los estándares aceptados por la industria y la hoja de trucos incluida. Deja de buscar en Google los comandos de Git y, de hecho, aprenden ella!

Nota: Solo mirar cómo hemos realizado el algoritmo K-Means usando Scikit-Learn puede darle la impresión de que es una obviedad y que no necesita preocuparse demasiado por eso. Solo 3 líneas de código realizan todos los pasos que hemos discutido en la sección anterior cuando hemos repasado el algoritmo K-Means paso a paso. Pero, El diablo está en los detalles ¡en este caso! Si no comprende todos los pasos y las limitaciones del algoritmo, lo más probable es que se enfrente a una situación en la que el algoritmo K-Means le proporcione resultados que no esperaba.

Con Scikit-Learn, también puede inicializar K-Means para una convergencia más rápida configurando el init='k-means++' argumento. En términos más amplios, K-medias++ todavía elige el k el conglomerado inicial se centra aleatoriamente siguiendo una distribución uniforme. Luego, cada centro de grupo subsiguiente se elige de los puntos de datos restantes no calculando solo una medida de distancia, sino usando probabilidad. El uso de la probabilidad acelera el algoritmo y es útil cuando se trata de conjuntos de datos muy grandes.

El método del codo: elegir el mejor número de grupos

¡Hasta aquí todo bien! Hemos agrupado 10 tiendas según la distancia euclidiana entre puntos y centroides. Pero, ¿qué pasa con esos dos puntos en el medio del gráfico que son un poco más difíciles de agrupar? ¿No podrían formar un grupo separado también? ¿De verdad cometimos un error al elegir K = 2 grupos? Tal vez en realidad tuvimos K = 3 grupos? Incluso podríamos tener más de tres grupos y no ser conscientes de ello.

La pregunta que se hace aquí es cómo determinar el número de grupos (K) en K-Means. Para responder a esa pregunta, debemos comprender si habría un grupo "mejor" para un valor diferente de K.

La forma ingenua de averiguarlo es agrupando puntos con diferentes valores de K, entonces, para K=2, K=3, K=4, etc.:

for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 

Pero, agrupar puntos para diferentes Ks solo no será suficiente para entender si hemos elegido el valor ideal para K. Necesitamos una manera de evaluar la calidad del agrupamiento para cada K hemos elegido.

Cálculo manual de la Dentro de la suma de cuadrados de clúster (WCSS)

Este es el lugar ideal para introducir una medida de cuánto están cerca unos de otros nuestros puntos agrupados. Esencialmente describe cuánto diferencia tenemos dentro de un solo grupo. Esta medida se llama Dentro del grupo Suma de cuadradoso WCSS para abreviar. Cuanto más pequeño es el WCSS, más cerca están nuestros puntos, por lo tanto, tenemos un clúster mejor formado. La fórmula WCSS se puede utilizar para cualquier número de clústeres:

$$
WCSS = suma (Pi_1 – Centroide_1)^2 + cdots + suma (Pi_n – Centroide_n)^2
$$

Nota: En esta guía, estamos utilizando el distancia euclidiana para obtener los centroides, pero también se podrían utilizar otras medidas de distancia, como Manhattan.

Ahora podemos suponer que hemos optado por tener dos clústeres e intentar implementar el WCSS para comprender mejor qué es el WCSS y cómo usarlo. Como dice la fórmula, necesitamos sumar las diferencias al cuadrado entre todos los puntos de conglomerados y los centroides. Entonces, si nuestro primer punto del primer grupo es (5, 3) y nuestro último centroide (después de la convergencia) del primer grupo es (16.8, 17.0), el WCSS será:

$$
WCSS = suma ((5,3) - (16.8, 17.0)) ^ 2
$$

$$
WCSS = suma ((5-16.8) + (3-17.0)) ^ 2
$$

$$
WCSS = suma ((-11.8) + (-14.0)) ^ 2
$$

$$
WCSS = suma ((-25.8)) ^ 2
$$

$$
WCSS = 335.24
$$

Este ejemplo ilustra cómo calculamos el WCSS para un punto del clúster. Pero el grupo generalmente contiene más de un punto, y debemos tenerlos en cuenta al calcular el WCSS. Lo haremos definiendo una función que reciba un grupo de puntos y centroides, y devuelva la suma de los cuadrados:

def sum_of_squares(cluster, centroid):
    squares = []
    for p in cluster:
        squares.append((p - centroid)**2)
        ss = np.array(squares).sum()
    return ss

Ahora podemos obtener la suma de cuadrados para cada grupo:

g1 = sum_of_squares(points_in_g1, g1_center)
g2 = sum_of_squares(points_in_g2, g2_center)

Y suma los resultados para obtener el total. WCSS:

g1 + g2

Esto resulta en:

2964.3999999999996

Entonces, en nuestro caso, cuando K es igual a 2, el WCSS total es 2964.39. Ahora, podemos cambiar Ks y calcular el WCSS para todos ellos. De esa manera, podemos obtener una idea de lo que K debemos elegir hacer que nuestro agrupamiento tenga el mejor rendimiento.

Calculador WCSS Usar Scikit-Aprender

Afortunadamente, no necesitamos calcular manualmente el WCSS para cada K. Después de realizar el agrupamiento de K-Means para el número de clústeres dado, podemos obtener su WCSS usando el inertia_ atributo. Ahora, podemos volver a nuestros K-Means for bucle, utilícelo para cambiar el número de clústeres y enumere los valores WCSS correspondientes:

wcss = [] 
for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 
    wcss.append(kmeans.inertia_)
wcss

Observe que el segundo valor en la lista es exactamente el mismo que hemos calculado antes para K = 2:

[18272.9, # For k=1 
 2964.3999999999996, # For k=2
 1198.75, # For k=3
 861.75,
 570.5,
 337.5,
 175.83333333333334,
 79.5,
 17.0,
 0.0]

Para visualizar esos resultados, tracemos nuestro Ks junto con los valores WCSS:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Hay una interrupción en una trama cuando x = 2, un punto bajo en la línea, y uno aún más bajo cuando x = 3. Nótese que nos recuerda a la forma de codo. Al graficar las K junto con el WCSS, estamos usando el Método del codo para elegir el número de Ks. Y el elegido K es exactamente el punto de codo más bajo, entonces, sería 3 en lugar de 2, en nuestro caso:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss);
plt.axvline(3, linestyle='--', color='r')

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Podemos ejecutar el algoritmo de conglomerado K-Means de nuevo, para ver cómo se verían nuestros datos con tres racimos:

kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(points)
sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Ya estábamos satisfechos con dos grupos, pero según el método del codo, tres grupos se ajustarían mejor a nuestros datos. En este caso, tendríamos tres tipos de tiendas en lugar de dos. Antes de usar el método del codo, pensábamos en los grupos de tiendas del suroeste y noreste, ahora también tenemos tiendas en el centro. Tal vez esa podría ser una buena ubicación para abrir otra tienda ya que tendría menos competencia cerca.

Medidas de calidad de clúster alternativas

También hay otras medidas que se pueden utilizar al evaluar la calidad del conglomerado:

  • Puntuación de la silueta – analiza no solo la distancia entre los puntos intra-cluster sino también entre los mismos clusters
  • Entre Conglomerados Suma de Cuadrados (BCSS) – métrica complementaria al WCSS
  • Error de suma de cuadrados (ESS)
  • Radio máximo – mide la mayor distancia de un punto a su baricentro
  • Radio medio – la suma de la mayor distancia de un punto a su centroide dividida por el número de grupos.

Se recomienda experimentar y conocer cada una de ellas ya que dependiendo del problema, algunas de las alternativas pueden ser más aplicables que las métricas más utilizadas. (WCSS y puntuación de silueta).

Al final, como con muchos algoritmos de ciencia de datos, queremos reducir la variación dentro de cada grupo y maximizar la variación entre diferentes grupos. Entonces tenemos grupos más definidos y separables.

Aplicar K-Means en otro conjunto de datos

Usemos lo que hemos aprendido en otro conjunto de datos. En esta ocasión, intentaremos encontrar grupos de vinos similares.

Nota: Puede descargar el conjunto de datos esta página.

Empezamos importando pandas para leer el wine-clustering CSV (Valores Separados por Comas) archivar en un Dataframe estructura:

import pandas as pd

df = pd.read_csv('wine-clustering.csv')

Después de cargarlo, echemos un vistazo a los primeros cinco registros de datos con el head() método:

df.head()

Esto resulta en:

	Alcohol 	Malic_Acid 	Ash 	Ash_Alcanity 	Magnesium 	Total_Phenols 	Flavanoids 	Nonflavanoid_Phenols 	Proanthocyanins 	Color_Intensity 	Hue 	OD280 	Proline
0 	14.23 		1.71 		2.43 	15.6 			127 		2.80 			3.06 		0.28 					2.29 				5.64 				1.04 	3.92 	1065
1 	13.20 		1.78 		2.14 	11.2 			100 		2.65 			2.76 		0.26 					1.28 				4.38 				1.05 	3.40 	1050
2 	13.16 		2.36 		2.67 	18.6 			101 		2.80 			3.24 		0.30 					2.81 				5.68 				1.03 	3.17 	1185
3 	14.37 		1.95 		2.50 	16.8 			113 		3.85 			3.49 		0.24 					2.18 				7.80 				0.86 	3.45 	1480
4 	13.24 		2.59 		2.87 	21.0 			118 		2.80 			2.69 		0.39 					1.82 				4.32 				1.04 	2.93 	735

Disponemos de multitud de medidas de sustancias presentes en los vinos. Aquí, tampoco necesitaremos transformar columnas categóricas porque todas ellas son numéricas. Ahora, echemos un vistazo a las estadísticas descriptivas con el describe() método:

df.describe().T 

La tabla de descripción:

 						count 	mean 		std 		min 	25% 	50% 	75% 		max
Alcohol 				178.0 	13.000618 	0.811827 	11.03 	12.3625 13.050 	13.6775 	14.83
Malic_Acid 				178.0 	2.336348 	1.117146 	0.74 	1.6025 	1.865 	3.0825 		5.80
Ash 					178.0 	2.366517 	0.274344 	1.36 	2.2100 	2.360 	2.5575 		3.23
Ash_Alcanity 			178.0 	19.494944 	3.339564 	10.60 	17.2000 19.500 	21.5000 	30.00
Magnesium 				178.0 	99.741573 	14.282484 	70.00 	88.0000 98.000 	107.0000 	162.00
Total_Phenols 			178.0 	2.295112 	0.625851 	0.98 	1.7425 	2.355 	2.8000 		3.88
Flavanoids 				178.0 	2.029270 	0.998859 	0.34 	1.2050 	2.135 	2.8750 		5.08
Nonflavanoid_Phenols 	178.0 	0.361854 	0.124453 	0.13 	0.2700 	0.340 	0.4375 		0.66
Proanthocyanins 		178.0 	1.590899 	0.572359 	0.41 	1.2500 	1.555 	1.9500 		3.58
Color_Intensity 		178.0 	5.058090 	2.318286 	1.28 	3.2200 	4.690 	6.2000 		13.00
Hue 					178.0 	0.957449 	0.228572 	0.48 	0.7825 	0.965 	1.1200 		1.71
OD280 					178.0 	2.611685 	0.709990 	1.27 	1.9375 	2.780 	3.1700 		4.00
Proline 				178.0 	746.893258 	314.907474 	278.00 	500.500 673.500 985.0000 	1680.00

Al mirar la tabla, está claro que hay algunos variabilidad en los datos – para algunas columnas como Alchool hay más, y para otros, como Malic_Acid, menos. Ahora podemos comprobar si hay alguna. nullo NaN valores en nuestro conjunto de datos:

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 13 columns):
 #   Column                Non-Null Count  Dtype  
---  ------                --------------  -----  
 0   Alcohol               178 non-null    float64
 1   Malic_Acid            178 non-null    float64
 2   Ash                   178 non-null    float64
 3   Ash_Alcanity          178 non-null    float64
 4   Magnesium             178 non-null    int64  
 5   Total_Phenols         178 non-null    float64
 6   Flavanoids            178 non-null    float64
 7   Nonflavanoid_Phenols  178 non-null    float64
 8   Proanthocyanins       178 non-null    float64
 9   Color_Intensity       178 non-null    float64
 10  Hue                   178 non-null    float64
 11  OD280                 178 non-null    float64
 12  Proline               178 non-null    int64  
dtypes: float64(11), int64(2)
memory usage: 18.2 KB

No hay necesidad de soltar o ingresar datos, considerando que no hay valores vacíos en el conjunto de datos. Podemos usar un Seaborn pairplot() para ver la distribución de datos y verificar si el conjunto de datos forma pares de columnas que pueden ser interesantes para la agrupación:

sns.pairplot(df)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Al observar el diagrama de pares, dos columnas parecen prometedoras para fines de agrupación: Alcohol y OD280 (que es un método para determinar la concentración de proteínas en los vinos). Parece que hay 3 grupos distintos en parcelas que combinan dos de ellos.

Hay otras columnas que también parecen estar en correlación. Más destacado Alcohol y Total_Phenolsy Alcohol y Flavanoids. Tienen grandes relaciones lineales que se pueden observar en el diagrama de pares.

Dado que nuestro enfoque es agrupar con K-Means, elijamos un par de columnas, digamos Alcohol y OD280y pruebe el método del codo para este conjunto de datos.

Nota: Al usar más columnas del conjunto de datos, será necesario trazar en 3 dimensiones o reducir los datos a componentes principales (uso de PCA). Este es un enfoque válido y más común, solo asegúrese de elegir los componentes principales en función de cuánto explican y tenga en cuenta que al reducir las dimensiones de los datos, se pierde algo de información, por lo que la gráfica es un aproximación de los datos reales, no como realmente son.

Tracemos el diagrama de dispersión con esas dos columnas configuradas como su eje para ver más de cerca los puntos que queremos dividir en grupos:

sns.scatterplot(data=df, x='OD280', y='Alcohol')

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Ahora podemos definir nuestras columnas y usar el método del codo para determinar el número de grupos. También iniciaremos el algoritmo con kmeans++ solo para asegurarse de que converge más rápidamente:

values = df[['OD280', 'Alcohol']]

wcss_wine = [] 
for i in range(1, 11): 
    kmeans = KMeans(n_clusters = i, init = 'k-means++', random_state = 42)
    kmeans.fit(values) 
    wcss_wine.append(kmeans.inertia_)

Hemos calculado el WCSS, por lo que podemos trazar los resultados:

clusters_wine = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
plt.plot(clusters_wine, wcss_wine)
plt.axvline(3, linestyle='--', color='r')

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

De acuerdo con el método del codo, deberíamos tener 3 grupos aquí. Para el paso final, agrupemos nuestros puntos en 3 grupos y tracemos esos grupos identificados por colores:

kmeans_wine = KMeans(n_clusters=3, random_state=42)
kmeans_wine.fit(values)
sns.scatterplot(x = values['OD280'], y = values['Alcohol'], hue=kmeans_wine.labels_)

Guía definitiva para la agrupación en clústeres de K-Means con Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Podemos ver grupos 0, 1y 2 en el gráfico. Con base en nuestro análisis, grupo 0 tiene vinos con mayor contenido proteico y menor alcohol, grupo 1 tiene vinos con mayor grado alcohólico y bajo contenido proteico, y grupo 2 tiene alto contenido de proteínas y alto contenido de alcohol en sus vinos.

Este es un conjunto de datos muy interesante y lo animo a profundizar en el análisis agrupando los datos después de la normalización y PCA, también interpretando los resultados y encontrando nuevas conexiones.

Conclusión

K-medias La agrupación en clústeres es un algoritmo de aprendizaje automático no supervisado simple pero muy efectivo para la agrupación de datos. Agrupa los datos en función de la distancia euclidiana entre los puntos de datos. El algoritmo de agrupamiento K-Means tiene muchos usos para agrupar documentos de texto, imágenes, videos y mucho más.

Sello de tiempo:

Mas de Abuso de pila