Abrir en Google Colab Abrir en Binder Descargar notebook

Validación con datos generados sintéticamente

PRECAUCIÓN 😱: El tema presentado en esta sección está clasificado como avanzado. El entendimiento de este contenido es totalmente opcional.

No siempre es sencillo tener acceso a repositorios de datos que sean lo suficientemente grandes y con valores realistas (como ser nombre, edad, dirección, fecha de nacimiento, sexo, etc). Disponer de estos conjuntos de datos es útil no solo para aquellas personas que desean probar diferentes técnicas o modelos de aprendizaje automático, sino que también son muy interesantes para validadores de software (testers) que les gustaría tener un conjuntos de datos arbitrariamente grande (aunque con datos ficticios) sobre los cuales ejecutar pruebas de calidad de los modelos de aprendizaje que otros desarrolladores crearon. Esto facilita la posibilidad de probar determinados casos de borde sin necesidad de modificar datos manualmente ni tener que crear de forma artesanal conjuntos de datos para las validaciones.

Sobre los datos sintéticos

Los conjuntos de datos sintéticos son conjuntos de datos generados a traves de procesos artificiales con el proposito de mantener la privacidad de los datos originales, realizar validaciones de un sistema o pruebas de carga o simplemente verificar un modelo de aprendizaje automático. En general, los datos sintéticos se generan de tal forma que «imitan» la distribución o representación de un conjunto de datos real, pero sin necesidad de revelar ningún detalle del conjunto de datos original. En algunos casos puede ser que los datos generados sintéticamente no tengan el mismo valor que los datos reales, pero existen muchos otros casos donde pueden tener incluso el mismo valor. Muchos modelos de aprendizaje automático son entrenados con datos generados sintéticamente.

Las generación de datos sintéticos se utiliza incluso durante el proceso de entrenamiento de modelos, con técnicas como SMOTE que permiten correjir el balance de clases en conjuntos de datos desbalanceados. Sin embargo, en esta sección no nos centraremos en tales típos de técnicas.

Técnicas para la generación de datos sintéticos

Existen multiples técnicas para la generación de datos sintéticos dependiendo de los requerimientos de negocio y de las características de los conjuntos de datos que estamos buscando.

Generarlos desde distribuciones conocidas

Aunque en la práctica no es el caso más habitual, puede ser que conoscamos la distribución de los datos que necesitamos, como ser una distribución normal, exponencial, binomial, etc. En tales casos, muchas librerías de aprendizaje automático nos permiten generar conjuntos de datos de tamaños arbitrales que se condicen con estas distribuciones.

Utilizando librerías espécificas

Existen librerías específicas para generar conjuntos de datos sintéticos en múltiples lenguajes. En Python, librerías como las siguientes pueden ser utilizadas:

  • faker: Es una librería que no solo permite la generación de tipos de datos simples, sino que también datos como nombres, direcciones, teléfonos o correos electrónicos.

  • SymPy: Es una libería de alta performance que permite generar datos a traves de expresiones simbólicas.

  • PyDBGen: Es una librería que permite generar datos categóricos localizados (localized) para diferentes paises e idiomas. Puede generar conjuntos de datos tanto en archivos como csv o txt como directamente en tablas de bases de datos.

  • mimesis: Es una librería similar a faker, aunque provee multiples formas de extender sus funcionalidades.

Utilizando modelos generativos

Modelos generativos, como son Variational Autoencoders (VAE) o Generative Adversarial Networks (GAN) puede generar datos sintéticos con un nivel de detallé importante. Muchas técnicas de aumento de datos (data augmentation) descansan en este tipo de modelos.

Ejemplos

Mimesis

Mimesis es una libería de Python que permite generar conjuntos de datos sintéticos. Mimesis no solo permite la generación de tipos de datos simples, sino que también puede generar datos como nombres, direcciones, teléfonos o direcciones de correo electrónico. Esta información la puede generar para diferentes locations incluyendo el idioma Español. Lamentablemente, no dispone de una implementación específica para Argentina, siendo las variaciones más aproximadas las de Mexico (es-mx) o España (es). Mimesis es extensible, lo que significa que si existe un tipo de dato que no es soportado actualmente, se lo puede implementar para que la librería lo genere. Es ampliamente utilizado por la comunida de código abierto por lo que existen multiples extensiones ya creadas.

Para más información sobre Mimesis puede revisar la documentación oficial.

[23]:
%pip install mimesis==18.0.0
Requirement already satisfied: mimesis==18.0.0 in /usr/local/lib/python3.11/dist-packages (18.0.0)
[10]:
import mimesis
import mimesis.schema

person = mimesis.Person(locale="es")
numbers = mimesis.Numeric()

Por ejemplo, si quisieramos generar un nombre de una persona generalmente asociado a sexo femenino, podríamos hacer los siguiente:

[ ]:
print(person.full_name(gender=mimesis.enums.Gender.FEMALE))
Nieves Molina

De forma similar, podriamos generar la edad de una persona mayor a 21 años como sigue:

[11]:
print(numbers.integer_number(start=21, end=100))
38

Esta libreria nos permite generar conjuntos completos de datos de forma rápida indicando un esquema de datos. En el siguiente ejemplo, crearemos un conjunto de datos con varios campos, para luego construir un DataFrame de Pandas:

[20]:
field = mimesis.schema.Field(locale="es")
description = (
    lambda: {
        'id': field('uuid'),
        'creator': field('full_name', gender=mimesis.enums.Gender.FEMALE),
        'age': field('integer_number', start=21, end=100),
        'timestamp': field('datetime.datetime'),
        'word': field('text.word'),
        'email': field('person.email', domains=['outlook.com', 'gmail.com', 'yahoo.com'], key=str.lower),
    }
)

sample_schema = mimesis.schema.Schema(schema=description)

Creamos un Pandas.DataFrame con 100 muestras:

[21]:
import pandas as pd

sample_schema.iterations = 100

pd.DataFrame(sample_schema.create())
[21]:
id creator age timestamp word email
0 33fb7ea0-5a17-433a-a0e3-fcf5cedd8542 Narcisa Medina 87 2025-11-09 05:55:49.599516 viendo watershed1805@yahoo.com
1 df6a5130-949a-48b5-86ac-4fcb1f438613 Rosalía Lopez 83 2025-10-28 04:21:49.607131 rápido wife1990@outlook.com
2 55d77079-0370-4831-861f-30345bd474d3 Jessica Moya 38 2025-12-18 21:34:31.034018 toques rings2053@yahoo.com
3 67596f2d-5640-4073-bb3b-c40b3a36a130 Amalia Suarez 32 2025-11-24 13:27:43.362711 medicina portugal1850@gmail.com
4 2273bf27-27c4-48bf-9915-f34420279a3d Meagens Santos 86 2025-12-16 05:53:38.754638 damas rack2022@outlook.com
... ... ... ... ... ... ...
95 339bdc41-0cc3-4598-bf46-57cdbb548732 Begoña Fuentes 86 2025-04-26 07:33:08.491777 respuesta declare2001@yahoo.com
96 adf7546c-759c-43c6-823b-24f1b9571d8d Patricia Roman 42 2025-04-22 03:30:03.276388 parque kernel2053@yahoo.com
97 4294fdac-5faa-45a3-a18a-f6d85e8ded14 Froilana Mendez 25 2025-03-10 03:57:08.649930 pantalones senate1969@outlook.com
98 c76a3f9c-51c0-4d13-99c7-ebe6b3dbebda Teresa Diaz 76 2025-07-28 17:15:43.511954 esperaba replace1830@yahoo.com
99 b5617d1e-b148-4fa0-8116-1d26f003e794 Noe Vidal 47 2025-04-25 20:24:44.440473 apoyo determined1945@gmail.com

100 rows × 6 columns

CTGAN

CTGAN es un técnica que ha ganado popularidad ya que se basa en la arquitectura GAN para modelar datos tabulares y muestrear filas condicionalmente a partir de un modelo generado especificamente para crear datos sintéticos. Al momento, esta representa una de las técnicas más avanzadas para la generación de datos sintéticos.

Xu, Lei and Skoularidou, Maria and Cuesta-Infante, Alfredo and Veeramachaneni, Kalyan. Modeling Tabular data using Conditional GAN. Advances in Neural Information Processing Systems. 2019

Para demostrar como realizar validaciones utilizando conjunto de datos sintéticos, trabajaremos con el conjunto de datos de “Pima Indians Diabetes Database” (https://www.openml.org/d/37), proveniente originalmente del National Institute of Diabetes and Digestive and Kidney Diseases. El objetivo del conjunto de datos es el de predecir si un paciente tiene o no diabetes, basado en ciertas mediciones que se incluyen. Este conjunto es interesante para esta demostración porque tiene varias restricciones en cuanto a como se recolectaron los datos. En particular, todos los pacientes son de sexo femenino, de al menos 21 años y de ascendencia india Prima.

[ ]:
%pip install ctgan
[24]:
import pandas as pd
import sklearn.datasets as datasets

data = datasets.fetch_openml(name='diabetes', version=1)
df = pd.DataFrame(data['data'], columns=data['feature_names'])
df['target'] = data['target'].astype('object')

Veamos como luce el conjunto de datos

[25]:
df.head(10)
[25]:
preg plas pres skin insu mass pedi age target
0 6 148 72 35 0 33.6 0.627 50 tested_positive
1 1 85 66 29 0 26.6 0.351 31 tested_negative
2 8 183 64 0 0 23.3 0.672 32 tested_positive
3 1 89 66 23 94 28.1 0.167 21 tested_negative
4 0 137 40 35 168 43.1 2.288 33 tested_positive
5 5 116 74 0 0 25.6 0.201 30 tested_negative
6 3 78 50 32 88 31.0 0.248 26 tested_positive
7 10 115 0 0 0 35.3 0.134 29 tested_negative
8 2 197 70 45 543 30.5 0.158 53 tested_positive
9 8 125 96 0 0 0.0 0.232 54 tested_positive

Entrenemos un modelo basado en la arquitectura de CTGAN para generar sintéticamente instancias pertenecientes a este conjunto de datos. Preste especial atención a los valores especificados en la variable discrete_columns donde indicamos aquellas variables que son categoricas. Las restantes variables serán consideradas como continuas.

[27]:
from ctgan import CTGAN

discrete_columns = ['preg', 'age', 'target']

ctgan = CTGAN(epochs=5)
ctgan.fit(df, discrete_columns)
[28]:
ctgan.sample(10)
[28]:
preg plas pres skin insu mass pedi age target
0 1 135 46 37 98 31.233694 2.772864 45 tested_positive
1 11 180 40 3 482 24.726927 0.578021 25 tested_negative
2 2 128 68 7 79 48.442813 0.135262 54 tested_negative
3 4 132 81 37 68 32.928613 0.582547 70 tested_positive
4 9 133 80 -7 489 34.210912 0.551240 59 tested_negative
5 1 97 61 32 364 51.610659 0.807465 21 tested_positive
6 13 151 84 3 111 45.342234 0.391592 34 tested_positive
7 1 218 76 14 154 29.559014 0.173615 38 tested_negative
8 1 161 25 4 572 34.164945 0.340733 27 tested_negative
9 12 100 77 21 499 -20.287110 0.568273 33 tested_negative

Nota

Note que variables como age y preg que representan la edad de la persona y la cantidad de veces que ha estado embarazada fueron configuradas como variables categoricas. Esto permite que nuestro modelo 1) no genere valores continuos, como ser 20.5 para la edad, y 2) que no utilice valores que se encuentren fuera de los valores que ya existen en el conjunto de datos. En algunos casos, sobre todo considerando escenarios de testing, este comportamiento podría no ser el deseado.