Usamos cookies. Tienes opciones. Las cookies nos ayudan a mantener el sitio funcionando sin problemas e informar sobre nuestra publicidad, pero si deseas realizar ajustes, puedes visitar nuestro Aviso de cookies para más información.
Utilizamos cookies propias y de terceros para analizar su actividad en el sitio web con el objetivo de enviarle publicidad personalizada y mejorar el funcionamiento de la web. Puedes aceptar todas las cookies pulsando el botón “ACEPTAR” o seleccionarlas en función de su funcionalidad pulsando el botón “AJUSTES”.
×

BigQuery ML: Segmentación usando K-means clustering

El objetivo de este post es ayudar a los usuarios de BigQuery a utilizar BigQuery Machine Learning (BigQuery ML) con el fin de realizar una segmentación en sus datos utilizando el algoritmo K-means.

Dentro de Google Cloud Platform destacamos BigQuery por su uso en el tratamiento de grandes volúmenes de datos. BigQuery nos permite realizar análisis interactivos de nuestros datasets a través de sencillas consultas SQL pero, además, por la integración de BigQuery Machine Learning, la herramienta es capaz de crear y ejecutar modelos de aprendizaje automático de una manera tan simple como con una query de SQL estándar desde la misma consola.

Si bien es cierto que la capacidad de realizar modelos en BigQuery ML es todavía limitada, se pueden realizar con rapidez regresiones lineales, regresiones logísticas (binomial o multinomial) y análisis clustering o de conglomerados. Este último es el que nos interesa por su posible uso para cualquier tipo de segmentación, como podría ser el caso de una segmentación de audiencias.

El algoritmo implementado en BigQuery ML es el conocido como K-means o de las K-medias (MacQueen,1967), cuyo objetivo sería encontrar segmentos homogéneos en población que se compongan de individuos con comportamientos diferentes con respecto a otros grupos teniendo en cuenta una distancia. Para esto, el número K de grupos debe estar pre-definido. El algoritmo funcionaría de la siguiente manera:

  1. Se elige un número aleatorio de clústeres.
  2. Se seleccionan aleatoriamente k observaciones como centroides de los K clústeres.
  3. Se asigna cada observación a su centroide más próximo en función de la distancia empleada.
  4. Para cada clúster se recalcula su centroide.
  5. Se repiten los pasos 3 y 4 hasta que las asignaciones no cambien o se logre el máximo de iteraciones acordado.

Para realizar este ejemplo utilizaré mi propio proyecto de pruebas y los datos los extraeré del dataset público bigquery-public-data, concretamente de la tabla bigquery-public-data:ml_datasets.census_adult_income, que contiene datos sobre características socioeconómicas de 32.561 adultos. Se ha de tener en cuenta que el dataset donde se va a realizar el modelo debe estar creado en la misma ubicación que los datos de origen; en mi caso, por tanto, será USA.

En el siguiente paso es la creación del modelo. Se realizará una consulta donde se cree un modelo en el dataset que se acaba de elaborar, de modo que se utilice la función CREATE OR REPLACE MODEL ‘*dataset*.*modelo_creado*’. Así se localizará el modelo dentro del dataset como si de una tabla de BigQuery se tratase. Se han de elegir como opciones (OPTIONS) ‘kmeans’ ‘num_clusters’=X, ‘standardize_features’ = TRUE y ‘distance_type’=’euclidean’, para elegir el número de centroides, estadanarizar los valores y elegir el tipo de distancia como euclídea. Existen otras opciones como KMEANS_INIT_METHOD o KMEANS_INIT_COL que establecerían un punto de referencia al algoritmo. Después se seleccionarán las variables que se necesitarán para el modelo. Si existiera alguna variable sobre la que se quisieran hacer los grupos, como un user_id, sería exceptuada mediante el comando EXCEPT(), pero no sucede eso en este caso.

  1. CREATE OR REPLACE MODEL
  2.  
  3. bqml_pruebas.adult_income_4
  4.  
  5. OPTIONS
  6.  
  7. (model_type='kmeans',
  8.  
  9. num_clusters=4,
  10.  
  11. standardize_features = TRUE,
  12.  
  13. distance_type= 'euclidean') AS
  14.  
  15. SELECT *
  16.  
  17. FROM `bigquery-public-data.ml_datasets.census_adult_income`

Para poder elegir el número óptimo de clusters se precisa realizar varios modelos con diferentes números de cluster y después comparar ambos con el método del codo o elbow method. Una vez hayamos ejecutado los distintos, podemos compararlos con la siguiente consulta:

  1. SELECT *
  2.  
  3. FROM
  4.  
  5. (SELECT
  6.  
  7. '2' AS Size,
  8.  
  9. *
  10.  
  11. FROM
  12.  
  13. ML.EVALUATE(MODEL `pruebas-jaime-235311.bqml_pruebas.adult_income_2`)
  14.  
  15. UNION ALL
  16.  
  17. SELECT
  18.  
  19. '3' AS Size,
  20.  
  21. *
  22.  
  23. FROM
  24.  
  25. ML.EVALUATE(MODEL `pruebas-jaime-235311.bqml_pruebas.adult_income_3`)
  26.  
  27. UNION ALL
  28.  
  29. SELECT
  30.  
  31. '4' AS Size,
  32.  
  33. *
  34.  
  35. FROM
  36.  
  37. ML.EVALUATE(MODEL `pruebas-jaime-235311.bqml_pruebas.adult_income_4`)
  38.  
  39. UNION ALL
  40.  
  41. (…)
  42.  
  43. )
  44.  
  45. ORDER BY 1 ASC

Cuando la consulta nos muestre resultados, podemos pasar los datos a DataStudio con ‘EXPLORAR DATOS’, para ahí buscar el codo mediante un gráfico de líneas con los resultados de mean_squared_distance. Según los resultados el modelo a seguir será el cluster con 4 centroides como se había planteado inicialmente.

El paso que sigue es la exploración del modelo. Dentro del dataset creado para los modelos, se encontrará el modelo concreto como si de una tabla se tratase y en la parte de evaluación tendremos numerosa información sobre el modelo, a saber: las métricas, las variables numéricas y las variables categóricas.

En el apartado Atributos numéricos se muestran las características del centroide, o representante del grupo, para cada una de las variables numéricas. Estas características representan al grupo en su conjunto. Además, también muestra el tamaño del grupo con la variable Cantidad.

Big query 1

En el apartado Atributos categóricos podemos observar cómo se comporta cada grupo con respecto a las diferentes variables categóricas incluidas en el modelo. Así, podemos ver cómo los clusters 3 y 4 se componen mayoritariamente por hombres y que los grupos 1 y 2 están compuestos en su mayoría por never-married.

Big query 2

3

A veces en la parte de Atributos numéricos no aparecen todos los existentes en el modelo, por lo que otra opción para extraer los datos de los centroides de las variables numéricas sería mediante una consulta al modelo para después exportar los datos a DataStudio y poder trabajar allí con ellos. La función ML.CENTROIDS() extraerá los centroides de las variables.

  1. SELECT
  2.  
  3. *
  4.  
  5. FROM
  6.  
  7. ML.CENTROIDS(MODEL bqml_pruebas.adult_income_4)
  8.  
  9. ORDER BY
  10.  
  11. centroid_id

Sin embargo, esta función nos muestra los datos de forma anidada, por lo que se procederá a realizar un desanidado de los datos creando una variable (T) formada por los centroides y los clusters de la que se extraerán los resultados para cada variable.

  1. WITH
  2.  
  3. T AS (
  4.  
  5. SELECT
  6.  
  7. centroid_id,
  8.  
  9. ARRAY_AGG(STRUCT(feature AS name,
  10.  
  11. ROUND(numerical_value,1) AS value)
  12.  
  13. ORDER BY
  14.  
  15. centroid_id) AS cluster
  16.  
  17. FROM
  18.  
  19. ML.CENTROIDS(MODEL bqml_pruebas.adult_income_4)
  20.  
  21. GROUP BY
  22.  
  23. centroid_id )
  24.  
  25. SELECT
  26.  
  27. CONCAT('Cluster#', CAST(centroid_id AS STRING)) AS centroid,
  28.  
  29. (
  30.  
  31. SELECT
  32.  
  33. value
  34.  
  35. FROM
  36.  
  37. UNNEST(cluster)
  38.  
  39. WHERE
  40.  
  41. name = 'age') AS age,
  42.  
  43. (
  44.  
  45. SELECT
  46.  
  47. value
  48.  
  49. FROM
  50.  
  51. UNNEST(cluster)
  52.  
  53. WHERE
  54.  
  55. name = 'education_num') AS education_num,
  56.  
  57. (
  58.  
  59. SELECT
  60.  
  61. value
  62.  
  63. FROM
  64.  
  65. UNNEST(cluster)
  66.  
  67. WHERE
  68.  
  69. name = 'capital_gain') AS capital_gain,
  70.  
  71. (
  72.  
  73. SELECT
  74.  
  75. value
  76.  
  77. FROM
  78.  
  79. UNNEST(cluster)
  80.  
  81. WHERE
  82.  
  83. name = 'capital_loss') AS capital_loss,
  84.  
  85. (
  86.  
  87. SELECT
  88.  
  89. value
  90.  
  91. FROM
  92.  
  93. UNNEST(cluster)
  94.  
  95. WHERE
  96.  
  97. name = 'hours_per_week') AS hours_per_week,
  98.  
  99.  
  100.  
  101. FROM
  102.  
  103. T
  104.  
  105. ORDER BY 1 ASC

Si exploramos los resultados mediante Google Data Studio podemos utilizarlos para realizar diferentes comparaciones entre los centroides, como se muestra a continuación usando un mapa de calor:

Big query 4

Finalmente, se realiza la asignación de los clusters a los datos originales. Para esto se seleccionan los datos de la tabla original y los clusters y se unirán. En el caso de haber sido usuarios identificados mediante un ID, la clave de unión será ese ID.

  1. SELECT
  2.  
  3. Data.*,
  4.  
  5.  
  6.  
  7. Clusters.CENTROID_ID
  8.  
  9. FROM
  10.  
  11. `bigquery-public-data.ml_datasets.census_adult_income` AS Data,
  12.  
  13. ML.PREDICT(MODEL bqml_pruebas.adult_income_4, TABLE `bigquery-public-data.ml_datasets.census_adult_income`) AS Clusters

Una vez hecho esto, podemos comprobar cómo se comportan los distintos grupos si tenemos algunas variables no incluidas en el modelo. Si en este análisis se hubiera utilizado como variable exceptuada algún ID (como user_id), mediante distintos matcheos podríamos comprobar cómo se comportan los usuarios y los grupos incluso en periodos siguientes al estudio. K-means es útil para lograr una buena segmentación de los usuarios, y en última instancia nos ayudaría con la siguiente labor de activación.

 

 

En nuestra compañía