Sintetizador de Datos: Cómo construí un generador de datos tabulares
21 oct 2025 (hace 3 meses)
3 min de lectura
Crear una app web ligera que permita subir un CSV, entrenar un modelo generativo (GaussianCopula / CTGAN / TVAE) y descargar un dataset sintético, todo corriendo en CPU dentro de Hugging Face Spaces.
En muchos proyectos reales no es posible compartir datos por temas de privacidad o compliance. Los datos sintéticos permiten:
- Publicar demos sin exponer información sensible.
- Aumentar datos (data augmentation) y balancear clases raras.
- Probar pipelines/ETL y dashboards sin usar el dataset original.
Quise construir una herramienta simple, explicable y portable para mi portafolio: subir un CSV, aprender su distribución y generar un nuevo CSV que conserve patrones globales (distribuciones y correlaciones), sin copiar registros.
¿Qué hace?
- Upload obligatorio de un CSV (no hay datos precargados).
- Detección de tipos de columna y construcción de metadata.
- Entrenamiento de un sintetizador (GaussianCopula / CTGAN / TVAE) con parámetros ligeros.
- Generación de N filas sintéticas y descarga (
synthetic.csv). - Evaluación de calidad (0–1) con
sdmetricssi está disponible. - UI moderna con header degradado, cards y tabs (Cargar Datos · Entrenar & Evaluar).
Arquitectura y stack
- Interfaz: Streamlit (tabs + cards + estilos CSS propios)
- Modelado sintético: SDV
single_table(con fallback asdv.tabularpara compatibilidad) - Métricas:
sdmetrics.QualityReport - ML opcional: PyTorch (solo para CTGAN/TVAE)
- Manipulación: Pandas / NumPy
Browser ──▶ Streamlit UI
│
├─▶ Upload CSV → previsualización + limpieza ligera
│
├─▶ SDV.metadata (detección tipos)
│ ├─▶ GaussianCopula Synthesizer (CPU, rápido)
│ ├─▶ CTGAN Synthesizer (GAN, requiere torch; pac=1)
│ └─▶ TVAE Synthesizer (VAE, requiere torch)
│
├─▶ sample(N) → synthetic.csv (download)
└─▶ sdmetrics.QualityReport (score 0–1)
Modelos y “cuándo usarlos”
- GaussianCopula (CPU, sin PyTorch): baseline rápido y estable; ideal para demos y datasets pequeños/medianos o relaciones poco no lineales.
- CTGAN (PyTorch): mejor para mixtos con muchas categóricas/alta cardinalidad y modas múltiples; capturó mejor clases minoritarias. Forcé
pac=1para evitar asserts de PacGAN con batches comunes. - TVAE (PyTorch): entrenamiento estable y buena estructura global, sobre todo cuando predomina lo numérico; a veces “suaviza” extremos.
Incluí un recomendador que, según el dataset y la disponibilidad de PyTorch, sugiere modelo y parámetros por defecto (epochs, batch, sample).
Decisiones técnicas clave
- Importación perezosa de modelos: CTGAN/TVAE solo se importan cuando el usuario los elige, así la app corre con GaussianCopula incluso sin PyTorch.
- Compatibilidad SDV nueva/legacy: primero intento
sdv.single_table(CTGANSynthesizer/TVAESynthesizer/GaussianCopulaSynthesizer) y, si falla, hago fallback asdv.tabular. - Guardrails de demo: límite de 25 columnas, muestreos razonables y epochs bajos en CPU.
- Evaluación robusta:
sdmetrics.QualityReportconmetadata.to_dict()cuando está disponible. - Límite de upload: 5 MB desde la app +
server.maxUploadSizeen.streamlit/config.toml.
Despliegue en Hugging Face Spaces (CPU, gratis)
Front‑matter de README (o Settings → Runtime):
sdk: streamlit
app_file: app.py
python_version: 3.10
requirements.txt
streamlit>=1.36.0
pandas>=2.1.0
numpy>=1.24.0
sdv>=1.8.0,<2.0.0
sdmetrics>=0.12.0
scikit-learn>=1.3.0
scipy>=1.10.0
plotly>=5.20.0
torch>=2.1,<3.0 # opcional: solo si usarás CTGAN/TVAE
Persistencia: en el plan gratis, el almacenamiento es efímero; lo generado se descarga localmente.
Uso local
# 1) Crear entorno
conda create -n synth python=3.10 -y
conda activate synth
# 2) Instalar dependencias
pip install -r requirements.txt
# 3) Ejecutar
streamlit run app.py
Si vas a usar CTGAN/TVAE en CPU:
pip install "torch>=2.1,<3.0" --index-url https://download.pytorch.org/whl/cpu
Resultados y lecciones
- En datasets mixtos con categóricas de alta cardinalidad, CTGAN rindió mejor que TVAE y GaussianCopula.
- TVAE fue el más estable con pocos epochs en CPU.
- GaussianCopula es ideal como baseline y para demos públicas donde no quieres depender de PyTorch.
- Los límites (columnas/epochs) fueron clave para evitar timeouts y ofrecer una experiencia fluida en Spaces.