WhatsApp

  

Construye un Sistema de Recomendaciones con SVD en Python: Guía Completa y Práctica

Aprende paso a paso cómo implementar, evaluar y escalar un algoritmo de recomendaciones basado en Singular Value Decomposition (SVD) usando Python. Incluye ejemplos, comparativas, buenas prácticas y consideraciones de seguridad.

Algoritmo de Recomendaciones con SVD: Guía Práctica en Python

Introducción

Los sistemas de recomendación son una pieza clave en plataformas de streaming, e‑commerce y redes sociales. Singular Value Decomposition (SVD) es uno de los algoritmos más robustos para collaborative filtering porque permite reducir la dimensionalidad de una matriz de usuarios‑productos y capturar relaciones latentes.

En este artículo encontrarás:

  • Fundamentos teóricos de SVD aplicados a recomendación.
  • Implementación completa en Python (NumPy, SciPy y surprise).
  • Comparativa con algoritmos alternativos (ALS, NMF, Deep Learning).
  • Mejores prácticas de pre‑procesado, evaluación, optimización y despliegue.
  • Guía de troubleshooting, seguridad y escalabilidad.

1. Fundamentos de SVD para Sistemas de Recomendación

Partimos de una matriz R de dimensiones m × n (usuarios × ítems) donde cada celda contiene una valoración (por ejemplo, de 1 a 5). La descomposición SVD se expresa como:

R ≈ U Σ Vᵀ

donde:

  • U (m × k) – vectores latentes de usuarios.
  • Σ (k × k) – valores singulares (importancia de cada factor).
  • Vᵀ (k × n) – vectores latentes de ítems.

Al truncar a k factores (usualmente entre 20 y 200) reducimos el ruido y obtenemos predicciones mediante:

Ŕ = U Σ Vᵀ

Las entradas de Ŕ son estimaciones de la valoración que un usuario daría a un ítem que aún no ha evaluado.

2. Preparación de los Datos

Los datos reales son extremadamente escasos. Algunas tareas esenciales:

  1. Filtrado de usuarios/ítems con muy pocas interacciones.
  2. Normalización. Restar la media del usuario o del ítem para centrar la distribución.
  3. División de conjuntos. train_test_split (ej. 80/20) usando surprise.model_selection.

Ejemplo de pre‑procesado con pandas:

import pandas as pd
# Cargar dataset (formato: userId, movieId, rating, timestamp)
ratings = pd.read_csv('ml‑100k/u.data', sep='\t',
                      names=['user','item','rating','ts'])
# Filtrar usuarios con < 20 ratings y items con < 20 ratings
user_counts = ratings['user'].value_counts()
item_counts = ratings['item'].value_counts()
ratings = ratings[ratings['user'].isin(user_counts[user_counts>=20].index)]
ratings = ratings[ratings['item'].isin(item_counts[item_counts>=20].index)]
# Centering por usuario
ratings['rating_centered'] = ratings.groupby('user')['rating'].transform(lambda x: x - x.mean())

3. Implementación Básica de SVD con NumPy / SciPy

Esta versión es útil para comprender el algoritmo, aunque no es la más eficiente para matrices muy grandes.

import numpy as np
from scipy.sparse.linalg import svds
# Construir matriz de usuarios‑items (rellena ceros donde no hay rating)
m = ratings['user'].nunique()
n = ratings['item'].nunique()
R = np.zeros((m, n))
for row in ratings.itertuples():
    R[row.user-1, row.item-1] = row.rating_centered
# Número de factores latentes
k = 50
# svds devuelve los k valores singulares más grandes
U, sigma, VT = svds(R, k=k)
Sigma = np.diag(sigma)
# Predicción
pred = np.dot(np.dot(U, Sigma), VT)
# Des‑centering (añadir la media del usuario)
user_means = ratings.groupby('user')['rating'].mean().values
pred += user_means[:, np.newaxis]

Para obtener las 10 mejores recomendaciones para el usuario 5:

user_id = 5 - 1  # índice 0‑based
user_pred = pred[user_id]
# Excluir ítems ya valorados
already_rated = ratings[ratings['user']==5]['item'].values - 1
user_pred[already_rated] = -np.inf
top_items = np.argsort(user_pred)[::-1][:10] + 1  # volver a 1‑based
print('Recomendaciones para usuario 5:', top_items)

4. Implementación con surprise (Recomendado para Producción)

La librería Surprise abstrae la mayor parte del pipeline y permite entrenar SVD con regularización y bias de forma eficiente.

from surprise import Dataset, Reader, SVD, accuracy
from surprise.model_selection import train_test_split
# Formato: user, item, rating
reader = Reader(line_format='user item rating', sep='\t', rating_scale=(1, 5))
 data = Dataset.load_from_df(ratings[['user','item','rating']], reader)
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)
# Entrenamiento con bias y regularización
svd = SVD(n_factors=100, n_epochs=30, biased=True, lr_all=0.005, reg_all=0.02)
svd.fit(trainset)
# Predicciones y métricas
predictions = svd.test(testset)
rmse = accuracy.rmse(predictions)
mae  = accuracy.mae(predictions)
print(f'RMSE: {rmse:.4f} | MAE: {mae:.4f}')
# Función de recomendación
from collections import defaultdict
def get_top_n(predictions, n=10):
    top_n = defaultdict(list)
    for uid, iid, true_r, est, _ in predictions:
        top_n[uid].append((iid, est))
    # Ordenar y cortar
    for uid, user_ratings in top_n.items():
        user_ratings.sort(key=lambda x: x[1], reverse=True)
        top_n[uid] = user_ratings[:n]
    return top_n
top10 = get_top_n(predictions, n=10)
print('Top‑10 para el usuario 5:', top10[5])

Ventajas de surprise.SVD:

  • Optimiza automáticamente los hiperparámetros mediante GridSearchCV.
  • Implementación en Cython, mucho más rápida que NumPy puro.
  • Manejo interno de bias de usuarios e ítems.

5. Comparativa: SVD vs ALS vs NMF vs Deep Learning

SVD (Factorización de Matriz)
  • Ventajas: Interpretabilidad, buen desempeño en datasets medianos, bajo coste computacional para k<200.
  • Desventajas: No escala bien a millones de usuarios sin paralelismo.
ALS (Alternating Least Squares)
  • Ventajas: Fácil de paralelizar (Spark MLlib), maneja datos implícitos.
  • Desventajas: Requiere más iteraciones y memoria que SVD.
NMF (Non‑Negative Matrix Factorization)
  • Ventajas: Factores no negativos → interpretables como “preferencias positivas”.
  • Desventajas: Convergencia más lenta y menos robusta a valores atípicos.
Deep Learning (Autoencoders, Neural CF)
  • Ventajas: Captura relaciones no lineales, fácilmente extensible con side‑information.
  • Desventajas: Necesita gran cantidad de datos, GPU y mayor tiempo de entrenamiento.

6. Métricas de Evaluación y Validación

Además de RMSE y MAE, en entornos de recomendación se usan métricas de ranking:

  • Precision@K / Recall@K: Cuántos de los K ítems recomendados son relevantes.
  • MAP (Mean Average Precision).
  • NDCG (Normalized Discounted Cumulative Gain): Penaliza ítems relevantes en posiciones bajas.

Ejemplo de cálculo de Precision@10 con surprise:

from sklearn.metrics import precision_score
def precision_at_k(predictions, k=10):
    user_est_true = defaultdict(list)
    for uid, iid, true_r, est, _ in predictions:
        user_est_true[uid].append((est, true_r))
    precisions = []
    for uid, ratings in user_est_true.items():
        ratings.sort(key=lambda x: x[0], reverse=True)
        top_k = ratings[:k]
        # Consideramos rating >=4 como relevante
        relevant = sum(1 for _, r in top_k if r >= 4)
        precisions.append(relevant / k)
    return np.mean(precisions)
print('Precision@10:', precision_at_k(predictions, k=10))

7. Buenas Prácticas, Optimización y Escalabilidad

Regularización y Bias

Siempre incluya bias_user y bias_item (p.e., surprise.SVD(biased=True)) para evitar sobre‑ajuste.

Selección de k

Realice una búsqueda de hiperparámetros (GridSearchCV de Surprise) con valores típicos: 20, 50, 100, 150.

Paralelismo

Para datasets > 10⁶ interacciones, considere:

  • Implementar SVD en Spark (spark.ml.recommendation.ALS) y usar la variante implicitPrefs si trabaja con clicks.
  • Utilizar faiss o Annoy para búsqueda aproximada de vecinos cuando se necesita generar recomendaciones en tiempo real.

Persistencia del Modelo

Guarde los factores U, Σ y V en un almacén columnar (Parquet) o en Redis para consultas de baja latencia.

8. Seguridad, Privacidad y Consideraciones Éticas

  • Anonimización: Elimine cualquier dato identificable antes de entrenar (hash de IDs).
  • Protección contra ataques de inferencia: Limite la exposición de puntuaciones predichas mediante rate‑limiting y differential privacy si el modelo se expone como API.
  • Bias de género/raza: Evalúe métricas de equidad (por ejemplo, disparity‑ratio) y ajuste los factores o añada regularización de fairness.

9. Despliegue en Producción

Un flujo típico:

  1. Ingesta de eventos (Kafka) → tabla de interacciones.
  2. Batch nightly: re‑entrenamiento del modelo SVD con Spark o con un script Python programado (Airflow).
  3. Persistencia de factores en un servicio de vectores (RedisVector, Milvus).
  4. API REST (FastAPI) que recibe user_id y devuelve top‑N ítems usando np.dot sobre los factores cargados.

Ejemplo de endpoint rápido con FastAPI:

from fastapi import FastAPI
import numpy as np, redis
app = FastAPI()
r = redis.Redis(host='localhost', port=6379, db=0)
U = np.load('U.npy')   # shape (users, k)
V = np.load('V.npy')   # shape (items, k)
@app.get('/recommend/{user_id}')
def recommend(user_id: int, n: int = 10):
    user_vec = U[user_id]
    scores = V @ user_vec  # dot product
    top_idx = np.argpartition(-scores, n)[:n]
    return {'user': user_id, 'recommendations': top_idx.tolist()}

10. Futuro y Tendencias

Si bien SVD sigue siendo la referencia por su simplicidad y rendimiento, la integración con:

  • Graph Neural Networks (GNN) para capturar relaciones de usuarios‑usuarios.
  • Large Language Models (LLM) como “retrieval‑augmented recommendation”.
  • Federated Learning para entrenar modelos sin centralizar datos sensibles.

Estas combinaciones prometen superar los límites de precisión de los enfoques puramente lineales.

© 2025 BlogTech AI. Todos los derechos reservados.



Construye un Sistema de Recomendaciones con SVD en Python: Guía Completa y Práctica
ASIMOV Ingeniería S. de R.L. de C.V., Emiliano Nava 13 noviembre, 2025
Compartir
Iniciar sesión dejar un comentario

  
Algoritmo de Cadenas de Markov con Álgebra Lineal: Conceptos, Ejemplos en Python y Mejores Prácticas
Aprende a modelar, analizar y simular cadenas de Markov usando álgebra lineal. Incluye teoría, ejemplos completos en Python, comparativas, troubleshooting y buenas prácticas.