Terminamos la lección anterior constatando que la mayoría de los sistemas que NovaMarket va a construir son subsimbólicos: aprenden de datos. Esta lección se dedica a esa materia prima. Marta lleva semanas diciéndolo en cada reunión: "antes de hablar de modelos, hablemos de qué datos tenemos y en qué estado están". Tiene razón, y en esta lección veremos por qué. Explicaremos por qué los datos son el combustible de la IA, qué tipos de datos existen y cómo se organizan, cuál es el ciclo de vida del dato en una organización, cómo se mide su calidad y qué problemas concretos esconden los ficheros de NovaMarket, de dónde vienen los sesgos que después se convierten en decisiones injustas, qué obligaciones conceptuales impone la protección de datos personales y por qué la calidad importa más que la cantidad. Cerraremos con un programa en Python que lee un pedidos.csv de ejemplo y produce un pequeño informe de calidad, exactamente el tipo de comprobación que debería preceder a cualquier proyecto de IA.
Contenido
- Por qué los datos son el combustible de la IA
- Tipos de datos
- Datos etiquetados y no etiquetados
- El ciclo de vida del dato: recogida, almacenamiento, calidad, gobernanza
- Dimensiones de la calidad de los datos, con los problemas reales de NovaMarket
- Sesgo en los datos: el origen de la injusticia algorítmica
- Datos personales y RGPD: minimización, anonimización y seudonimización
- Cantidad frente a calidad; datos sintéticos
- Ejemplo en Python: un informe de calidad de
pedidos.csv
- Por qué los datos son el combustible de la IA
Recuerda el esquema de 01-02: en la programación tradicional, datos + programa → resultados; en el aprendizaje automático, datos + resultados → modelo, y después el modelo produce resultados para datos nuevos. El modelo no contiene más conocimiento que el que había en los datos con los que se construyó. De ahí se derivan tres consecuencias que conviene grabarse:
- Sin datos no hay modelo. El recomendador de 01-03 no podía recomendar nada para el televisor hasta que hubo pedidos con televisores (el "arranque en frío").
- Con datos malos hay modelos malos. La expresión clásica es garbage in, garbage out: si el 50 % de la columna "causa" de
incidencias.csvestá vacía, ningún algoritmo va a diagnosticar bien las incidencias. - El modelo hereda todo lo que hay en los datos, incluidos los errores, las lagunas y los sesgos. Si históricamente NovaMarket revisó más los pedidos de ciertos códigos postales, un modelo entrenado con ese historial aprenderá a sospechar de esos códigos postales (lo desarrollaremos en la sección 6 y en 02-04).
Por eso, en un proyecto real de IA, entre el 60 % y el 80 % del esfuerzo se dedica a obtener, entender, limpiar y preparar datos, no a entrenar modelos. Es lo primero que Marta quiso que Diego entendiera: el "coste de la IA" es en gran parte el coste de poner en orden los datos, y ese coste se amortiza en todos los proyectos posteriores.
- Tipos de datos
Los datos se clasifican de varias maneras complementarias. Conocerlas ayuda a saber qué técnica se puede aplicar y qué preparación necesitarán.
2.1 Por su estructura
| Tipo | Qué es | Ejemplos en NovaMarket | Cómo se trabaja |
|---|---|---|---|
| Estructurados | Tablas con filas y columnas de tipo fijo | pedidos.csv, clientes.csv, productos.csv, la base de datos de stock |
Consultas SQL, hojas de cálculo, ML clásico directamente |
| Semiestructurados | Tienen etiquetas o jerarquía, pero no un esquema rígido | Respuestas JSON de la API de la mensajería, ficheros de log del servidor web, correos con cabeceras | Hay que extraer campos antes de analizarlos |
| No estructurados | Sin organización predefinida | Texto libre de resenas.csv, transcripciones del chat de atención al cliente, fotos de productos devueltos, audios de llamadas |
Requieren PLN, visión por computador o extracción previa |
La mayoría del volumen de datos de una empresa es no estructurado, y la mayoría del valor histórico se ha extraído de los estructurados. El deep learning (módulo 5) cambió eso al hacer explotable el texto y la imagen.
2.2 Por la naturaleza del valor
| Tipo | Descripción | Ejemplos | Observación |
|---|---|---|---|
| Numéricos | Cantidades con las que tiene sentido operar | Importe del pedido, peso del paquete, unidades vendidas | Pueden ser continuos (importe) o discretos (unidades) |
| Categóricos | Etiquetas de un conjunto finito | Ciudad, categoría de producto, estado del pedido, causa de la incidencia | Sin orden (nominal: ciudad) o con orden (ordinal: talla S/M/L, satisfacción 1-5) |
| Texto | Cadenas de lenguaje natural | Reseñas, mensajes del chat, descripciones de producto | No estructurado; requiere PLN |
| Imagen / audio / vídeo | Señales percibidas | Fotos de productos, fotos de daños en devoluciones, llamadas | No estructurado; requiere visión o procesamiento de señal |
| Series temporales | Valores numéricos ordenados en el tiempo | Ventas diarias por producto, tráfico web por hora, tiempos de entrega | El orden importa; base de la previsión de demanda |
| Fechas e identificadores | Marcas de tiempo, claves | fecha, id_pedido, id_cliente |
Ni numéricos ni categóricos "de verdad": sirven para relacionar y ordenar |
Un mismo fichero mezcla varios: pedidos.csv tiene identificadores, una fecha, un importe numérico, una ciudad categórica y una columna devuelto categórica binaria. Saber qué es cada columna es el primer paso de cualquier análisis, y es sorprendente cuántos problemas vienen de tratar un identificador como número (sumar códigos postales) o un número como texto (ordenar importes alfabéticamente: "1000" antes que "200").
- Datos etiquetados y no etiquetados
Una distinción decisiva para el aprendizaje automático:
- Datos etiquetados: cada ejemplo lleva asociada la respuesta correcta que queremos que el modelo aprenda a producir. En
pedidos.csv, la columnadevueltoes la etiqueta si queremos predecir devoluciones. Enresenas.csv, una columna "sentimiento" (positivo/negativo) puesta por una persona sería la etiqueta. - Datos no etiquetados: solo tenemos los ejemplos, sin respuesta. Miles de reseñas sin clasificar, el historial de navegación sin saber qué acabó comprando el cliente.
Con datos etiquetados se puede hacer aprendizaje supervisado (aprender la relación entre las características y la etiqueta); con datos no etiquetados, aprendizaje no supervisado (descubrir estructura: grupos de clientes parecidos, productos que se compran juntos). Ambos se desarrollan en 04-02; aquí basta con saber que las etiquetas son caras (a menudo hay que ponerlas a mano) y valiosas, y que su calidad condiciona todo.
Un ejemplo de lo cara y delicada que es la etiqueta: incidencias.csv tiene unos 400 registros y la mitad de la columna causa vacía. Esa columna es la etiqueta que el caso de uso 9 (diagnóstico de incidencias) necesitaría aprender. Con 200 ejemplos etiquetados de forma desigual (los operadores rellenaban la causa cuando tenían tiempo, es decir, más en los días tranquilos y menos en los picos), el sistema aprendería de una muestra sesgada. Diego propuso una solución no técnica pero correcta: hacer obligatoria la causa en el formulario a partir de ahora y organizar una sesión para etiquetar retrospectivamente las 200 que faltan.
- El ciclo de vida del dato: recogida, almacenamiento, calidad, gobernanza
Los datos no aparecen listos para usar; atraviesan un ciclo, y cada etapa puede introducir o corregir problemas:
flowchart LR
R[Recogida<br/>formularios, sensores,<br/>logs, APIs, compras] --> A[Almacenamiento<br/>bases de datos, ficheros,<br/>almacén de datos]
A --> C[Calidad<br/>validación, limpieza,<br/>deduplicación]
C --> U[Uso<br/>análisis, modelos,<br/>decisiones]
U --> G[Gobernanza<br/>propiedad, acceso,<br/>retención, cumplimiento]
G -.-> R
- Recogida: cómo entran los datos. Cada canal tiene sus vicios: el formulario web de devoluciones permite dejar campos vacíos; el terminal del almacén guarda el peso en gramos y la web en kilos; la mensajería externa envía las fechas en formato
DD/MM/AAAAmientras el sistema interno usaAAAA-MM-DD. La regla de oro es validar en origen: es mucho más barato obligar a rellenar la causa de la incidencia en el momento que reconstruirla meses después. - Almacenamiento: dónde y cómo se guardan. Bases de datos transaccionales (las que soportan la tienda), almacenes de datos para análisis, ficheros planos como los CSV con los que trabajamos en el curso. Aquí importan la trazabilidad (¿de dónde viene cada dato?, ¿cuándo se cargó?) y el esquema (qué significa cada columna, en qué unidades).
- Calidad: comprobar y corregir (sección 5). Idealmente es un proceso continuo, no un arreglo puntual antes de cada proyecto.
- Uso: análisis, informes, entrenamiento de modelos, decisiones. Es lo que justifica todo lo anterior.
- Gobernanza: el conjunto de normas y responsabilidades sobre los datos: quién es propietario de cada conjunto de datos (Marta propuso que cada área lo sea de los suyos: operaciones de
incidencias.csv, marketing deresenas.csv), quién puede acceder a qué, cuánto tiempo se conservan, cómo se documentan (un diccionario de datos con la definición de cada columna) y cómo se cumple la legislación (sección 7). La gobernanza cierra el ciclo porque sus normas mejoran la siguiente recogida.
Sin gobernanza, cada proyecto de IA vuelve a descubrir los mismos problemas. Con ella, el segundo proyecto de NovaMarket (previsión de demanda) reutiliza los datos limpios del primero (recomendación).
- Dimensiones de la calidad de los datos, con los problemas reales de NovaMarket
"Datos de calidad" no es un juicio vago: se descompone en dimensiones medibles. Las cinco más usadas, con los problemas que Marta encontró al abrir los CSV de NovaMarket por primera vez:
| Dimensión | Pregunta | Problema real encontrado en NovaMarket | Consecuencia si no se corrige | Posible corrección |
|---|---|---|---|---|
| Completitud | ¿Faltan valores? | La mitad de la columna causa de incidencias.csv está vacía; algunos pedidos sin codigo_postal |
El diagnóstico de incidencias no puede aprender; los modelos que usan código postal descartan filas | Hacer el campo obligatorio; etiquetar retrospectivamente; para el resto, decidir si imputar o descartar (04-03) |
| Exactitud | ¿Los valores son correctos? | Precios de productos.csv en céntimos en una parte del catálogo (importada de un proveedor) y en euros en el resto: un cable a "1299" |
Un modelo de previsión aprende que un cable vale más que un portátil; las medias se disparan | Unificar la unidad; detectar valores fuera de rango con reglas |
| Consistencia | ¿Los mismos hechos se representan igual en todas partes? | Fechas mezcladas: 2026-03-02, 02/03/2026, 03-03-2026; ciudad como "Zaragoza", "zaragoza", "ZARAGOZA " |
Ordenar por fecha falla; "Zaragoza" y "zaragoza" cuentan como ciudades distintas | Normalizar formatos y mayúsculas al cargar; validar en origen |
| Actualidad | ¿Los datos reflejan el estado presente? | Direcciones de clientes que no se actualizan; stock del almacén de Getafe con retraso de horas | Rutas mal planificadas; asignación de pedidos a almacenes sin stock | Definir la frecuencia de actualización aceptable por dato; marcar la fecha de última modificación |
| Unicidad | ¿Hay duplicados? | Clientes duplicados en clientes.csv (mismo correo con mayúsculas distintas o con un espacio final; misma persona con dos correos); un mismo pedido cargado dos veces |
El recomendador ve dos clientes donde hay uno; se cuentan ventas de más | Definir la clave de unicidad; deduplicar con normalización; evitar la doble carga |
Dos comentarios importantes:
- La calidad se mide, no se supone. Marta hizo lo que haremos en la sección 9: contar vacíos, duplicados y formatos por columna y ponerle números. Descubrir que un 58 % de las filas de una muestra tenía algún problema fue lo que convenció a Diego de dedicar tiempo a la limpieza antes que a los modelos.
- La calidad depende del uso. Un código postal vacío es irrelevante para clasificar reseñas y grave para planificar rutas. No existe "el" nivel de calidad: existe el suficiente para cada caso de uso.
Cómo se limpian estos problemas para preparar un modelo (imputación de valores, codificación de categorías, escalado, tratamiento de atípicos) es el contenido de 04-03; aquí nos quedamos en detectarlos y medirlos.
- Sesgo en los datos: el origen de la injusticia algorítmica
Un sesgo en los datos es una desviación sistemática entre lo que los datos representan y la realidad que deberían representar. No es un problema de "datos sucios" (los datos pueden estar limpísimos y sesgados) sino de qué se recogió, de quién y cómo se etiquetó. Como el modelo hereda lo que hay en los datos, el sesgo se convierte en decisiones sistemáticamente desviadas, y cuando esas decisiones afectan a personas, en injusticia algorítmica. Los tres orígenes principales:
| Tipo de sesgo | Qué ocurre | Ejemplo en NovaMarket | Efecto en el modelo |
|---|---|---|---|
| De muestreo | La muestra no representa a la población: unos grupos están sobrerrepresentados y otros casi ausentes | Las reseñas las escriben sobre todo clientes muy satisfechos o muy enfadados; los clientes de ciudades sin reparto propio apenas aparecen en incidencias.csv porque sus incidencias las gestiona la mensajería |
El clasificador de reseñas no reconoce opiniones templadas; el diagnóstico de incidencias no sabe nada de las ciudades con mensajería |
| Histórico | Los datos reflejan fielmente un pasado que era injusto o distinto | Durante años el equipo revisó manualmente más los pedidos de ciertos códigos postales; en el histórico esos códigos tienen más "fraude detectado" simplemente porque se buscó más allí | El modelo de riesgo aprende que esos códigos postales son de riesgo, y al revisar más allí encuentra más, reforzando el sesgo (bucle de retroalimentación) |
| De etiquetado | Las etiquetas las ponen personas (o procesos) con criterios inconsistentes o prejuicios | La causa de las incidencias la rellenan operadores distintos: unos ponen "error de almacén" donde otros ponen "producto dañado"; los días de pico se etiqueta peor |
El modelo aprende el criterio de cada operador, no la causa real |
Otros sesgos frecuentes: el de supervivencia (solo vemos los datos que "sobrevivieron": analizamos a los clientes que siguen comprando y olvidamos por qué se fueron los que se fueron), el de medición (un sensor o formulario captura peor a un grupo: el formulario de devoluciones en la app es más incómodo que en la web, así que los clientes de móvil rellenan menos) y el de confirmación en el análisis (buscar en los datos lo que ya creíamos, como la regla de 300 € de Diego).
Lo esencial en esta lección: el sesgo entra por los datos y se manifiesta en las decisiones. Cómo evaluar sus consecuencias éticas, cómo medir la disparidad entre grupos y qué hacer al respecto es el contenido de la próxima lección, 02-04.
- Datos personales y RGPD: minimización, anonimización y seudonimización
Buena parte de los datos de NovaMarket son datos personales: identifican o permiten identificar a una persona (nombre, correo, dirección, teléfono, historial de compras, incluso una combinación de código postal, fecha de nacimiento y sexo). En la Unión Europea su tratamiento está regulado por el Reglamento General de Protección de Datos (RGPD). Aquí no vamos a estudiar la norma (que se retoma en el marco regulatorio de 02-04) sino los principios que afectan directamente al trabajo con datos para IA:
- Finalidad y base jurídica: los datos se recogen para un fin concreto y con una base legal (contrato, consentimiento, interés legítimo...). Usar el historial de compras para recomendar productos puede encajar; usarlo para algo no previsto (venderlo, perfilar con fines ajenos) no.
- Minimización: recoger y usar solo los datos necesarios para el fin. Si para prever la demanda basta con la fecha, el producto, la ciudad y las unidades, no hace falta cargar el nombre y el correo del cliente en el conjunto de entrenamiento. Menos datos personales significa menos riesgo y menos obligaciones.
- Limitación del plazo de conservación: no guardar datos personales más tiempo del necesario. Esto choca con el instinto de "guardar todo por si sirve para entrenar algo"; hay que definir plazos.
- Derechos de las personas: acceso, rectificación, supresión ("olvido"), oposición al perfilado y a decisiones automatizadas con efectos significativos. Un modelo entrenado con los datos de un cliente que pide su supresión plantea preguntas prácticas que el proyecto debe prever.
- Seguridad: proteger los datos frente a accesos indebidos, especialmente cuando se copian a entornos de análisis o se envían a servicios en la nube (recuerda la dicotomía nube/dispositivo de 02-02).
Dos técnicas que reducen el riesgo y que aparecerán constantemente:
| Técnica | Qué hace | Ejemplo | ¿Sigue siendo dato personal? |
|---|---|---|---|
| Seudonimización | Sustituye los identificadores directos por un código; la correspondencia se guarda aparte y protegida | clientes.csv con id_cliente = C1001 en lugar del nombre y correo; la tabla que relaciona C1001 con la persona la custodia otro equipo |
Sí (se puede revertir con la tabla), pero con menor riesgo; el RGPD lo reconoce como medida de seguridad |
| Anonimización | Elimina o transforma los datos de manera que no sea posible volver a identificar a la persona, ni combinándolos con otros | Agregar ventas por ciudad y semana sin ningún identificador; generalizar el código postal a los dos primeros dígitos; eliminar campos únicos | No, si la anonimización es real. Pero es difícil de lograr: la combinación de pocos datos "inocentes" puede reidentificar |
Marta decidió que los conjuntos de datos que se usen para entrenar modelos en NovaMarket estén siempre, como mínimo, seudonimizados, y que la previsión de demanda trabaje con datos agregados (anónimos).
Aviso importante: todo lo anterior es una descripción conceptual con fines formativos, no asesoramiento jurídico. Cualquier proyecto que trate datos personales debe revisarse con el delegado de protección de datos o un profesional legal, que evaluará la base jurídica, la necesidad de una evaluación de impacto y las medidas concretas.
- Cantidad frente a calidad; datos sintéticos
Es habitual oír que "cuantos más datos, mejor". Es cierto a medias:
- Más datos ayudan cuando son variados y representativos: permiten aprender patrones más finos y reducen el peligro de que el modelo memorice casos concretos (el sobreajuste, tema de 04-06). Los grandes avances del deep learning se apoyaron en conjuntos enormes.
- Más datos malos no ayudan: multiplicar por diez un conjunto sesgado da un modelo diez veces más seguro de su sesgo. Doscientos ejemplos bien etiquetados de causas de incidencia valen más que dos mil etiquetados de cualquier manera.
- Los datos deben ser relevantes: para el recomendador de NovaMarket, los pedidos de otra tienda de otro sector aportan poco.
Regla práctica: primero calidad y representatividad; después, cantidad. Y mide siempre si más datos mejoran realmente el resultado.
Los datos sintéticos son datos generados artificialmente (mediante reglas, simulación o modelos generativos) que imitan las propiedades estadísticas de los reales. Se usan para: completar clases poco frecuentes (hay muy pocos fraudes reales de los que aprender), probar sistemas sin exponer datos personales, o simular escenarios que aún no han ocurrido (una campaña de Navidad para un producto nuevo). Tienen un límite evidente: solo contienen lo que quien los generó sabía o supuso; no descubren nada nuevo del mundo, y si se generan a partir de datos sesgados, heredan el sesgo. Son un complemento, no un sustituto.
- Ejemplo en Python: un informe de calidad de
pedidos.csv
pedidos.csvVamos a hacer lo que hizo Marta el primer día: leer un extracto de pedidos.csv, contar los problemas por dimensión y producir un pequeño informe. Para que el ejemplo sea autocontenido, el CSV está escrito dentro del programa como una cadena de texto; en la práctica lo leerías con open("pedidos.csv"). Solo usamos la biblioteca estándar: csv, io, re y collections.
9.1 Los datos y su lectura
import csv
import io
import re
from collections import Counter
DATOS_PEDIDOS = """id_pedido,id_cliente,fecha,importe,ciudad,codigo_postal,devuelto
48201,C1001,2026-03-02,89.90,Zaragoza,50001,no
48202,C1002,02/03/2026,15990,Madrid,28045,no
48203,C1003,2026-03-02,,Getafe,28901,si
48204,C1001,2026-03-03,45.00,zaragoza,50001,no
48205,C1004,03-03-2026,320.50,Valencia,46001,si
48206,C1005,2026-03-03,12.99,Madrid,,no
48207,C1002,2026-03-04,159.90,Madrid,28045,no
48202,C1002,02/03/2026,15990,Madrid,28045,no
48208,C1006,2026-13-04,75.00,Sevilla,41001,no
48209,,2026-03-04,210.00,Bilbao,48001,
48210,C1007,2026-03-05,58.40,Zaragoza,50002,no
48211,C1008,2026-03-05,1299.00,Getafe,28901,no
"""
def leer_pedidos(texto_csv):
# io.StringIO convierte la cadena en algo que se lee como un fichero.
# csv.DictReader devuelve cada fila como un diccionario {columna: valor}.
lector = csv.DictReader(io.StringIO(texto_csv))
return list(lector)
pedidos = leer_pedidos(DATOS_PEDIDOS)
print(f"Filas leidas: {len(pedidos)}")
print(pedidos[0])Salida:
Filas leidas: 12
{'id_pedido': '48201', 'id_cliente': 'C1001', 'fecha': '2026-03-02', 'importe': '89.90', 'ciudad': 'Zaragoza', 'codigo_postal': '50001', 'devuelto': 'no'}Explicación: csv.DictReader lee la primera línea como cabecera y convierte cada línea siguiente en un diccionario, lo que nos permite acceder a los valores por nombre (fila["importe"]). Observa que todo se lee como texto: '89.90' es una cadena, no un número; convertirlo será responsabilidad nuestra. Si miras los datos con atención ya verás los problemas sembrados: un importe vacío, un id_cliente vacío, un devuelto vacío, un codigo_postal vacío, tres formatos de fecha, una fecha con mes 13, un importe de 15990 que huele a céntimos, "zaragoza" en minúsculas y el pedido 48202 dos veces.
9.2 Completitud: contar vacíos por columna
def informe_completitud(filas):
columnas = filas[0].keys()
total = len(filas)
print(f"{'columna':15s} {'vacios':>7s} {'% vacios':>9s}")
for col in columnas:
vacios = sum(1 for f in filas if f[col].strip() == "")
print(f"{col:15s} {vacios:7d} {100*vacios/total:8.1f}%")
informe_completitud(pedidos)Salida:
columna vacios % vacios id_pedido 0 0.0% id_cliente 1 8.3% fecha 0 0.0% importe 1 8.3% ciudad 0 0.0% codigo_postal 1 8.3% devuelto 1 8.3%
Explicación: para cada columna recorremos las filas y contamos las que tienen la celda vacía tras quitar espacios (strip()); un espacio en blanco también es un vacío. La expresión sum(1 for f in filas if ...) es una forma compacta de contar. Con el incidencias.csv real, este informe es el que mostraría "causa: 50,0 %".
9.3 Unicidad: duplicados
def detectar_duplicados(filas, clave):
# Counter cuenta cuantas veces aparece cada valor de la clave.
contador = Counter(f[clave] for f in filas)
return {valor: veces for valor, veces in contador.items() if veces > 1}
print(detectar_duplicados(pedidos, "id_pedido")) # {'48202': 2}Explicación: Counter construye un diccionario valor → número de apariciones; nos quedamos con los que aparecen más de una vez. Aquí el duplicado es exacto (la misma fila cargada dos veces), el caso fácil. Los duplicados difíciles son los de clientes.csv: mismo cliente con correo en mayúsculas o con espacio final. Para esos, la clave habría que normalizarla antes de contar: f["email"].strip().lower(). Pruébalo como variante.
9.4 Consistencia: formatos de fecha mezclados
PATRONES_FECHA = {
"AAAA-MM-DD": re.compile(r"^\d{4}-\d{2}-\d{2}$"),
"DD/MM/AAAA": re.compile(r"^\d{2}/\d{2}/\d{4}$"),
"DD-MM-AAAA": re.compile(r"^\d{2}-\d{2}-\d{4}$"),
}
def clasificar_fecha(texto):
for nombre, patron in PATRONES_FECHA.items():
if patron.match(texto):
return nombre
return "desconocido"
formatos = Counter(clasificar_fecha(f["fecha"]) for f in pedidos)
print(formatos) # Counter({'AAAA-MM-DD': 9, 'DD/MM/AAAA': 2, 'DD-MM-AAAA': 1})Explicación: cada patrón es una expresión regular: ^\d{4}-\d{2}-\d{2}$ significa "exactamente cuatro dígitos, guion, dos dígitos, guion, dos dígitos". clasificar_fecha devuelve el nombre del primer patrón que encaja. El Counter final nos dice cuántas fechas hay de cada formato: tres filas no siguen el estándar. Ordenar o comparar esas fechas como texto daría resultados absurdos, y cualquier programa que esperase AAAA-MM-DD fallaría en ellas.
9.5 Exactitud: valores imposibles y unidades sospechosas
def fecha_valida(texto):
# Solo comprobamos las que ya tienen formato estandar.
if not PATRONES_FECHA["AAAA-MM-DD"].match(texto):
return False
anio, mes, dia = (int(x) for x in texto.split("-"))
return 1 <= mes <= 12 and 1 <= dia <= 31
imposibles = [f["id_pedido"] for f in pedidos
if clasificar_fecha(f["fecha"]) == "AAAA-MM-DD" and not fecha_valida(f["fecha"])]
print("Fechas imposibles:", imposibles) # ['48208'] (mes 13)
def importes_sospechosos(filas, umbral=5000):
sospechosos = []
for f in filas:
if f["importe"].strip() == "":
continue # el vacio ya lo contamos en completitud
valor = float(f["importe"])
if valor > umbral:
sospechosos.append((f["id_pedido"], valor))
return sospechosos
print("Importes sospechosos:", importes_sospechosos(pedidos))
# [('48202', 15990.0), ('48202', 15990.0)]Explicación: la exactitud no se puede comprobar del todo sin una fuente de verdad, pero sí podemos detectar valores imposibles (mes 13) y valores fuera del rango razonable (un pedido de 15.990 € en una tienda cuyo ticket medio ronda los 100 € huele a importe en céntimos: 159,90 €). El umbral de 5.000 € es una regla de negocio que fijó Diego. Fíjate en que el importe sospechoso aparece dos veces porque la fila está duplicada: los problemas de calidad se acumulan.
9.6 Consistencia de categorías
def informe_ciudades(filas):
tal_cual = Counter(f["ciudad"] for f in filas)
normalizadas = Counter(f["ciudad"].strip().lower() for f in filas)
print("Ciudades distintas tal cual:", len(tal_cual), sorted(tal_cual))
print("Ciudades distintas normalizadas:", len(normalizadas))
informe_ciudades(pedidos)Salida:
Ciudades distintas tal cual: 7 ['Bilbao', 'Getafe', 'Madrid', 'Sevilla', 'Valencia', 'Zaragoza', 'zaragoza'] Ciudades distintas normalizadas: 6
Explicación: contando los valores tal cual hay siete ciudades; normalizando (sin espacios, en minúsculas) hay seis. La diferencia es exactamente el número de inconsistencias. Este truco (comparar el número de valores distintos antes y después de normalizar) sirve para cualquier columna categórica.
9.7 El informe de calidad completo
def informe_calidad(filas):
total = len(filas)
print("=== INFORME DE CALIDAD: pedidos.csv ===")
print(f"Registros: {total}")
dup = detectar_duplicados(filas, "id_pedido")
print(f"Unicidad: {len(dup)} id_pedido repetidos {sorted(dup)}")
vacios = sum(1 for f in filas for col in f if f[col].strip() == "")
print(f"Completitud: {vacios} celdas vacias")
formatos = Counter(clasificar_fecha(f["fecha"]) for f in filas)
no_estandar = total - formatos.get("AAAA-MM-DD", 0)
print(f"Consistencia: {no_estandar} fechas fuera de AAAA-MM-DD")
imposibles = [f["id_pedido"] for f in filas
if clasificar_fecha(f["fecha"]) == "AAAA-MM-DD" and not fecha_valida(f["fecha"])]
sosp = importes_sospechosos(filas)
ids_sosp = {s[0] for s in sosp}
print(f"Exactitud: {len(imposibles)} fechas imposibles, {len(sosp)} importes sospechosos")
# Una fila es problematica si tiene al menos un problema de cualquier tipo
filas_con_problema = 0
for f in filas:
problema = (any(f[c].strip() == "" for c in f)
or dup.get(f["id_pedido"], 0) > 1
or clasificar_fecha(f["fecha"]) != "AAAA-MM-DD"
or f["id_pedido"] in imposibles
or f["id_pedido"] in ids_sosp)
if problema:
filas_con_problema += 1
porcentaje = 100 * filas_con_problema / total
print(f"Filas con algun problema: {filas_con_problema} de {total} ({porcentaje:.0f}%)")
print(f"Puntuacion de calidad: {100 - porcentaje:.0f}/100")
informe_calidad(pedidos)Salida:
=== INFORME DE CALIDAD: pedidos.csv === Registros: 12 Unicidad: 1 id_pedido repetidos ['48202'] Completitud: 4 celdas vacias Consistencia: 3 fechas fuera de AAAA-MM-DD Exactitud: 1 fechas imposibles, 2 importes sospechosos Filas con algun problema: 7 de 12 (58%) Puntuacion de calidad: 42/100
Explicación: el informe reúne las comprobaciones anteriores y añade una métrica global: el porcentaje de filas con al menos un problema. Un 58 % de filas problemáticas en una muestra pequeña y exagerada; en el fichero real de NovaMarket la cifra fue menor pero suficiente para justificar un proyecto previo de limpieza. La "puntuación de calidad" es una simplificación (todas las dimensiones pesan igual), pero convierte una sensación en un número que se puede seguir en el tiempo: el objetivo de Marta es que suba mes a mes. Como ejercicio mental, piensa qué añadirías para medir la actualidad (necesitarías una columna con la fecha de última actualización) y qué necesitarías para medir la exactitud de verdad (una fuente de referencia con la que comparar).
Errores Comunes y Consejos
- Empezar por el modelo. El impulso natural es entrenar algo cuanto antes. Empieza siempre por un informe de calidad como el de la sección 9; una hora de comprobaciones ahorra semanas de depurar por qué el modelo "hace cosas raras".
- Confiar en que un fichero limpio no está sesgado. Calidad y representatividad son cosas distintas. Pregunta siempre quién falta en los datos y por qué.
- Tratar el vacío como cero, o como una categoría más, sin pensarlo. Un importe vacío no es un importe de 0 €; una causa vacía no es "sin causa". Antes de decidir qué hacer con los vacíos hay que entender por qué faltan (¿es aleatorio o falta más en los días de pico?).
- Ignorar las unidades. Céntimos frente a euros, gramos frente a kilos, hora local frente a UTC. Documenta las unidades en el diccionario de datos y valida los rangos.
- Guardar todo "por si acaso". Choca con la minimización y la limitación de conservación del RGPD y aumenta el riesgo. Recoge y conserva lo necesario para un fin definido.
- Anonimizar quitando solo el nombre. Código postal + fecha de nacimiento + sexo identifican a una gran parte de la población. Si necesitas anonimizar de verdad, agrega o generaliza, y pide revisión experta.
- Consejo: crea el diccionario de datos desde el primer día (columna, significado, tipo, unidad, valores permitidos, quién es responsable). Es el documento más útil y menos glamuroso de un proyecto de IA.
Ejercicios
Ejercicio 1: Clasificar los datos de NovaMarket
Para cada uno de los cinco ficheros (clientes.csv, pedidos.csv, productos.csv, resenas.csv, incidencias.csv), indica: (a) si es estructurado, semiestructurado o no estructurado (o mixto: qué columnas de cada tipo); (b) qué columna podría ser una etiqueta y para qué caso de uso de la lista de 01-03; (c) si contiene datos personales y qué medida (seudonimización, anonimización, minimización) aplicarías antes de usarlo para entrenar.
Ejercicio 2: Sesgo en el modelo de riesgo de devolución
NovaMarket quiere entrenar un modelo que prediga si un pedido será devuelto, usando el histórico de pedidos.csv de los últimos tres años. Durante ese periodo: (i) las devoluciones de la app móvil se registraban en otro sistema y no están en el fichero; (ii) el equipo de Diego revisaba manualmente y anulaba muchas devoluciones "dudosas" de pedidos de más de 300 € (su antigua regla); (iii) la columna motivo_devolucion la rellenaban los clientes libremente. Identifica qué tipo de sesgo introduce cada circunstancia y qué efecto tendría en el modelo.
Ejercicio 3: Ampliar el informe de calidad
Amplía el programa de la sección 9 con dos comprobaciones: (a) el campo devuelto solo admite los valores si y no (cualquier otro, incluido el vacío, es un problema de consistencia); (b) el codigo_postal, cuando no está vacío, debe tener exactamente 5 dígitos y sus dos primeros dígitos deben ser coherentes con la ciudad para al menos estos casos: Zaragoza → 50, Madrid → 28, Getafe → 28 (problema de exactitud). Añade el recuento de ambos al informe.
Soluciones
Solución 1.
| Fichero | Estructura | Etiqueta posible (caso de uso) | Datos personales y medida |
|---|---|---|---|
clientes.csv |
Estructurado (nombre, correo, dirección, fecha de alta) | Ninguna evidente; podría añadirse "cliente activo/inactivo" para predecir abandono (no está en la lista de 9, pero es habitual) | Sí, plenamente: seudonimizar (sustituir nombre y correo por id_cliente); minimizar (¿hace falta la dirección completa para recomendar? probablemente basta la ciudad) |
pedidos.csv |
Estructurado | devuelto (caso 3, riesgo de devolución); unidades por producto y fecha son la serie temporal del caso 2 (previsión) |
Sí, mientras contenga id_cliente vinculable: seudonimizado; para previsión de demanda, agregar por producto/ciudad/día (anonimizado) |
productos.csv |
Estructurado (categoría, precio, peso) con una columna no estructurada (descripción en texto) | Ninguna; es información de contexto (características) para casos 1, 2 y 6 | No contiene datos personales |
resenas.csv |
Mixto: columnas estructuradas (id_producto, puntuacion, fecha) y texto libre no estructurado |
puntuacion (1-5) puede servir de etiqueta aproximada de sentimiento para el caso 4; mejor una etiqueta puesta a mano |
Sí: id_cliente y, potencialmente, el propio texto (la gente escribe su nombre o datos); seudonimizar y revisar el texto |
incidencias.csv |
Mixto: columnas estructuradas (id_pedido, fecha, tipo, causa) y descripción libre |
causa (caso 9, diagnóstico), con el problema de estar vacía en la mitad de las filas |
Sí, indirectamente vía id_pedido → cliente; seudonimizar |
Solución 2.
- (i) Devoluciones de la app ausentes: sesgo de muestreo (o de medición). El modelo subestimará las devoluciones de los clientes que compran por móvil; si el canal está correlacionado con la edad o el tipo de producto, el modelo se equivocará sistemáticamente en esos grupos.
- (ii) Anulaciones manuales de devoluciones dudosas de más de 300 €: sesgo histórico (los datos reflejan una política pasada). El histórico contiene menos devoluciones "consumadas" en pedidos altos de lo que ocurriría sin la intervención de Diego; el modelo puede aprender que los pedidos caros se devuelven poco, justo lo contrario de lo que motivó la regla, y además incorpora el criterio subjetivo de qué era "dudoso". Si el modelo se usa para decidir qué revisar, se crea un bucle de retroalimentación.
- (iii) Motivo escrito libremente por el cliente: sesgo de etiquetado (y problema de consistencia). "No me gusta", "no era lo que esperaba", "talla" y "calidad mala" pueden ser lo mismo o no; el modelo aprende las palabras que usa cada cliente, no la causa real. Habría que normalizar los motivos a una lista cerrada antes de usarlos como etiqueta.
Solución 3.
def problemas_devuelto(filas):
return [f["id_pedido"] for f in filas if f["devuelto"].strip() not in ("si", "no")]
PREFIJOS_CP = {"zaragoza": "50", "madrid": "28", "getafe": "28"}
def problemas_codigo_postal(filas):
malos = []
for f in filas:
cp = f["codigo_postal"].strip()
if cp == "":
continue # ya contado en completitud
ciudad = f["ciudad"].strip().lower()
if not re.fullmatch(r"\d{5}", cp):
malos.append((f["id_pedido"], cp, "formato"))
elif ciudad in PREFIJOS_CP and not cp.startswith(PREFIJOS_CP[ciudad]):
malos.append((f["id_pedido"], cp, "no coincide con " + f["ciudad"]))
return malos
print("devuelto no valido:", problemas_devuelto(pedidos)) # ['48209']
print("codigo postal:", problemas_codigo_postal(pedidos)) # [] con los datos de ejemploPara incorporarlo al informe basta añadir dos líneas dentro de informe_calidad con len(problemas_devuelto(filas)) y len(problemas_codigo_postal(filas)) e incluir esos identificadores en la condición de "fila con problema". Con los datos de ejemplo la comprobación de código postal no encuentra errores; añade una fila 48212,C1009,2026-03-06,20.00,Madrid,50003,no y comprueba que la detecta.
Conclusión
En esta lección hemos tratado los datos como lo que son en la IA moderna: la materia prima de la que el modelo hereda todo, tanto el conocimiento como los errores y los sesgos. Hemos clasificado los datos por estructura (estructurados, semiestructurados, no estructurados), por naturaleza (numéricos, categóricos, texto, imagen, series temporales) y por la presencia de etiquetas, anticipando la distinción entre aprendizaje supervisado y no supervisado. Hemos recorrido el ciclo de vida del dato (recogida, almacenamiento, calidad, uso, gobernanza) y hemos desglosado la calidad en cinco dimensiones medibles (completitud, exactitud, consistencia, actualidad, unicidad) ilustradas con los problemas reales de los CSV de NovaMarket: la mitad de la columna causa vacía, clientes duplicados, fechas en tres formatos y precios en céntimos. Hemos visto que el sesgo entra por los datos (muestreo, histórico, etiquetado) y se convierte en decisiones desviadas, hemos presentado los principios del RGPD que afectan al trabajo con datos (finalidad, minimización, conservación, derechos, seguridad) junto con la seudonimización y la anonimización, y hemos matizado el mito de "más datos siempre es mejor". Por último, hemos escrito un programa que lee un CSV con la biblioteca estándar y produce un informe de calidad: la primera herramienta que debería ejecutarse en cualquier proyecto de IA.
Con los datos ya sobre la mesa, la siguiente lección, Ética y Consideraciones en IA, aborda lo que ocurre cuando esos datos, con sus sesgos, alimentan decisiones que afectan a personas: qué principios éticos deben guiar a NovaMarket, qué problemas concretos (discriminación, privacidad, opacidad, responsabilidad, impacto laboral, desinformación, sostenibilidad) hay que prever, qué exige el marco regulatorio europeo y qué herramientas prácticas (checklist, evaluación de impacto, revisión humana, métricas de equidad) permiten pasar de las buenas intenciones a los hechos. Retomaremos allí el modelo de riesgo de devolución y el código postal para medir, con números, si un modelo trata igual a todos los grupos.
Fundamentos de Inteligencia Artificial (IA)
Módulo 1: Introducción a la Inteligencia Artificial
Módulo 2: Principios Básicos de la IA
- Conceptos Fundamentales: Agentes, Entornos y Racionalidad
- Tipos de Inteligencia Artificial
- Los Datos como Materia Prima de la IA
- Ética y Consideraciones en IA
Módulo 3: Algoritmos en IA
- Introducción a los Algoritmos
- Algoritmos de Búsqueda
- Búsqueda con Adversario: Juegos y Minimax
- Algoritmos de Optimización
Módulo 4: Aprendizaje Automático (Machine Learning)
- Conceptos Básicos de Machine Learning
- Tipos de Aprendizaje Automático
- Preparación de Datos y Características
- Algoritmos de Machine Learning
- Evaluación y Validación de Modelos
- Sobreajuste, Regularización y Ajuste de Hiperparámetros
Módulo 5: Redes Neuronales y Deep Learning
- Introducción a las Redes Neuronales
- Arquitectura de Redes Neuronales
- Cómo Aprende una Red: Descenso del Gradiente y Retropropagación
- Deep Learning y sus Aplicaciones
- Transformers, Grandes Modelos de Lenguaje e IA Generativa
Módulo 6: Lógica y Sistemas Expertos
- Lógica en IA
- Sistemas Expertos
- Razonamiento con Incertidumbre: Probabilidad y Redes Bayesianas
- Aplicaciones de Sistemas Expertos
Módulo 7: Herramientas y Lenguajes de Programación en IA
- Lenguajes de Programación para IA
- Python Científico: NumPy, pandas y Matplotlib
- Herramientas y Librerías Populares
- Entornos de Desarrollo
Módulo 8: Proyectos y Casos de Estudio
Módulo 9: Ejercicios y Prácticas
- Ejercicios de Algoritmos
- Prácticas de Machine Learning
- Proyectos de Redes Neuronales
- Proyecto Integrador: de la Idea al Prototipo
