Analítica web
Reflexiones desde el mercado español de Analítica Web

Primeros pasos en sistemas de recomendación

Se lee en 5 minutos

(Re)introducción

Recientemente, mi compañera Suni escribió unas primeras pinceladas sobre quiénes y de qué manera usan sistemas de recomendación. En su post menciona diferentes métodos para calcular estas predicciones, de los cuales nosotros vamos a emplear el filtrado colaborativo.

Un enfoque mixto, como el que tiene Spotify con sus playlist diarias, posiblemente sería el más acertado, detectando, por ejemplo, cuál es el tema más interesante para ese usuario y haciendo las recomendaciones sobre ese tema (filtrado basado en contenido + filtrado colaborativo). Posteriormente podrían añadirse reglas para ponderar estas recomendaciones basadas en aspectos demográficos (filtrado basado en reglas), pero, en principio, el propósito de este ejercicio es demostrar la implementación de una arquitectura funcional que cumpla el propósito de la recomendación de la manera más comprensible.

Hace algún tiempo que nuestro equipo encontró a su vez esta solución recomendada por Google para realizar este tipo de predicción sobre su arquitectura: Google Cloud Platform (GCP). En parte a raíz de ese artículo, en parte por la necesidad de ponernos en forma a la hora de desplegar servicios en la Cloud, y en parte por pura curiosidad del equipo, empujamos este proyecto hasta llevarlo a puerto.

Recolección

¿Así que estás decidido a hacer recomendaciones?, ¿sobre qué?

Una buena forma de optimizar las vistas a nuestro blog, y a su vez presentar contenido más relevante a nuestros lectores, podría ser recomendar artículos ya publicados. Además, podemos saber si a un usuario le ha enganchado un artículo si termina de leerlo, así que cada vez que se lee un artículo recogemos la siguiente información:

  • Lector (id): identificador que nos permita separar las lecturas de un usuario, de las de los demás.
  • % de lectura (rating): en función de si le gusta o no, el usuario abandonará el artículo o lo terminará.
  • Artículo: (URL): identificador de este artículo.

Almacenaremos esta información en una base de datos para luego calcular la recomendación.

Nota: en este caso hemos optado por desarrollar una recolección personalizada, pero el mismo dato podría extraerse de una implementación de analítica, aunque efectos similares se podrían haber conseguido utilizando el tiempo en página como rating, una valoración directa del artículo, el número de comentarios, etc.

arquitectura del recomendador
Figura 1: Diagrama de la arquitectura del recomendador empleando módulos de GCP.

En nuestro caso, como estamos realizando este ejercicio empleando GCP, recogemos los datos valiéndonos de Cloud Functions y los insertamos en una base de datos Cloud SQL. Para no distraer de la narrativa, pondré a disposición del lector la función de recolección e inserción de la base de datos en lugar de insertarlo aquí.

diagrama entidad relación
Figura 2: Diagrama entidad-relación de la base de datos para almacenar la información relacionada con las predicciones basadas en vistas de artículos.

De acuerdo con la Figura 2, que explica el diagrama entidad-relación de nuestra base de datos, tendremos dos tablas principales, una para los datos proporcionados por la capa de recolección y otra para los calculados por nuestro algoritmo de recomendación. Además, tendremos dos tablas para traducir los identificadores de usuario y de post en algo manejable por el algoritmo (la librería que emplearemos nos obligará a utilizar índices naturales para representar a cada usuario y cada producto a recomendar).

Predicción

A la hora de ejecutar el algoritmo predictivo, necesitaremos transformar los datos que hemos extraído en algo que pueda manejar el algoritmo de predicción. Como comentábamos antes, tenemos dos tablas de traducción de identificadores de usuario y producto en índices.

Partiendo del dato recuperado que podemos ver en la tabla 1, tendremos un dato traducido como en la tabla 2.

visitorId url rating
015e7e6…3d08100408 http://www.analiticawe…-para-ser-mejor-analista/ 25
015e7f1…3d06a0086e http://www.analiticawe…-para-ser-mejor-analista/ 0
015e80d…3d06a0086e http://www.analiticawe…-para-ser-mejor-analista/ 100
015e810…3d06a00ac2 http://www.analiticawe…-para-ser-mejor-analista/ 50
015e814…3d06b008a0 http://www.analiticawe…-para-ser-mejor-analista/ 25
015fac9…190700086e http://www.divisadero….po-de-datos-estas-usando/ 75
015f528…1c06b0086e http://www.divisadero….po-de-datos-estas-usando/ 75
0160571…4506a0086e http://www.divisadero….po-de-datos-estas-usando/ 50
0160894…4506a0086e http://www.divisadero….po-de-datos-estas-usando/ 50
015f2a0…1906b0086e http://www.divisadero….iva-sistema-recomendacion 50
015ffec…1900d0086e http://www.divisadero….iva-sistema-recomendacion 50
0160040…4208a0093c http://www.divisadero….iva-sistema-recomendacion 0
016007d…5700d007e8 http://www.divisadero….iva-sistema-recomendacion 25

Tabla 1: Tabla con los IDs de usuario e identificadores del producto (en nuestro caso la URL) sin indexar.

userId postId rating
323452 234 25
532342 234 0
421254 234 100
655343 234 50
367561 234 25
345323 121 75
432122 121 75
316052 121 50
787238 121 50
732637 104 50
283712 104 50
983716 104 0
367167 104 25

Tabla 2: Tabla con los IDs de usuario e identificadores del producto indexados.

El algoritmo de recomendación que estamos utilizando es el de filtrado colaborativo. Para ejecutarlo podemos seguir la recomendación de buenas prácticas para ejecutar tareas periódicas en GCP.  En nuestro caso hemos escrito este script en python para ejecutar en pyspark sobre Dataproc, tomando como modelo el que provee Google.

La ejecución de este script sobrescribe la tabla de predicciones (como podemos ver en la Figura 1) con la información más fresca, y nos deja un resultado como el de la tabla 3.

userId postId rating
18872 2289 98
42044 1644 23
42044 4723 22
42044 13860 21
42044 698 21
42044 148 20
24688 1655 53
24688 58 50
24688 1654 45
24688 4482 43
..

Tabla 3: Resultado del algoritmo de predicción

Egresión

Gracias a las Cloud Functions y demás arquitectura Serverless que ofrecen los grandes proveedores de servicios en la nube (AWS con las Lambda Functions, Google con las Cloud Functions y Microsoft con Azure Functions) podemos implementar este tipo de APIs muy fácilmente.

Hace unos meses, mi compañero Nico revisaba la ventaja estratégica que supone este tipo de servicios en su artículo. Puede servirnos de introducción si queremos un poco de contexto antes de ponernos manos a la obra.

Símplemente pediremos las recomendaciones (si las hubiera) para el usuario actual desde el front usando una función similar a esta (sirva de plantilla). Es interesante señalar que estamos ingresando datos de orígenes disjuntos como son nuestros dos blogs (Analitica Web y el blog de Actualidad de Divisadero) por lo que, para que las recomendaciones tengan sentido dentro de cada uno, deberemos filtrar las que se refieren a este. Es decir, dentro del blog de Analitica serviremos solamente recomendaciones sobre este mismo blog.

Al pedir los datos a la api para cierto ID, debería devolvernos una respuesta de este tipo:

{

“tuuid”: “015e949d37bb001a1b2316be0a3e04072003606a00918”,

“post_array”: [

“http://www.analiticaweb.es/torturando-los-datos-capitulo-i/”,

“http://www.analiticaweb.es/cross-device-tracking-google-analytics/”,

“http://www.analiticaweb.es/un-paso-mas-en-data-studio/”,

“http://www.analiticaweb.es/multi-channel-funnels-o-embudos-multicanal-de-ga/”,

“http://www.analiticaweb.es/trucos-lowcost-para-adobe-analytics/”

]

}

Después es tarea personal mostrar esta información de manera relevante sobre la página.

Next Steps

Ahora mismo las recomendaciones se calculan periódicamente, el dato no es absolutamente fresco. Es decir, si una visitante habitual del blog lee un artículo, esta información no se incluirá en las recomendaciones hasta la próxima vez que se recalculen. Se dará la paradoja de que después de leer los artículos recomendados, seguiremos recibiendo las mismas recomendaciones. Aunque las predicciones puedan recalcularse con mucha frecuencia, seguirán siendo procesos en batch, cuando lo que necesitamos es un procesamiento en streaming con el dato siempre fresco.

Para este propósito disponemos en GCP de una herramienta llamada Dataflow, fácilmente operable en python, que junto con esta librería (FluRS) podría realizar esta predicción casi en tiempo real. Funciona implementando el algoritmo de Descenso Estocástico del Gradiente (SGD) para calcular un modelo fiable, pero con la particularidad de hacerlo de manera incremental, de tal forma que se pueden añadir datos al vuelo.

Da gusto trabajar con la plataforma Fully Managed de GCP, con toda la potencia al alcance de la mano. Espero que el lector pueda extraer información práctica del artículo. Como siempre, las preguntas son bien recibidas.

Escribe tu comentario

3 + dos =

Navegar