Saltar a contenido

Optimización de Modelos LLM

Tiempo de lectura: 25 minutos | Dificultad: Intermedia | Categoría: Inteligencia Artificial

Resumen

La optimización de modelos LLM es crucial para ejecutar modelos grandes en hardware limitado. Esta guía cubre técnicas como cuantización, pruning, distilación y estrategias de deployment que permiten reducir el uso de memoria y mejorar el rendimiento sin sacrificar significativamente la calidad.

🎯 Por Qué Optimizar Modelos LLM

Problemas Comunes sin Optimización

  • Memoria insuficiente: Modelos de 7B-70B parámetros requieren 14-140GB+ de RAM/VRAM
  • Velocidad lenta: Inferencia puede tomar segundos por token
  • Costos elevados: Hardware GPU caro para deployment
  • Escalabilidad limitada: Dificultad para servir múltiples usuarios

Beneficios de la Optimización

  • 70-90% menos memoria con cuantización 4-bit
  • 2-5x más velocidad de inferencia
  • Hardware más accesible: GPUs de gama media o CPUs
  • Mayor throughput: Más usuarios simultáneos
  • Costos reducidos: Menos hardware necesario

🔢 Cuantización (Quantization)

¿Qué es la Cuantización?

La cuantización reduce la precisión de los pesos del modelo de float32 (4 bytes) a formatos más pequeños como float16, int8 o int4, manteniendo la funcionalidad.

Tipos de Cuantización

1. Post-Training Quantization (PTQ)

  • Se aplica después del entrenamiento
  • No requiere re-entrenamiento
  • Rápida y sencilla de implementar
# Ejemplo con Ollama (GGUF quantization)
ollama pull llama2:7b
ollama pull llama2:7b-q4_0  # Versión cuantizada 4-bit

2. Quantization-Aware Training (QAT)

  • Se entrena considerando la cuantización
  • Mejor precisión pero más complejo
  • Usado en producción crítica

Niveles de Cuantización

Precisión Memoria Velocidad Calidad Uso
FP32 100% 100% 100% Entrenamiento
FP16 50% ~2x 99.9% GPUs modernas
INT8 25% ~4x 98-99% GPUs, CPUs
INT4 12.5% ~8x 95-97% CPUs, edge

Implementación Práctica

Con Ollama (GGUF)

# Descargar modelo base
ollama pull llama2:7b

# Crear modelo cuantizado personalizado
cat > Modelfile << EOF
FROM llama2:7b
PARAMETER temperature 0.8
PARAMETER top_p 0.9
QUANTIZE q4_0
EOF

ollama create llama2-custom:q4_0 -f Modelfile

Con llama.cpp

# Convertir y cuantizar modelo
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp

# Convertir PyTorch a GGML
python convert.py --model /path/to/model.bin --type f16

# Cuantizar a diferentes formatos
./quantize /path/to/model-f16.bin /path/to/model-q4_0.bin q4_0

🌿 Pruning (Poda)

Concepto Básico

El pruning elimina conexiones neuronales poco importantes, reduciendo el tamaño del modelo sin afectar significativamente el rendimiento.

Técnicas de Pruning

1. Weight Pruning

  • Elimina pesos individuales por debajo de un threshold
  • Efectivo pero requiere fine-tuning posterior

2. Structured Pruning

  • Elimina neuronas, capas o atención heads completas
  • Más eficiente para hardware
  • Ejemplos: eliminar 20-30% de atención heads

3. Dynamic Pruning

  • Ajusta la estructura durante inferencia
  • Trade-off entre calidad y velocidad

Ejemplo Práctico

import torch
from transformers import AutoModelForCausalLM

# Cargar modelo
model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-medium")

# Aplicar pruning (simplificado)
def prune_weights(model, threshold=0.1):
    for name, param in model.named_parameters():
        if 'weight' in name:
            mask = torch.abs(param) > threshold
            param.data *= mask.float()

prune_weights(model)

🧪 Distilación (Knowledge Distillation)

¿Qué es la Distilación?

La distilación transfiere conocimiento de un modelo grande ("teacher") a uno más pequeño ("student"), manteniendo la mayoría del rendimiento.

Proceso de Distilación

  1. Teacher Model: Modelo grande y preciso
  2. Student Model: Modelo pequeño a entrenar
  3. Soft Targets: El student aprende de las distribuciones de probabilidad del teacher
  4. Fine-tuning: Ajuste final en datos reales

Ventajas

  • Mejor ratio calidad/tamaño que cuantización sola
  • Modelo más pequeño pero inteligente
  • Transfer learning efectivo

Ejemplo con Hugging Face

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# Modelo teacher (grande)
teacher = AutoModelForCausalLM.from_pretrained("gpt2-large")

# Modelo student (pequeño)
student = AutoModelForCausalLM.from_pretrained("gpt2")

# Función de pérdida de distilación
def distillation_loss(student_logits, teacher_logits, temperature=2.0):
    soft_targets = torch.softmax(teacher_logits / temperature, dim=-1)
    student_soft = torch.log_softmax(student_logits / temperature, dim=-1)
    return torch.nn.functional.kl_div(student_soft, soft_targets, reduction='batchmean')

🚀 Estrategias de Deployment

1. CPU vs GPU Optimization

Optimizaciones para CPU

# Usar llama.cpp con optimizaciones CPU
./main -m model.bin --threads 8 --ctx-size 2048 -p "Prompt"

Optimizaciones para GPU

# Con vLLM
from vllm import LLM

llm = LLM(
    model="microsoft/DialoGPT-large",
    tensor_parallel_size=2,  # Multi-GPU
    gpu_memory_utilization=0.9,
    max_model_len=4096
)

2. Batch Processing

# Procesamiento por lotes para mayor throughput
prompts = ["Prompt 1", "Prompt 2", "Prompt 3"]

# Inferencia por lotes
outputs = llm.generate(prompts, max_tokens=100)

3. Model Caching y Prefilling

# Cache de KV para prompts comunes
from transformers import Cache

cache = Cache()
model = AutoModelForCausalLM.from_pretrained("gpt2", use_cache=True)

# Primera inferencia crea cache
output1 = model.generate("Common prefix", use_cache=True)

# Inferencias posteriores reutilizan cache
output2 = model.generate("Common prefix + continuation", past_key_values=output1.past_key_values)

📊 Benchmarks y Comparativas

Resultados Típicos de Optimización

Técnica Modelo Tamaño Original Tamaño Optimizado Degradación Velocidad
FP16 LLaMA-7B 13GB 6.5GB ~0% 2x
INT8 LLaMA-7B 13GB 3.5GB 1-2% 4x
INT4 LLaMA-7B 13GB 1.8GB 3-5% 8x
Pruning 20% GPT-2 1.5GB 1.2GB 2-3% 1.5x
Distilación BERT Large→Base 340M→110M params 67% menos 3-5% 2x

Hardware Recommendations

Hardware Modelo Máximo Técnica Recomendada
CPU (16GB RAM) 7B Q4 GGUF + llama.cpp
GPU RTX 3060 (12GB) 13B FP16 vLLM + tensor parallel
GPU RTX 4080 (16GB) 30B Q4 Ollama + cuantización
CPU Server (128GB) 70B Q4 llama.cpp + threads

🛠️ Herramientas y Frameworks

Frameworks de Optimización

1. GGUF (GPT-Generated Unified Format)

  • Formato de cuantización de llama.cpp
  • Compatible con múltiples plataformas
  • Optimizado para CPU y GPU
# Convertir modelo a GGUF
python convert-hf-to-gguf.py --model /path/to/model --outdir /output/dir

2. AWQ (Activation-aware Weight Quantization)

  • Cuantización que considera activaciones
  • Mejor precisión que PTQ estándar
  • Especialmente bueno para GPUs

3. GPTQ (GPT Quantization)

  • Cuantización post-entrenamiento
  • Mantiene alta calidad
  • Compatible con AutoGPTQ

Herramientas Prácticas

# Benchmark con llama.cpp
./llama-bench -m model.gguf -p 512 -n 128 -t 8

# Perfilado de memoria
python -c "
import torch
from transformers import AutoModel
model = AutoModel.from_pretrained('model')
print(f'Model size: {sum(p.numel() for p in model.parameters()) / 1e6:.1f}M parameters')
print(f'Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB')
"

⚠️ Consideraciones y Limitaciones

Trade-offs Importantes

  • Precisión vs Velocidad: Más cuantización = más velocidad pero menos precisión
  • Calidad vs Tamaño: Modelos más pequeños pueden perder capacidades específicas
  • Hardware vs Software: Optimizaciones dependen del hardware objetivo

Errores Comunes

  1. Cuantización excesiva: INT2/INT3 puede hacer modelos inutilizables
  2. Pruning agresivo: Eliminar >50% puede causar colapso del rendimiento
  3. Ignorar fine-tuning: Modelos optimizados necesitan ajuste posterior

Mejores Prácticas

  • Probar exhaustivamente después de optimizar
  • Monitorear calidad con métricas automatizadas
  • A/B testing entre versiones optimizadas
  • Documentar trade-offs para stakeholders

🔗 Recursos Adicionales

📚 Próximos Pasos

Después de optimizar modelos, considera:

  1. Chatbots Locales - Construir interfaces conversacionales
  2. Prompt Engineering - Técnicas para mejores resultados
  3. Deployment en Producción - Servir modelos optimizados a escala

¿Has optimizado algún modelo LLM? Comparte tus experiencias y mejores prácticas en los comentarios.