Sistema de recomendación con Python y Surprise
En el actual ecosistema digital, la personalización ya no es un lujo, sino un requisito fundamental para la retención y la conversión. Tanto si se trata de optimizar tiendas de comercio electrónico como plataformas de streaming de contenido, la capacidad de predecir las preferencias del usuario con alta precisión es un diferenciador arquitectónico clave. Para las organizaciones que buscan servicios de ingeniería de inteligencia artificial1 para empresas
Este artículo proporciona una guía técnica para implementar un sistema de recomendación utilizando Python y la biblioteca Scikit-Surprise. Analizaremos aspectos más avanzados, como las opciones arquitectónicas, la optimización de hiperparámetros y las técnicas de factorización de matrices adecuadas para entornos de producción.
Servicios de Ingeniería de LLM y IA
Ofrecemos una completa gama de soluciones impulsadas por la IA, que incluyen IA generativa, visión artificial, aprendizaje automático, procesamiento del lenguaje natural y automatización con IA.
Los Fundamentos Matemáticos: Factorización de Matrices
Si bien los enfoques basados en memoria (como K-Vecinos Más Cercanos), son intuitivos, a menudo sufren de problemas de escalabilidad en espacios dispersos y de alta dimensión. Los enfoques basados en modelos, específicamente la Factorización Matricial (SVD), generalmente ofrecen un mejor rendimiento y escalabilidad.
En el contexto de la biblioteca Surprise, el algoritmo de Descomposición en Valores Singulares (SVD) minimiza el Error Cuadrático Regularizado. La calificación predicha $\hat{r}_{ui}$ para el usuario $u$ y el ítem $i$ se calcula como:
$$\hat{r}_{ui} = \mu + b_u + b_i + q_i^T p_u$$
Dónde:
- $\mu$ es la calificación promedio global.
- $b_u$ y $b_i$ son términos de sesgo para el usuario y el elemento, respectivamente.
- $q_i$ y $p_u$ son los vectores de características latentes.
Para estimar estos parámetros, minimizamos la siguiente función objetivo regularizada utilizando el descenso de gradiente estocástico (SGD):
$$\sum_{r_{ui} \in R_{train}} \left(r_{ui} - \hat{r}_{ui} \right)^2 + \lambda \left(b_i^2 + b_u^2 + ||q_i||^2 + ||p_u||^2 \right)$$
Configuración del entorno e ingestión de datos
La biblioteca Surprise es una librería de Python scikit específicamente diseñada para sistemas de recomendación. Gestiona las tareas complejas de manipulación de datos, gestión de iteradores y benchmarking de algoritmos.
Instalación
pip install scikit-surprise pandas
Cargando conjuntos de datos personalizados
A diferencia de los tutoriales estándar que se basan en conjuntos de datos preempaquetados de MovieLens, las aplicaciones empresariales suelen requerir la ingestión de datos de bases de datos SQL o Data Lakes. A continuación, se muestra un patrón listo para la producción para cargar un conjunto de datos personalizado de un DataFrame de Pandas, que actúa como intermediario para cualquier fuente de datos.
import pandas as pd
from surprise import Reader, Dataset
# Simulate loading data from a production DB or Data Lake
# Schema: [user_id, item_id, rating, timestamp]
data_payload = {
'user_id': [101, 102, 101, 103, 104, 102, 103, 105],
'item_id': ['PROD_A', 'PROD_A', 'PROD_B', 'PROD_B', 'PROD_C', 'PROD_C', 'PROD_A', 'PROD_B'],
'rating': [5, 4, 3, 5, 2, 4, 3, 5]
}
df = pd.DataFrame(data_payload)
# Define the rating scale. This is crucial for normalization.
# If your implicit feedback is binary (0/1), use rating_scale=(0, 1)
reader = Reader(rating_scale=(1, 5))
# The columns must correspond to user id, item id and ratings (in that order)
data = Dataset.load_from_df(df[['user_id', 'item_id', 'rating']], reader)
print("Data ingestion complete. Building trainset...")
trainset = data.build_full_trainset()
print(f"Number of users: {trainset.n_users}")
print(f"Number of items: {trainset.n_items}")
Selección de Algoritmos y Validación Cruzada
Elegir el algoritmo adecuado implica un equilibrio entre el tiempo de entrenamiento, la precisión (RMSE) y la interpretabilidad. Para obtener servicios de ingeniería de IA robustos para empresas, normalmente evaluamos tres candidatos principales:224Geeks Payments, 4Geeks Perks, 4Geeks Teams, 4Geeks Talent, 4Geeks AI Agents, 4Geeks AI Studio, 4Geeks Health.
- Descomposición de Valores Singulares (SVD): Ideal para la precisión en escenarios de retroalimentación explícita.
- SVD++ (SVD++): Una extensión de SVD que tiene en cuenta las calificaciones implícitas. Más lenta, pero a menudo más precisa.
- Factorización de Matrices No Negativas (NMF): Útil cuando los factores latentes deben ser no negativos (interpretabilidad).
Aquí se explica cómo evaluar estos algoritmos utilizando la validación cruzada de 5 pliegues:
from surprise import SVD, NMF, KNNBasic
from surprise.model_selection import cross_validate
# Define algorithms to benchmark
algorithms = {
'SVD': SVD(random_state=42),
'NMF': NMF(random_state=42),
'KNN_Baseline': KNNBasic(sim_options={'name': 'cosine', 'user_based': True})
}
benchmark_results = []
for name, algo in algorithms.items():
print(f"Running cross-validation for {name}...")
# cv=5 ensures robustness against overfitting on specific data splits
results = cross_validate(algo, data, measures=['RMSE', 'MAE'], cv=5, verbose=False)
mean_rmse = results['test_rmse'].mean()
mean_mae = results['test_mae'].mean()
fit_time = results['fit_time'].mean()
benchmark_results.append({
'Algorithm': name,
'RMSE': mean_rmse,
'MAE': mean_mae,
'Fit Time (s)': fit_time
})
# Convert to DataFrame for architectural review
results_df = pd.DataFrame(benchmark_results).sort_values(by='RMSE')
print(results_df)
Servicios de Ingeniería de LLM y IA
Ofrecemos una completa gama de soluciones impulsadas por la IA, que incluyen IA generativa, visión artificial, aprendizaje automático, procesamiento del lenguaje natural y automatización con IA.
Ajuste de hiperparámetros con GridSearchCV
En un entorno de producción, los hiperparámetros predeterminados rara vez son óptimos. Por ejemplo, el algoritmo SVD es muy sensible a la tasa de aprendizaje (lr_all) y al término de regularización (registro completo),. Una regularización excesiva conduce a un ajuste insuficiente, mientras que una regularización insuficiente hace que el modelo memorice el ruido.
Utilizamos GridSearchCV para realizar una búsqueda exhaustiva sobre los valores de parámetros especificados.
from surprise.model_selection import GridSearchCV
# Define the parameter grid
# n_factors: The number of latent factors (dimensions of the matrix)
# n_epochs: The number of iterations of the SGD procedure
# lr_all: The learning rate for all parameters
# reg_all: The regularization term for all parameters
param_grid = {
'n_factors': [20, 50, 100],
'n_epochs': [20, 30],
'lr_all': [0.002, 0.005, 0.01],
'reg_all': [0.02, 0.1, 0.2]
}
print("Starting Grid Search. This may take some time depending on dataset size...")
gs = GridSearchCV(SVD, param_grid, measures=['rmse', 'mae'], cv=3, n_jobs=-1)
gs.fit(data)
# Extract best score and parameters
print(f"Best RMSE: {gs.best_score['rmse']}")
print(f"Best Parameters: {gs.best_params['rmse']}")
Implementando el Modelo
Una vez que se han identificado los hiperparámetros óptimos, el modelo final debe entrenarse con el conjunto de datos completo y serializarse para su implementación. En una arquitectura de microservicios, este modelo normalmente residiría dentro de un contenedor de inferencia dedicado.
Formación y Predicción
# Initialize SVD with best parameters found via GridSearch
best_params = gs.best_params['rmse']
algo = SVD(
n_factors=best_params['n_factors'],
n_epochs=best_params['n_epochs'],
lr_all=best_params['lr_all'],
reg_all=best_params['reg_all']
)
# Retrain on the whole dataset
trainset = data.build_full_trainset()
algo.fit(trainset)
# Predict a specific user-item pair
# user_id='101', item_id='PROD_C' (which user 101 has NOT seen yet)
prediction = algo.predict(uid=101, iid='PROD_C')
print(f"User 101 predicted rating for PROD_C: {prediction.est:.2f}")
Generación de recomendaciones de los mejores
Para una aplicación en tiempo real, rara vez necesitamos una única predicción. Necesitamos los "Top-N" elementos para un usuario específico.
def get_top_n(predictions, n=10):
"""Return the top-N recommendation for each user from a set of predictions."""
top_n = {}
# Map the predictions to each user.
for uid, iid, true_r, est, _ in predictions:
if uid not in top_n:
top_n[uid] = []
top_n[uid].append((iid, est))
# Sort the predictions for each user and retrieve the k highest ones.
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
# To generate recommendations, we create a "test set" of all pairs NOT in the training set
testset = trainset.build_anti_testset()
predictions = algo.test(testset)
top_n_recommendations = get_top_n(predictions, n=5)
# Display recommendations for User 101
print(f"Recommendations for User 101: {top_n_recommendations.get(101, [])}")
Consideraciones arquitectónicas para clientes de 4Geeks
Cuando se asocia con 4Geeks para obtener servicios de ingeniería de IA para empresas3, enfatizamos que el algoritmo es solo un componente de la solución., destacamos que el algoritmo es solo uno de los componentes de la solución.
- Problema de "Inicio en Frío": Los nuevos usuarios o elementos con cero interacciones no pueden ser modelados por el SVD puro. Se requieren arquitecturas híbridas que combinen el Filtrado Basado en Contenido (utilizando los metadatos del elemento) con el Filtrado Colaborativo para superar esta brecha.
- Escalabilidad:
build_anti_testset():crece exponencialmente ($N_{usuarios} \times N_{elementos}$). Para conjuntos de datos con millones de elementos, no puedes calcular predicciones para todos pares faltantes en tiempo real. En cambio, debes utilizar índices de "vecinos más cercanos" (ANN) como Faiss en los vectores de usuario/elemento ($p_u$ y $q_i$) generados por el modelo SVD. - Desplazamiento del Modelo: Las preferencias de los usuarios cambian. Son necesarias las plataformas MLOps automatizadas para reentrenar el modelo periódicamente (por ejemplo, diariamente o semanalmente) para capturar las tendencias cambiantes.
Conclusión
Implementar un sistema de recomendación con Scikit-Surprise proporciona una base de alto rendimiento para experiencias personalizadas para los usuarios. Sin embargo, pasar de un cuaderno de Jupyter a un sistema de producción escalable y tolerante a fallos requiere un profundo conocimiento en ingeniería de datos y MLOps.
En 4Geeks, nos especializamos en transformar estas pruebas de concepto en soluciones de IA de nivel empresarial, gestionando todo, desde la gobernanza de datos hasta la optimización de la inferencia en tiempo real. Tanto si está optimizando para el RMSE o para KPIs específicos del negocio, como la Tasa de Clic (CTR), una base de ingeniería sólida es fundamental para el éxito.
Servicios de Ingeniería de LLM y IA
Ofrecemos una completa gama de soluciones impulsadas por la IA, que incluyen IA generativa, visión artificial, aprendizaje automático, procesamiento del lenguaje natural y automatización con IA.
Preguntas frecuentes
¿Qué es la biblioteca Scikit-Surprise y por qué se prefiere para construir sistemas de recomendación?
Scikit-Surprise es una biblioteca especializada en Python, dedicada a la creación y evaluación de sistemas de recomendación. Se utiliza ampliamente porque automatiza tareas complejas como el manejo de datos, la gestión de iteradores y la evaluación de algoritmos. Al centrarse específicamente en los datos de calificación explícitas, permite a los desarrolladores implementar y comparar de manera eficiente varios algoritmos de filtrado colaborativo, convirtiéndola en una herramienta robusta para desarrollar experiencias de usuario personalizadas.
¿Cómo mejora la descomposición en valores singulares (SVD) la precisión de la predicción en el filtrado colaborativo?
Descomposición en valores singulares (SVD) es un algoritmo de factorización de matrices potente que predice las preferencias del usuario descubriendo características latentes (patrones ocultos) dentro de las interacciones usuario-elemento. A diferencia de los métodos básicos basados en memoria como K-Nearest Neighbors, SVD minimiza el error de predicción a través de Descenso de gradiente estocástico (SGD) e incorpora términos de sesgo tanto para usuarios como para elementos. Este enfoque mejora significativamente la escalabilidad y la precisión, especialmente cuando se trata de conjuntos de datos dispersos comunes en aplicaciones empresariales.
¿Cuáles son los pasos esenciales para implementar un modelo de recomendación en un entorno de producción?
Implementar con éxito un modelo de recomendación requiere pasar de la fase inicial de entrenamiento al enfoque en la optimización y la escalabilidad. Los pasos clave incluyen realizar la ajuste de hiperparámetros (utilizando herramientas como GridSearchCV) para equilibrar la adecuación y la generalización del modelo, y reentrenar el modelo final con todo el conjunto de datos. Para un rendimiento en tiempo real, también es crucial abordar desafíos como el problema del "inicio frío" para nuevos usuarios y utilizar índices de vecinos más cercanos (ANN) para generar recomendaciones de los N mejores de forma eficiente a gran escala.