15 · Feedback implícito y BPR
Con datos implícitos no hay valoraciones ni negativos verdaderos — así que deja de predecir valores y empieza a optimizar el ranking. Bayesian Personalized Ranking aprende a poner lo que clicaste por encima de lo que no.
Cuando todo lo que observas es lo que los usuarios clicaron (positivos) y un mar de desconocidos, predecir el valor de una valoración es el objetivo equivocado. BPR replantea el problema como ranking: para cada par observado (usuario, ítem), muestrea un ítem no observado y entrena para que el observado puntúe más alto — una pérdida logística por pares que optimiza directamente el orden que realmente sirves.
Sin esto:
Ajusta un regresor de valoraciones sobre datos de clic y optimizas el error cuadrático contra 1s y 0s que no significan lo que crees — el modelo gasta su capacidad empujando desconocidos hacia cero en vez de aprender el ranking que mueve las recomendaciones que los usuarios ven.
La mayoría de los datos de interacción reales son implícitos: reproducciones, clics, compras, permanencia. No hay valoraciones, y — como vimos en el Capítulo 1 — no hay negativos verdaderos: un ítem que un usuario nunca tocó puede que le disguste o que simplemente nunca lo viera. Funk-SVD sobre una matriz 0/1 intenta que cada celda observada prediga 1 y cada celda faltante prediga 0, lo que desperdicia esfuerzo modelando desconocidos como si fueran desagrados confirmados.
Bayesian Personalized Ranking (BPR) corrige el objetivo. En vez de preguntar "¿qué valor va en esta celda?", pregunta "para el usuario u, ¿el ítem i (con el que interactuó) debería ir por encima del ítem j (con el que no)?" Eso es exactamente el orden que sirve un recomendador. BPR representa cada usuario e ítem con un vector latente y puntúa un par como el producto punto x_ui = pu · qi. Para un triple muestreado (u, i, j) con i positivo y j no observado, la diferencia por pares es x_uij = x_ui - x_uj, y BPR maximiza el log-probabilidad de que esa diferencia sea positiva:
loss = -ln σ(x_uij) σ(z) = 1 / (1 + e^-z)
El gradiente empuja hacia arriba la puntuación del ítem positivo y hacia abajo la del negativo muestreado. Sacamos los triples por muestreo de negativos — elige un (u, i) observado, luego muestrea un ítem aleatorio j que el usuario no haya tocado — así cada paso de SGD solo compara un positivo contra un negativo. Una medida natural de calidad es el AUC: la fracción de pares (positivo, negativo) que el modelo ordena correctamente. Un modelo aleatorio da ~0.5; BPR debería subir muy por encima de eso conforme entrena.
La celda de abajo implementa BPR-SGD desde cero sobre una matriz binaria con semilla e imprime el AUC subiendo en cada época.
Python (in browser)
BPR-SGD sobre una matriz implícita binaria: pérdida logística por pares con muestreo de negativos. El AUC sube de ~0.5 hacia ~0.9 a medida que el modelo aprende a ordenar clics por encima de no-clics.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
En producción recurres a una librería probada en batalla en vez de SGD hecho a mano. La librería implicit implementa BPR (y el relacionado ALS-para-implícito / WMF) con Cython multihilo y solvers de Gradiente Conjugado; LightFM añade factorización híbrida con la pérdida WARP (un muestreador de negativos más astuto que el BPR puro). El read-along de abajo esboza la API de LightFM — importa un paquete que nunca ejecutamos en el navegador, así que es de solo lectura.
Ranking implícito del mundo real con la pérdida WARP de LightFM (solo lectura). Misma idea que nuestra celda BPR — ranking por pares — pero con un muestreador de negativos más astuto y características opcionales de ítem/usuario para manejar el cold-start de forma híbrida.
¿Por qué BPR optimiza una pérdida por pares (ítem i vs ítem j) en vez de regresar cada celda hacia 0 o 1?
- El feedback implícito no tiene valoraciones ni negativos verdaderos — predice ranking, no valores.
- BPR muestrea triples (usuario, positivo, negativo) y maximiza -ln σ(x_ui - x_uj), una pérdida logística por pares que optimiza directamente el orden.
- El AUC (fracción de pares positivo>negativo ordenados correctamente) sube desde ~0.5 mientras BPR entrena; librerías como implicit y LightFM (WARP) lo llevan a producción.
Spotify, el 'añadir al carrito' del e-commerce y cualquier feed de clic/reproducción entrenan con señales implícitas usando pérdidas por pares/de ranking como BPR o WARP, no regresión de valoraciones.
Si lo quitas: Sin un objetivo de ranking, un recomendador implícito optimiza el error cuadrático contra 0s sin sentido y ordena el catálogo mal pese a una 'pérdida de entrenamiento' baja.