Abrir en Google Colab
|
|
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 | ||
|---|---|---|---|---|---|---|
| 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.
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.
Abrir en Google Colab
Descargar notebook