Anteriormente escribí sobre las redes neuronales (click aca para verlo). Las redes neuronales y todos los otros «métodos supervisados» son utilizados cuando posee una muestra de valores predecir, pero cuando sabes lo que quieres lograr, pero no tienes una muestra del valor a predecir, se utilizan los llamados «métodos no supervisados»
Un clásico problema donde se aplica esta clase de métodos es en la Segmentación de Clientes, donde a priori no se conocen los segmentos/grupos, dentro de los métodos, uno de los más famosos es K-Means.
K-Means es un algoritmo utilizado para encontrar grupos de individuos con características similares. Donde similar o distinto, será calculado según la distancia euclidiana de sus atributos numéricos.
A continuación seguiremos un ejemplo paso a paso sobre como segmentar clientes en un caso simplificado.
Para hacer este ejemplo, generaremos una muestra aleatoria de datos en dos dimensiones por caso: trafico de datos (megas) y de voz (minutos). Cada caso ha sido simulado de modo que tengan un patrón de comportamiento similar a un grupo.
Con K-Means intentaremos encontrar estos cuatro grupos, los cuales existen, pero no los conocemos.
A continuación un gráfico de los cuatro grupos:
Problema Real:
Somos el Data Scientist de una prestigiosa compañía de Celulares (experiencia personal del escritor) donde se nos encomienda la tarea de segmentar/clasificar a los clientes (nuevamente algo nada alejado de la realidad del escritor). Al revisar la base de datos, nos damos cuenta que solo disponemos de los consumos mensuales de Datos y Voz de cada cliente. (pueden ser muchos mas como: recargas, mensajes de texto llamadas al call center, etc…).
Como las escalas de consumo de datos (MB) y Voz (Minutos) son muy distintas y K-Means mide la similitud por distancia euclidiana entre casos, escalaremos los valores entre 0 y 1, obteniendo los siguientes datos:
Ya estamos listos para comenzar, como K-Means no determina el número de grupos, se ejecuta para distintas cantidades procediendo a comparar los resultados de cada caso. Las elección del número de grupos se mueve entre las matemáticas y el criterio.
Realizaremos K-Means desde 1 a 6 grupos y utilizaremos el método matemático y el método de «criterio» para determinar el numero de grupos.
Lo primero observar es ver el nivel de ajuste para cada caso, este consiste en el porcentaje de varianza explicado por cada segmentación, calculado como between_SS / total_SS (no quiero entrar en detalle). Cuando se ve que la segmentación ya no mejora considerablemente al incrementar los grupos, significa que el grupo nuevo grupo es similar a uno ya existente, por lo que deberían el mismo.
A continuación el gráfico de ajuste para cada caso.
Al parecer, más de 4 grupos no hace sentido, ahora comparemos los valores agregados de cada grupo, veremos sus valores promedio y el numero de elementos en cada grupo.
Ahora procederemos a realizar el análisis no numérico, el cual consiste en darle nombre a los grupos, cuando no se pueden diferenciar 2 grupos, significa que no tiene sentido separarlos (solo por curiosidad, los contrastaremos con los grupos «reales»).
1 Grupo
grupo_numero | min | mb | numero |
---|---|---|---|
1) Promedio de todos | 71 | 447 | 120 |
2 Grupos
grupo_numero | min | mb | numero |
---|---|---|---|
1) Poco Minutos | 9 | 538 | 60 |
2) Muchos Minutos | 134 | 356 | 60 |
3 Grupos
grupo_numero | min | mb | numero |
---|---|---|---|
1) Poco Trafico | 13 | 111 | 31 |
2) Muchos Minutos | 134 | 356 | 60 |
3) Muchos Megas y pocos Minutos | 5 | 994 | 29 |
4 Grupos
grupo_numero | min | mb | numero |
---|---|---|---|
1) Muchos Megas | 5 | 994 | 29 |
2) Muchos Minutos | 148 | 23 | 30 |
3) Poco Trafico | 13 | 111 | 31 |
4)Mucho Trafico | 120 | 690 | 30 |
5 Grupos
grupo_numero | min | mb | numero |
---|---|---|---|
1) Alto Trafico | 111 | 699 | 22 |
2) Alto Trafico, en especial minutos* | 143 | 666 | 8 |
3)Muchos Megas | 5 | 994 | 29 |
4)Muchos Minutos | 148 | 23 | 30 |
5) Poco Trafico | 13 | 111 | 31 |
- El grupo 1 y 2 son muy similares y el grupo 2 son muy pocos clientes, no tiene sentido separarlos.
6 Grupos
grupo_numero | min | mb | numero |
---|---|---|---|
1) Alto consumo Minutos | 148 | 23 | 30 |
2) Altísimo consumo Megas | 3 | 1172 | 10 |
3) Bajo Consumo, un poco más de Megas | 9 | 288 | 10 |
4) Alto Consumo de Megas | 6 | 917 | 18 |
5) Bajo Consumo | 13 | 51 | 22 |
6) Alto Consumo | 120 | 690 | 30 |
- El grupo 1,2 y 4 son muy similares, basicamente caracterisados por clientes que utilizan megas pero muy poca voz.
Por ende existen 4 grupos, a los cuales les daremos nombres:
grupo_numero | min | mb | numero |
---|---|---|---|
Usuario de Megas | 5 | 994 | 29 |
Usuario de Minutos | 148 | 23 | 30 |
Bajo Consumo | 13 | 111 | 31 |
Alto Consumo | 120 | 690 | 30 |
Ahora que ya tenemos segmentación, comparemos los datos iniciales con los obtenidos, en el siguiente gráfico, en el color se representa el grupo encontrado por K-Means y en la forma del punto el grupo original al que correspondía el cliente (según datos generados):
Efectivamente K-Means detectó casi todos los grupos generados inicialmente.
Un corolario, así es como una operadora movil re definió sus productos, nos dimos cuenta de que la competencia tenia productos que apuntaban a los segmentos de alto consymo y bajo consumo, mientras que nosotros nos dimos cuenta que teníamos clientes que utilizaban principalmente Datos o Voz, por lo que decidimos focalizarnos en este segmento que no tenía competencia.
Si les gustó este articulo, los invito a leer sobre:
Saludos!
Si te gustó, síguenos en cualquiera de nuestros medios, allí aparecerán todas las publicaciones.
Y no olvides compartir en tus RRSS, vuestras visitas son mi motivación.
Anexo: El código R con el que se hicieron los analisis:
set.seed(1984) library(ggplot2) library(plyr) library(xtable) #Generar Muestra muestra = rbind( data.frame(min = rnorm(30,10,10), mb = rnorm(30,100,100),grupo = "bajo"), #Clientes con consumo promedio data.frame(min = rnorm(30,120,20), mb = rnorm(30,700,100),grupo = "alto"), #Clientes con consumo promedio data.frame(min = rnorm(30,3,10), mb = rnorm(30,1000,200), grupo = "datos"), #Clientes con consumo alto en datos data.frame(min = rnorm(30,150,20), mb = rnorm(30,15,60), grupo = "voz") #Clientes con consumo alto en voz ) muestra[,1:2] = apply(muestra[,1:2],2,function(x) ifelse(x<0,0,x)) qplot(min,mb,data=muestra,xlab = "Minutos Mensuales", ylab = "MB Mensuales",color = grupo) #Normalización de datos muestra = transform(muestra,n_min = min/max(min), n_mb = mb/max(mb)) qplot(n_min,n_mb,data=muestra,xlab = "Minutos Mensuales Normalizados", ylab = "MB Mensuales Normalizados") #Ejecutar el modelo para los 6 casos codo = data.frame() set.seed(2016) for(grupos in 1:6){ modelo = kmeans(muestra[,4:5],grupos,iter.max = 100) codo = rbind(codo, data.frame(grupos = grupos, between_SS = modelo$betweenss, total_ss = modelo$totss, tot.withinss = modelo$tot.withinss, value = modelo$betweenss/modelo$totss) ) muestra[,paste0("kmeans_",grupos)] = as.character(modelo$cluster) } #Grafico del nivel de ajuste qplot(x = grupos, y = value, data = codo,geom="line", ylab = "Procentaje de Ajuste", xlab = "Numero de grupos") # resumen para cada modelo resumen = data.frame() for(n in 1:6){ tabla = ddply(muestra,paste0("kmeans_",n),function(x) data.frame(min = mean(x$min),mb = mean(x$mb), numero = nrow(x)) ) colnames(tabla)[1] = "grupo_numero" resumen = rbind(resumen, data.frame(numero_de_grupos = n, tabla) ) print(xtable(tabla,digits = 0),type="HTML",include.rownames=FALSE) } print(xtable(resumen,digits = 0),type="HTML",include.rownames=FALSE) #Grafico de cada grupo qplot(min,mb,data=muestra,xlab = "Minutos Mensuales", ylab = "MB Mensuales",color = kmeans_6,shape = grupo) )