Python Data Science Program
📓 Abrir notebook en GitHub

Clase 218 — Content-based filtering

Parte: 6 — Sistemas de Recomendación · Fuente: Aggarwal Recommender Systems: The Textbook cap. 4 + docs scikit-learn TfidfVectorizer. ⏱️ Duración estimada: 70 min.

🎯 Objetivo

Recomendar items basándose en sus atributos (texto, género, categoría) en vez de interacciones — útil cuando hay cold-start de items (Clase 221) o cuando los items tienen rica metadata. Combinar TF-IDF / embeddings sobre descripciones + scoring por similitud al perfil del usuario.

📚 Resultados de aprendizaje

Al finalizar, el estudiante podrá:

🗺️ Temas

# Tema Por qué importa
1 TF-IDF + cosine similarity El baseline desde 1990.
2 One-hot vs multi-hot features categóricas Géneros, tags, autores.
3 User profile como media ponderada El "embedding del gusto".
4 Embeddings semánticos (sentence-transformers) all-MiniLM-L6-v2 reemplaza TF-IDF con mucha más profundidad.
5 FAISS para top-N rápido Cuando items son millones.
6 Hybrid con CF (Clase 219) Content-only sufre serendipia.

📖 Definiciones y características

📂 Dataset / recursos

🧪 Ejercicios

  1. TF-IDF base: cargar movies con title + overview + genres. TfidfVectorizer(max_features=10000, ngram_range=(1,2)). Matrix shape (n_items, 10000).
  2. Item-item similarity: cosine_similarity(tfidf_matrix). Para Toy Story, mostrar top-10 más similares — deberían ser otras animaciones.
  3. User profile: para user_id=42, tomar items rateados ≥4. user_profile = mean(item_profiles) (ponderado por rating). Recomendar top-10.
  4. Embeddings modernos: model = SentenceTransformer('all-MiniLM-L6-v2'). Generar embeddings de cada movie. Comparar top-10 de TF-IDF vs embeddings — los embeddings entienden semántica.
  5. FAISS rápido: index = faiss.IndexFlatIP(384); index.add(embeddings). index.search(user_profile, k=10) → top-10 en <1 ms aunque haya 1M items.

📝 Homework verificable

Notebook con:

  1. Recomendador content-based con sentence-transformers sobre MovieLens + sinopsis (10K movies).
  2. FAISS index para retrieval <10 ms p99.
  3. Comparativa con CF (Clase 216-217): NDCG@10, coverage (% items recomendados al menos una vez), diversidad (1 - avg intra-list similarity).
  4. Demonstración cold-start: agregar una "movie nueva" sin ratings; verificar que content-based la recomienda; CF no.
  5. README discutiendo: cuándo content-based gana (cold-start, niche items), cuándo pierde (filter bubble, serendipia baja).

Criterio de aceptación: content-based recomienda la movie nueva sin ratings (CF la ignora); coverage de content-based es ≥CF; el estudiante justifica un hybrid (Clase 219).

⚠️ Errores comunes

Síntoma / mensaje Causa y cómo arreglar
TF-IDF gigante: shape (10K items, 100K features) Sin max_features o stopwords. Fix: max_features=10000, stop_words='english'.
Recomendaciones todas iguales: variantes del mismo film Sobreespecialización (filter bubble). Fix: agregar diversity penalty (MMR — Maximal Marginal Relevance).
User profile vacío para new user No tiene interactions todavía. Fix: onboarding explícito ("elegí 3 géneros") o popular fallback.
Embeddings de 100K items en RAM = 150 MB Es OK pero el cosine_similarity 100K × 100K = 40 GB. Fix: FAISS con IndexFlatIP o IndexIVFFlat.
Multi-hot de géneros domina el TF-IDF Concatenaste sin normalizar. Fix: normalizar cada bloque (L2-normalize) antes de concatenar; o usar weighted combination.
sentence-transformers tarda mucho al cargar modelo Es lento la primera vez (download del checkpoint). Fix: cachear; usar device='cuda' si hay GPU.

❓ Preguntas frecuentes

❓ ¿Content-based vs CF?

Resuelven cosas distintas, y la mejor solución suele ser hybrid (Clase 219). - Content-based: maneja item cold-start, explica por qué ("te recomendamos X porque te gustó Y, ambos de género acción"), pero filter bubble. - CF: capta señales sociales (a gente como vos le gustó), serendipia, pero no funciona con items nuevos.

❓ ¿TF-IDF o embeddings?

Embeddings (sentence-transformers) ganan en calidad semántica. TF-IDF gana en velocidad de inferencia y simplicidad. Para 2026 greenfield: empezá con embeddings, agregá FAISS para retrieval.

❓ ¿Cómo combino texto + features categóricas?

Tres opciones: (1) concatenar TF-IDF + one-hot (escalado), (2) entrenar un modelo de feature embedding (fastText, USE) sobre todo, (3) usar metadata como features adicionales en LightFM (Clase 222).

❓ ¿sentence-transformers modelo elijo?

❓ ¿FAISS es necesario?

Si tenés <10K items: cosine_similarity con sklearn alcanza. Si tenés >100K items y querés top-N en <50 ms: FAISS obligatorio. Para 1M+ items y escala: FAISS con índices avanzados (HNSW, IVF) o Milvus/Pinecone (managed vector DBs).

❓ ¿Y los embeddings de OpenAI?

text-embedding-3-small/large son fuertes; pagás por inference + lock-in. Para empezar/offline: sentence-transformers gratis. Para producción con presupuesto: OpenAI / Cohere / Voyage.

🔗 Referencias

📥 Material descargable

➡️ Siguiente clase

Clase 219 — Recomendadores híbridos