¿Qué es un sistema de recomendación?
Un sistema de recomendación predice qué ítems (películas, productos, canciones, cursos) le interesarán a un usuario a partir de su comportamiento pasado y el de otros usuarios. Es la tecnología detrás de “Porque viste…”, “Otros clientes también compraron…” y las listas personalizadas de cualquier plataforma moderna.
El dato de partida es la matriz usuario-ítem: filas = usuarios, columnas = ítems, y cada celda contiene una valoración (rating de 1 a 5, número de reproducciones, compra sí/no). El problema: esa matriz está casi vacía. Un usuario típico ha valorado una fracción minúscula del catálogo. Recomendar es, en esencia, rellenar los huecos de esa matriz.
Dos grandes enfoques
| Enfoque | Idea | Ventajas | Desventajas |
|---|---|---|---|
| Filtrado colaborativo | “A usuarios parecidos les gustan cosas parecidas” | No necesita conocer los ítems; descubre patrones inesperados | Cold start; necesita muchas interacciones; matriz dispersa |
| Basado en contenido | “Recomienda ítems similares a los que ya le gustaron” | Funciona con pocos usuarios; no sufre cold start de ítem | Sobre-especialización; necesita extraer atributos de los ítems |
El filtrado colaborativo (CF) usa solo las interacciones. Su versión clásica es la de vecinos cercanos:
- User-based: encuentra los usuarios más similares a ti (p. ej. por similitud coseno entre sus vectores de ratings) y te recomienda lo que a ellos les gustó y tú no has visto.
- Item-based: calcula similitudes entre ítems (“quien valoró bien A también valoró bien B”) y recomienda ítems similares a los tuyos. Escala mejor, porque suele haber menos ítems que usuarios y las similitudes son más estables.
El basado en contenido representa cada ítem como un vector de atributos (género, director, palabras clave) y recomienda ítems cuyo vector sea cercano al perfil del usuario, construido a partir de lo que ya valoró positivamente.
En la práctica, las plataformas reales usan sistemas híbridos: combinan colaborativo y contenido para compensar las debilidades de cada uno.
Factorización de matrices y ALS
A escala industrial, el enfoque dominante es la factorización de matrices: aproximar la matriz de ratings R (grande y dispersa) como el producto de dos matrices pequeñas y densas:
- P (usuarios × k factores latentes)
- Q (ítems × k factores latentes)
tal que R ≈ P·Qᵀ. Cada usuario y cada ítem quedan representados por un vector de k dimensiones “latentes” (afinidad al humor, a la acción, al precio… aunque no tengan nombre explícito). El rating predicho es el producto escalar de ambos vectores.
graph LR subgraph R["Matriz R (usuarios x items)"] R1["5 ? 3 ?"] R2["? 4 ? 1"] R3["2 ? 4 ?"] end subgraph P["P (usuarios x k)"] P1["u1"] P2["u2"] P3["u3"] end subgraph Q["Q (items x k)"] Q1["i1"] Q2["i2"] Q3["i3"] Q4["i4"] end R -->|"R ≈ P · Qᵀ"| P R --> Q P --> PRED["Rating predicho:<br/>pᵤ · qᵢ"] Q --> PRED
¿Cómo se calculan P y Q cuando R es enorme? Con ALS (Alternating Least Squares):
- Fija Q y resuelve P con mínimos cuadrados (cada fila de forma independiente → paralelizable).
- Fija P y resuelve Q de la misma manera.
- Repite hasta converger.
La alternancia convierte un problema no convexo en muchos problemas de mínimos cuadrados independientes, perfectos para Spark: MLlib incluye ALS listo para usar con millones de usuarios e ítems.
El problema del cold start
El cold start aparece cuando el sistema no tiene datos suficientes:
- Usuario nuevo: sin historial, no hay vecinos ni vector latente. Soluciones: pedir valoraciones iniciales, usar datos demográficos, o recomendar lo más popular.
- Ítem nuevo: nadie lo ha valorado. Soluciones: usar sus atributos (enfoque de contenido) o promocionarlo a usuarios exploradores.
- Sistema nuevo: el peor caso; se arranca con reglas de popularidad mientras se acumulan interacciones.
Métricas de evaluación
| Métrica | Qué mide | Cuándo usarla |
|---|---|---|
| RMSE | Raíz del error cuadrático medio entre ratings predichos y reales | Cuando importa acertar la valoración exacta |
| Precision@k | Fracción de los k ítems recomendados que son relevantes | Listas top-N (lo habitual en producción) |
| Recall@k | Fracción de los ítems relevantes que aparecen en el top-k | Complemento de precision@k |
| NDCG@k | Como precision@k pero penaliza que los aciertos estén abajo en la lista | Cuando el orden de la lista importa |
En producción casi nadie muestra ratings predichos: se muestra una lista top-N. Por eso precision@k y NDCG@k suelen ser más informativas que el RMSE, aunque ALS se entrene minimizando el error cuadrático.
Ejercicio: filtrado colaborativo user-based
🧪 Ejercicio
Recomendador con similitud coseno
Implementa un mini filtrado colaborativo user-based. Dada una matriz de ratings (0 = no valorado), calcula la similitud coseno entre el usuario objetivo y los demás (usando solo los ítems valorados por ambos), y predice el rating que el usuario objetivo daría a un ítem que no ha valorado como la media de los ratings de los vecinos ponderada por similitud. La matriz ratings tiene 4 usuarios y 5 películas; predice qué rating daría el usuario 0 a la película 4.
🔍 La similitud coseno entre dos vectores es dot(a,b) / (norm(a) * norm(b)). Filtra primero las columnas donde ambos usuarios tienen rating > 0. Para la predicción: suma(similitud_i * rating_i) / suma(similitud_i) sobre los vecinos que sí valoraron ese ítem.
import numpy as np
# Filas: usuarios; columnas: peliculas. 0 = no valorado
ratings = np.array([
[5, 3, 0, 1, 0],
[4, 0, 0, 1, 5],
[1, 1, 0, 5, 4],
[1, 0, 0, 4, 4],
], dtype=float)
def similitud_coseno(a, b):
# Solo items valorados por ambos
mascara = (a > 0) & (b > 0)
if mascara.sum() == 0:
return 0.0
va, vb = a[mascara], b[mascara]
return float(va @ vb / (np.linalg.norm(va) * np.linalg.norm(vb)))
def predecir(ratings, usuario, item):
numerador = 0.0
denominador = 0.0
for otro in range(ratings.shape[0]):
if otro == usuario or ratings[otro, item] == 0:
continue
sim = similitud_coseno(ratings[usuario], ratings[otro])
numerador += sim * ratings[otro, item]
denominador += sim
return numerador / denominador if denominador > 0 else 0.0
pred = predecir(ratings, usuario=0, item=4)
print(f"Rating predicho del usuario 0 para la pelicula 4: {pred:.2f}")
# Similitudes del usuario 0 con el resto
for u in range(1, ratings.shape[0]):
print(f"sim(usuario 0, usuario {u}) = {similitud_coseno(ratings[0], ratings[u]):.3f}")Comprueba lo aprendido
Comprueba que lo pillaste
¿Cuál es la principal ventaja del filtrado colaborativo frente al enfoque basado en contenido?
El filtrado colaborativo solo usa la matriz de interacciones: no requiere extraer atributos de los ítems y puede recomendar cosas sorprendentes que el contenido no explicaría. Su debilidad es justamente el cold start.
Comprueba que lo pillaste
En ALS (Alternating Least Squares), ¿qué se alterna exactamente?
ALS fija Q y resuelve P por mínimos cuadrados, luego fija P y resuelve Q, repitiendo hasta converger. Cada subproblema es convexo y las filas se resuelven de forma independiente, lo que lo hace ideal para Spark.
Comprueba que lo pillaste
Una plataforma muestra al usuario una lista de 10 recomendaciones. ¿Qué métrica evalúa mejor la calidad de esa lista?
En listas top-N lo relevante es cuántos de los ítems mostrados interesan de verdad (precision@k, y recall@k como complemento). El RMSE evalúa la predicción de ratings individuales, no la calidad de la lista presentada.
Resumen
- Los sistemas de recomendación rellenan los huecos de la matriz usuario-ítem, que es extremadamente dispersa.
- Filtrado colaborativo (user-based / item-based) usa solo interacciones; basado en contenido usa atributos de los ítems. Los sistemas reales son híbridos.
- La factorización de matrices representa usuarios e ítems con vectores latentes; ALS la calcula alternando mínimos cuadrados y escala en Spark.
- El cold start (usuario o ítem nuevo sin datos) se mitiga con contenido, popularidad o valoraciones iniciales.
- RMSE mide el error de predicción de ratings; precision@k y NDCG@k evalúan la calidad de las listas top-N, que es lo que el usuario realmente ve.
📚 Lecturas y fuentes
| Recurso | Tipo | Por qué leerlo |
|---|---|---|
| Sistema de recomendación (Wikipedia en español) | Docs | Repaso rápido del vocabulario; lee solo “Filtrado colaborativo” y “Basado en contenido” para fijar la comparación. |
| MovieLens Datasets — GroupLens | Dataset | El dataset estándar para practicar; empieza por ml-latest-small (100k ratings), que cabe en tu portátil. (en inglés) |
| Collaborative Filtering — Spark MLlib | Docs | Documentación de ALS en Spark; lee “Explicit vs. implicit feedback” y “Cold-start strategy”, que es donde está la chicha. (en inglés) |
| Matrix Factorization Techniques for Recommender Systems (Koren, Bell y Volinsky, 2009) | Paper | El artículo que popularizó la factorización tras el Netflix Prize; con las secciones “A Basic Matrix Factorization Model” y “Learning Algorithms” tienes lo esencial. (en inglés) |