K-Means en Python paso a paso

K-Means es un algoritmo no supervisado de Clustering. Se utiliza cuando tenemos un montón de datos sin etiquetar. El objetivo de este algoritmo es el de encontrar “K” grupos (clusters) entre los datos crudos. En este artículo repasaremos sus conceptos básicos y veremos un ejemplo paso a paso en python que podemos descargar.

Cómo funciona K-Means

El algoritmo trabaja iterativamente para asignar a cada “punto” (las filas de nuestro conjunto de entrada forman una coordenada) uno de los “K” grupos basado en sus características. Son agrupados en base a la similitud de sus features (las columnas). Como resultado de ejecutar el algoritmo tendremos:

  • Los “centroids” de cada grupo que serán unas “coordenadas” de cada uno de los K conjuntos que se utilizarán para poder etiquetar nuevas muestras.
  • Etiquetas para el conjunto de datos de entrenamiento. Cada etiqueta perteneciente a uno de los K grupos formados.

Los grupos se van definiendo de manera “orgánica”, es decir que se va ajustando su posición en cada iteración del proceso, hasta que converge el algoritmo. Una vez hallados los centroids deberemos analizarlos para ver cuales son sus características únicas, frente a la de los otros grupos. Estos grupos son las etiquetas que genera el algoritmo.

Casos de Uso de K-Means

El algoritmo de Clustering K-means es usado uno de los más usados para encontrar grupos ocultos, o sospechados en teoría sobe un conjunto de datos no etiquetado. Esto puede servir para confirmar -o desterrar- alguna teoría que teníamos asumida de nuestros datos. Y también puede ayudarnos a descubrir relaciones asombrosas entre conjuntos de datos, que de manera manual, no hubiéramos reconocido. Una vez que el algoritmo ha ejecutado y obtenido las etiquetas, será fácil clasificar nuevos valores o muestras entre los grupos obtenidos.

Algunos casos de uso son:

  • Segmentación por Comportamiento: relacionar el carrito de compras de un usuario, sus tiempos de acción e información del perfil.
  • Categorización de Inventario: agrupar productos por actividad en sus ventas
  • Detectar anomalías o actividades sospechosas: según el comportamiento en una web reconocer un troll -o un bot- de un usuario normal

Aquí se listan las aplicaciones más frecuentes en Machine Learning

Datos de Entrada para K-Means

Las “features” o características que utilizaremos como entradas para aplicar el algoritmo k-means deberán ser de valores numéricos, continuos en lo posible. En caso de valores categóricos (por ej. Hombre/Mujer o Ciencia Ficción, Terror, Novela,etc) se puede intentar pasarlo a valor numérico, pero no es recomendable pues no hay una “distancia real” -como en el caso de géneros de película o libros-. Además es recomendable que los valores utilizados estén normalizados, manteniendo una misma escala. En algunos casos también funcionan mejor datos porcentuales en vez de absolutos. No conviene utilizar features que estén correlacionados o que sean escalares de otros. Recordar los 7 pasos para el Aprendizaje Automático.

El Algoritmo K-means

El algoritmo utiliza una proceso iterativo en el que se van ajustando los grupos para producir el resultado final. Para ejecutar el algoritmo deberemos pasar como entrada el conjunto de datos y un valor de K. El conjunto de datos serán las características o features para cada punto. Las posiciones iniciales de los K centroids serán asignadas de manera aleatoria de cualquier punto del conjunto de datos de entrada. Luego se itera en dos pasos:

1- Paso de Asignación de datos

En este paso, cada “fila” de nuestro conjunto de datos se asigna al centroide más cercano basado en la distancia cuadrada Euclideana. Se utiliza la siguiente fórmula (donde dist() es la distancia Euclideana standard):

2-Paso de actualización de Centroid

En este paso los centroid de cada grupo son recalculados. Esto se hace tomando una media de todos los puntos asignados en el paso anterior.

El algoritmo itera entre estos pasos hasta cumplir un criterio de detención:
*  si no hay cambios en los puntos asignados a los grupos,
* o si la suma de las distancias se minimiza,
* o se alcanza un número máximo de iteraciones.

El algoritmo converge a un resultado que puede ser el óptimo local, por lo que será conveniente volver a ejecutar más de una vez con puntos iniciales aleatorios para confirmar si hay una salida mejor. Recuerden siempre seguir los 7 pasos para construir IA

Elegir el valor de K

Este algoritmo funciona pre-seleccionando un valor de K. Para encontrar el número de clusters en los datos, deberemos ejecutar el algoritmo para un rango de valores K, ver los resultados y comparar características de los grupos obtenidos. En general no hay un modo exacto de determinar el valor K, pero se puede estimar con aceptable precisión siguiendo la siguiente técnica:

Una de las métricas usada para comparar resultados es la distancia media entre los puntos de datos y su centroid. Como el valor de la media diminuirá a medida de aumentemos el valor de K, deberemos utilizar la distancia media al centroide en función de K y entontrar el “punto codo”, donde la tasa de descenso se “afila”. Aquí vemos una gráfica a modo de ejemplo:

Un ejemplo K-Means en Python con Sklearn

Como ejemplo utilizaremos de entradas un conjunto de datos que obtuve de un proyecto propio, en el que se analizaban rasgos de la personalidad de usuarios de Twitter. He filtrado a 140 “famosos” del mundo en diferentes areas: deporte, cantantes, actores, etc. Basado en una metodología de psicología conocida como “Ocean: The Big Five” tendemos como características de entrada:

  • usuario (el nombre en Twitter)
  • “op” = Openness to experience – grado de apertura mental a nuevas experiencias, curiosidad, arte
  • “co” =Conscientiousness – grado de orden, prolijidad, organización
  • “ex” = Extraversion – grado de timidez, solitario o participación ante el grupo social
  • “ag” = Agreeableness – grado de empatía con los demás, temperamento
  • “ne” = Neuroticism, – grado de neuroticismo, nervioso, irritabilidad, seguridad en sí mismo.
  • Wordcount – Cantidad promedio de palabras usadas en sus tweets
  • Categoria – Actividad laboral del usuario (actor, cantante, etc.)

Utilizaremos el algoritmo K-means para que agrupe estos usuarios -no por su actividad laboral- si no, por sus similitudes en la personalidad. Si bien tenemos 8 columnas de entrada, sólo utilizaremos 3 en este ejemplo, de modo que podamos ver en un gráfico tridimensional -y sus proyecciones a 2D- los grupos resultantes. Pero para casos reales, podemos utilizar todas las dimensiones que necesitemos. Una de las hipótesis que podríamos tener es: “Todos los cantantes tendrán personalidad parecida” (y así con cada rubro laboral). Pues veremos si lo probamos, o por el contrario, los grupos no están relacionados necesariamente con la actividad de estas Celebridades.

Requerimientos para el Ejercicio

Necesitaremos tener Python 2.7 o 3.5+. Mejor si tenemos instalada una suite como Anaconda o Canopy (que funcionan en Windows, Mac y Linux). Puedes seguir este tutorial donde explico cómo instalar tu ambiente de desarrollo. Crearemos un Jupiter notebook para seguir paso a paso el ejercicio e importaremos un archivo de entrada csv. Utilizaremos los paquetes scikit-learn, pandas, matplotlib  y numpy.

Agrupar usuarios Twitter de acuerdo a su personalidad con K-means

Implementando K-means en Python con Sklearn

Comenzaremos importando las librerías que nos asistirán para ejecutar el algoritmo y graficar.

Importamos el archivo csv -para simplificar, suponemos que el archivo se encuentra en el mismo directorio que el notebook- y vemos los primeros 5 registros del archivo tabulados.

También podemos ver una tabla de información estadística que nos provee Pandas dataframe:

El archivo contiene diferenciadas 9 categorías -actividades laborales- que son:

  1. Actor/actriz
  2. Cantante
  3. Modelo
  4. Tv, series
  5. Radio
  6. Tecnología
  7. Deportes
  8. Politica
  9. Escritor

Para saber cuantos registros tenemos de cada uno hacemos:

Como vemos tenemos 34 cantantes, 27 actores, 17 deportistas, 16 políticos,etc.

Visualización de Datos

Veremos graficamente nuestros datos para tener una idea de la dispersión de los mismos:

En este caso seleccionamos 3 dimensiones: op, ex y ag y las cruzamos para ver si nos dan alguna pista de su agrupación y la relación con sus categorías.

Revisando la gráfica no pareciera que haa algún tipo de agrupación o correlación entre los usuarios y sus categorías.

Definimos la entrada

Concretamos la estructura de datos que utilizaremos para alimentar el algoritmo. Como se ve, sólo cargamos las columnas op, ex y ag en nuestra variable X.

(140,3)

Ahora veremos una gráfica en 3D con 9 colores representando las categorías.

Veremos si con K-means, podemos “pintar” esta misma gráfica de otra manera, con clusters diferenciados.

Obtener el valor K

Vamos a hallar el valor de K haciendo una gráfica e intentando hallar el “punto de codo” que comentábamos antes. Este es nuestro resultado:

 

Realmente la curva es bastante “suave”. Considero a 5 como un buen número para K. Según vuestro criterio podría ser otro.

Ejecutamos K-Means

Ejecutamos el algoritmo para 5 clusters y obtenemos las etiquetas y los centroids.

Ahora veremos esto en una gráfica 3D con colores para los grupos y veremos si se diferencian: (las estrellas marcan el centro de cada cluster)

Aqui podemos ver que el Algoritmo de K-Means con K=5 ha agrupado a los 140 usuarios Twitter por su personalidad, teniendo en cuenta las 3 dimensiones que utilizamos: Openess, Extraversion y Agreeablenes. Pareciera que no hay necesariamente una relación en los grupos con sus actividades de Celebrity.

Haremos 3 gráficas en 2 dimensiones con las proyecciones a partir de nuestra gráfica 3D para que nos ayude a visualizar los grupos y su clasificación:

En estas gráficas vemos que están bastante bien diferenciados los grupos.

Podemos ver cada uno de los clusters cuantos usuarios tiene:

Y podemos ver la diversidad en rubros laborales de cada uno. Por ejemplo en el grupo 0 (rojo), vemos que hay de todas las actividades laborales aunque predominan de actividad 1 y 2 correspondiente a Actores y Cantantes con 11 y 15 famosos.

De categoría 3 “modelos” hay 6 sobre un total de 9.

Buscaremos los usuarios que están más cerca a los centroids de cada grupo que podríamos decir que tienen los rasgos de personalidad característicos que representan a cada cluster:

array([21, 107, 82, 80, 91]) #posicion en el array de usuarios

carmenelectra
Pablo_Iglesias_
JudgeJudy
JPVarsky
kobebryant

En los centros vemos que tenemos una modelo, un político, presentadora de Tv, locutor de Radio y un deportista.

Clasificar nuevas muestras

Y finalmente podemos agrupar y etiquetar nuevos usuarios twitter con sus características y clasificarlos. Vemos el ejemplo con el usuario de David Guetta y nos devuelve que pertenece al grupo 1 (verde).

[1]

Conclusiones

El algoritmo de K-means nos ayudará a crear clusters cuando tengamos grandes grupos de datos sin etiquetar, cuando queramos intentar descubrir nuevas relaciones entre features o para probar o declinar hipótesis que tengamos de nuestro negocio.

Atención: Puede haber casos en los que no existan grupos naturales, o clusters que contengan una verdadera razón de ser. Si bien K-means siempre nos brindará “k clusters”, quedará en nuestro criterio reconocer la utilidad de los mismos o bien revisar nuestras features y descartar las que no sirven o conseguir nuevas. También tener en cuenta que en este ejemplo estamos utilizando como medida de similitud entre features la distancia Euclideana pero podemos utilizar otras diversas funciones que podrían arrojar mejores resultados (como Manhattan, Lavenshtein, Mahalanobis, etc).

Hemos visto una descripción del algoritmo, aplicaciones y un ejemplo python paso a paso, que podrán descargar también desde los siguientes enlaces:

Si aún no viste el ejercicio de Regresión Logística paso a paso  ó Arbol de decisión puedes leerlos en español y seguir practicando

Los invito a escribirme sus comentarios al respecto y si tienen dudas o inconvenientes con el ejercicio. También pueden suscribirse al blog en donde intentaré escribir artículos de interés y aprendizaje de Machine Learning.

Suscribirme al Blog Aprende Machine Learning

El próximo artículo quincenal sobre Machine Learning te llegará al email para continuar estudiando!.

 

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardar

GuardarGuardarGuardarGuardarGuardarGuardar

13 Replies to “K-Means en Python paso a paso”

  1. ¡Muy interesante Juan!
    El ejemplo práctico de los famosos que muestran rasgos comunes en sus personalidades es genial.
    Me iría bien que explicaras de forma sencilla cómo instalar y configurar el entorno de desarrollo y cómo trabajar con él.
    ¡Un abrazo!

    1. Hola David, muchas gracias, siempre da ánimos que guste el artículo que tanto cuesta escribir! Aún te debo una pregunta anterior, mil disculpas!!!. Voy a intentar escribir un artículo tutorial sobre instalar el ambiente de desarrollo con Python y Anaconda -que es el más popular- y sirve para Windows, Mac, Linux y permite crear Jupyter Notebooks muy fácilmente. Ya tengo dos deudas contigo! Abrazo y felicitaciones también por tus proyectos, tu nueva web, muy buena!

  2. Hola Juan!
    No hay deudas pendientes, no te preocupes.
    Me alegra que hayas mostrado interés por mis proyectos y que le hayas echado un vistazo a mi Portfolio.
    Ahora mismo estoy metido en un proyecto de visualización 3D. He dejado un poco de lado el deep learning, pues me dió la sensación de que faltaba aún mucho por investigar. Aunque sigo teniendo interés por el tema y cómo evoluciona. Por otro lado, también tengo interés por la robótica y me he creado mi propio robot. Ahora mismo, estoy en la fase de añadir sensores al robot y que éste reaccione a los eventos.
    Como ves estoy con muchas cosas.
    ¡Un abrazo Juan!

    1. Que bueno David!, me da curiosidad sobre tu robot. ¿En que lo estás haciendo? con Arduino? Raspberry pi? Saludos y seguimos en contacto!

  3. ¡Hola Juan!
    El robot es de la marca Allbot y yo he optado por la placa Arduino.
    Me he descargado softwares por internet y, de momento, sólo mueve los 8 servos, pero quería añadir sensores de luz y de audio.
    ¡Un abrazo Juan!

  4. Hola juan muchas gracias por el articulo sin duda me ah servido mucho en mi estudio de machine learning sin duda alguna, uno de los mejores artículos que eh visto en mi vida gracias por el aporte y espero que siga adelante con este maravilloso trabajo.

    1. Hola Jared, muchas gracias a ti por el comentario! Me da mucho ánimo para seguir escribiendo nuevos artículos. Si todo va bien, publicaré uno la semana que viene. Me alegra mucho saber que te ha ayudado mi post!. Espero que sigamos en contacto ya que me interesa mucho vuestra opinión o si tiene alguna inquietud en particular que pueda ayudar a resolver. Saludos!

    1. Muchas gracias Canvas, espero te gusten los otros ejemplos de los demás algoritmos. Intento que sean originales. Saludos

  5. Estimado Juan

    Me pareció excelente tu articulo y me dio una idea practica de como aplicar esto en mi trabajo, ahora eso si tengo la duda en los últimos comandos que aplicaste tipo consulta. Me podría indicar como seria el código mas menos para ver en un listado todos los usuarios en forma ascendente, no solamente el que esta mas cerca del correspondiente centroide.

    Saludos

  6. Hola Osvaldo, gracias por escribir y comentar, y me alegra que te sirva el artículo para aplicar en tu trabajo. Si bien no aparece como listar a los usuarios de cada cluster en el artículo, en el Jupyter Notebook sí que aparece.
    El código es el siguiente:

    #miramos los usuarios del grupo 0
    for index, row in copy.iterrows():
      if row["label"] == 0:
      print (row["usuario"], row["categoria"],row["label"])

    Obviamente podrías iterar los 5 grupos de 0 a 4.
    Espero que te sirva! Saludos y espero sigas visitando el Blog.

  7. Estimado Juan

    Gracias por la pronta respuesta, me costo un poco la lógica de la programación, pero lo pude entender y aplicar que es lo que me interesa.

    Eso si leyendo el código me encontré con la variable “group_referrer_index”
    revisando por separado en la consola jupyter salia lo siguiente :

    0 True
    1 True
    2 False
    3 True
    4 True
    5 False
    6 False
    7 True

    107 True
    108 False
    109 False
    110 True
    111 False
    Name: label, Length: 112, dtype: bool

    Por lo que entendi compara copy[‘label’] ==1 con los valores de categoría y indicando que si es verdadero o falso.
    Si tuvieras tiempo para explicar ese tema ya que no me interesa ser un mero copiador de códigos jaaj…

    1. Osvaldo, te comento esa parte del código:
      Lo que hace es comparar con una de los clusters, (por ejemplo con la 1 si pones copy[‘label’] ==1) y Pandas devuelve un array con true y false en cada una de las 112 filas indicando si esa fila pertenece a cluster 1 true o False (es el listado que copiaste en tu mensaje).
      Luego, en la siguiente linea hace:

      group_referrals = copy[group_referrer_index]

      Con lo cual filtra de todas las filas solamente las que estén en True, es decir, la del cluster 1 y se lo asigna a la variable group_referals. En el ejemplo de arriba, de las 112 filas deberían quedar 33.

      Espero que te ayude esa explicación!.
      Saludos y lo que necesites, me escribes!

Leave a Reply