Módulo 3: Modelos de Embeddings Comparison
Domain-Specific y Multilingual Embeddings
Descripción de la cápsula
Los embeddings "generales" (OpenAI, SBERT) funcionan bien para textos estándar, pero dominios especializados (legal, medical, code) y multiidioma requieren modelos específicos. ¿Cuándo usar embeddings especializados? ¿Cuándo vale la pena fine-tuning?
En esta cápsula aprenderás sobre domain-specific embeddings (legal, medical, financial, code), multilingual embeddings (mBERT, XLM-R, BGE-M3), cuándo fine-tune vs zero-shot, y trade-offs. También verás código para evaluar embeddings en tu dominio.
Al final, podrás elegir embeddings especializados cuando sea necesario.
Domain-Specific Embeddings
Por qué dominio importa:
# Embedding general (SBERT):
query = "consideration"
doc_1 = "He showed consideration for others" # Contexto social
doc_2 = "In consideration of $100, parties agree..." # Contexto legal
# Problema: Embedding general puede no diferenciar bien
# "consideration" tiene significado MUY diferente en legal vs social
Solución: Embeddings entrenados en corpus legal.
Dominios principales:
1. Legal:
# Modelos:
# - Law-BERT
# - Legal-SBERT
# Entrenado en:
# - Case law
# - Contracts
# - Legal documents
# Mejora: +10-15% MTEB en tareas legales vs modelos generales
2. Medical:
# Modelos:
# - BioBERT
# - PubMedBERT
# - Clinical-BERT
# Entrenado en:
# - PubMed papers
# - Clinical notes
# - Medical terminology
# Mejora: +20% en tareas médicas
3. Financial:
# Modelos:
# - FinBERT
# Entrenado en:
# - Financial reports
# - News articles
# - SEC filings
# Mejora: +15% en sentiment analysis financiero
4. Code:
# Modelos:
# - CodeBERT
# - GraphCodeBERT
# Entrenado en:
# - GitHub repos
# - Stack Overflow
# Mejora: +30% en code search
Multilingual Embeddings
Por qué multiidioma:
# Problema: SBERT (all-MiniLM-L6-v2) es inglés-only
# Textos en español, chino, árabe tienen embeddings subóptimos
# Solución: Multilingual embeddings
# Entrenados en 100+ idiomas simultáneamente
Modelos multilingual:
1. mBERT (multilingual BERT):
Idiomas: 104
Dimensiones: 768
MTEB (avg 100+ idiomas): ~55
Uso: General purpose multiidioma
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('distiluse-base-multilingual-cased-v2')
2. XLM-RoBERTa:
Idiomas: 100
Dimensiones: 768
MTEB: ~58
Uso: Mejor performance que mBERT
model = SentenceTransformer('xlm-r-100langs-bert-base-nli-stsb-mean-tokens')
3. BGE-M3 (BAAI Multilingual):
Idiomas: 100+
Dimensiones: 1024
MTEB: ~64 (en promedio)
Uso: Estado del arte multiidioma
model = SentenceTransformer('BAAI/bge-m3')
4. Cohere Multilingual (API):
Idiomas: 100+
Dimensiones: 1024
MTEB: ~62
Costo: $0.10/1M tokens
# Uso con Cohere API
import cohere
co = cohere.Client('YOUR_API_KEY')
response = co.embed(texts=["Hola mundo"], model="embed-multilingual-v3.0")
Zero-Shot vs Fine-Tuning
Zero-Shot (usar modelo pre-entrenado sin modificar):
# Ventajas:
✅ No requiere datos de entrenamiento
✅ Funciona "out-of-the-box"
✅ Zero effort
# Desventajas:
❌ Performance subóptima en dominio específico
❌ No captura vocabulario único de tu dominio
Cuándo usar:
- Prototipado
- Dominio general (e-commerce, FAQ)
- No tienes datos de entrenamiento
Fine-Tuning (re-entrenar embeddings en tu dominio):
# Ventajas:
✅ Performance +10-30% en tu dominio
✅ Captura vocabulario específico
✅ Aprende relaciones de tu data
# Desventajas:
❌ Requiere datos de entrenamiento (1K-10K pares)
❌ Tiempo de entrenamiento (horas-días)
❌ ML expertise requerido
Cuándo usar:
- Dominio muy específico (legal, medical)
- Tienes datos de entrenamiento
- Performance crítica (vale el effort)
Comparison table:
| Criterio | Zero-Shot | Fine-Tuning |
|---|---|---|
| Effort | Bajo | Alto |
| Data required | 0 | 1K-10K pares |
| Time | Minutos | Horas-días |
| Performance (general) | Bueno | N/A |
| Performance (domain) | Aceptable | Excelente |
| Cost | $0 | $50-$500 (GPU) |
Ejemplos prácticos
1. Multilingual embeddings:
from sentence_transformers import SentenceTransformer
import numpy as np
# Cargar modelo multilingual
model = SentenceTransformer('distiluse-base-multilingual-cased-v2')
# Textos en diferentes idiomas (mismo significado)
texts = [
"The cat is sleeping", # English
"El gato está durmiendo", # Español
"Le chat dort", # Français
"猫在睡觉", # 中文
"القط نائم" # العربية
]
# Generar embeddings
embeddings = model.encode(texts)
# Calcular similarities
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# Comparar inglés con otros idiomas
en_emb = embeddings[0]
for i, lang in enumerate(["Español", "Français", "中文", "العربية"]):
sim = cosine_similarity(en_emb, embeddings[i+1])
print(f"English vs {lang}: {sim:.4f}")
Output esperado:
English vs Español: 0.87
English vs Français: 0.85
English vs 中文: 0.82
English vs العربية: 0.80
Embeddings capturan significado cross-lingual.
2. Domain-specific (code search):
from sentence_transformers import SentenceTransformer
# Modelo general
model_general = SentenceTransformer('all-MiniLM-L6-v2')
# Modelo code-specific (si existe)
# model_code = SentenceTransformer('microsoft/codebert-base')
query = "function to sort array"
docs = [
"def sort_array(arr): return sorted(arr)",
"function sortArray(arr) { return arr.sort(); }",
"The weather is nice today"
]
# Generar embeddings
query_emb = model_general.encode([query])[0]
docs_embs = model_general.encode(docs)
# Similarities
sims = [cosine_similarity(query_emb, doc_emb) for doc_emb in docs_embs]
for doc, sim in zip(docs, sims):
print(f"{sim:.4f} | {doc[:50]}...")
Output (modelo general):
0.65 | def sort_array(arr): return sorted(arr)...
0.63 | function sortArray(arr) { return arr.sort(); }...
0.35 | The weather is nice today...
Con modelo code-specific (CodeBERT), scores serían más altos (~0.85).
Evaluar embeddings en tu dominio
Crear dataset de evaluación:
# Formato:
evaluation_pairs = [
{
"query": "How to install Python?",
"doc_relevant": "Download Python from python.org",
"doc_irrelevant": "JavaScript is a web language"
},
# ... más pares
]
# Mínimo: 100 pares (cuanto más, mejor)
Evaluar modelo:
from sentence_transformers import SentenceTransformer
import numpy as np
def evaluate_model(model_name, eval_pairs):
"""
Evaluar modelo en dataset custom
Returns:
Accuracy (% de veces que doc_relevant > doc_irrelevant)
"""
model = SentenceTransformer(model_name)
correct = 0
for pair in eval_pairs:
query_emb = model.encode([pair['query']])[0]
rel_emb = model.encode([pair['doc_relevant']])[0]
irrel_emb = model.encode([pair['doc_irrelevant']])[0]
sim_rel = np.dot(query_emb, rel_emb)
sim_irrel = np.dot(query_emb, irrel_emb)
if sim_rel > sim_irrel:
correct += 1
accuracy = correct / len(eval_pairs)
return accuracy
# Test
evaluation_pairs = [
{
"query": "Python installation",
"doc_relevant": "Download from python.org",
"doc_irrelevant": "JavaScript is popular"
},
# ... más pares
]
accuracy = evaluate_model("all-MiniLM-L6-v2", evaluation_pairs)
print(f"Accuracy: {accuracy:.2%}")
Cuándo NO fine-tune
Casos donde zero-shot es suficiente:
✅ Dominio general (e-commerce, FAQ)
✅ No tienes datos de entrenamiento
✅ Presupuesto/tiempo limitado
✅ Modelo general ya tiene >85% accuracy en tu eval
Casos donde fine-tune vale la pena:
✅ Dominio muy específico (legal, medical, code)
✅ Tienes 1K+ pares de entrenamiento
✅ Performance crítica (cada % de accuracy importa)
✅ Modelo general tiene <80% accuracy
✅ Presupuesto para ML Engineering
Ejercicios
Ejercicio 1: Multilingual embeddings
Usa distiluse-base-multilingual-cased-v2 para comparar:
# Textos:
# - "Hello world" (English)
# - "Hola mundo" (Español)
# - "Bonjour le monde" (Français)
# ¿Cuál es más similar entre sí?
Ver solución
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer('distiluse-base-multilingual-cased-v2')
texts = [
"Hello world",
"Hola mundo",
"Bonjour le monde"
]
embeddings = model.encode(texts)
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
print("Similarities:")
print(f"EN vs ES: {cosine_similarity(embeddings[0], embeddings[1]):.4f}")
print(f"EN vs FR: {cosine_similarity(embeddings[0], embeddings[2]):.4f}")
print(f"ES vs FR: {cosine_similarity(embeddings[1], embeddings[2]):.4f}")
Output esperado:
Similarities:
EN vs ES: 0.88
EN vs FR: 0.86
ES vs FR: 0.89 ← Más similar (ambos idiomas latinos)
Ejercicio 2: Evaluar en dominio
Crea 5 pares de evaluación para tu dominio y evalúa all-MiniLM-L6-v2:
# Implementa función evaluate_model()
# Crea evaluation_pairs (mínimo 5)
# Calcula accuracy
Ver solución
evaluation_pairs = [
{
"query": "Python installation",
"doc_relevant": "Download Python from python.org",
"doc_irrelevant": "JavaScript is a web language"
},
{
"query": "List comprehension syntax",
"doc_relevant": "[x for x in range(10)]",
"doc_irrelevant": "Java uses for loops"
},
{
"query": "Django tutorial",
"doc_relevant": "Django is a Python web framework",
"doc_irrelevant": "React is a JavaScript library"
},
{
"query": "NumPy array",
"doc_relevant": "np.array([1, 2, 3])",
"doc_irrelevant": "Arrays in C are different"
},
{
"query": "Virtual environment",
"doc_relevant": "Use venv or virtualenv in Python",
"doc_irrelevant": "Docker containers isolate apps"
}
]
accuracy = evaluate_model("all-MiniLM-L6-v2", evaluation_pairs)
print(f"Accuracy en dominio Python: {accuracy:.2%}")
Resumen
Qué aprendiste:
- ✅ Domain-specific: Legal, medical, code (mejora +10-30%)
- ✅ Multilingual: mBERT, XLM-R, BGE-M3 (100+ idiomas)
- ✅ Zero-shot: Usar pre-entrenado (fácil, suficiente si >85% accuracy)
- ✅ Fine-tuning: Re-entrenar (effort alto, mejora +10-30%)
- ✅ Evaluación custom: Crear dataset de tu dominio
Conceptos clave:
- Dominio específico mejora performance significativamente
- Multilingual crítico para non-English
- Fine-tune solo si vale el effort (>$500, semanas)
Recursos adicionales
- BioBERT - Medical embeddings
- Legal-BERT - Legal embeddings
- CodeBERT - Code embeddings
- BGE-M3 - Multilingual SOTA
En la siguiente cápsula
Cápsula 08: Mini-Proyecto - Benchmark Framework
Construirás:
- Comparar 3+ modelos
- Métricas: MTEB, latencia, costo
- Reportes automáticos
- Recomendación final
De teoría a proyecto completo.
Módulo 3 - Embeddings Deep Dive Guide Domain-specific y multilingual: cuando generalista no es suficiente