Al cerrar el módulo 3 dejamos una promesa: en lugar de programar nosotros el algoritmo que resuelve el problema, íbamos a dar al sistema datos históricos para que aprendiera por sí mismo la regla. Esta lección cumple esa promesa y abre el módulo 4. Veremos qué significa exactamente "aprender de datos" (con la definición clásica de Tom Mitchell), fijaremos el vocabulario que usaremos en todo el módulo (dataset, característica, etiqueta, modelo, parámetros, pérdida, generalización...), dibujaremos el flujo de trabajo completo de un proyecto de machine learning como mapa de las lecciones que vienen y discutiremos cuándo merece la pena usar ML y cuándo es mejor una regla fija. Terminaremos entrenando el primer modelo "de verdad" del curso con scikit-learn: un predictor de devoluciones de NovaMarket que compararemos con la regla manual de Diego ("riesgo si el importe supera los 300 €") y con el umbral que aprendimos a mano en 01-02. Es importante porque todo lo que sigue (tipos de aprendizaje, preparación de datos, algoritmos, evaluación, redes neuronales) se apoya en las ideas y en el vocabulario de esta lección.

Contenido

  1. Qué es aprender de datos: la definición de Mitchell
  2. De aprender_umbral a machine learning: nada nuevo bajo el sol
  3. Vocabulario esencial
  4. El flujo de trabajo de un proyecto de ML: mapa del módulo
  5. Cuándo usar ML y cuándo no
  6. Ejemplo en Python: los datos de NovaMarket y el primer modelo con scikit-learn
  7. Errores Comunes y Consejos
  8. Ejercicios
  9. Conclusión

  1. Qué es aprender de datos: la definición de Mitchell

En 01-02 vimos que un programa tradicional recibe datos + reglas y produce resultados, mientras que el machine learning recibe datos + resultados y produce reglas (un modelo). Esa imagen es útil, pero necesitamos una definición operativa, que nos diga cuándo un programa "ha aprendido". La más citada es la de Tom Mitchell (1997):

Un programa aprende de la experiencia E respecto a una tarea T y una medida de rendimiento P si su rendimiento en T, medido por P, mejora con E.

Aplicada al caso 3 de NovaMarket (predecir si un pedido será devuelto):

Elemento Significado general En NovaMarket
Tarea T Lo que el sistema tiene que hacer Dado un pedido recién realizado, decir si se devolverá (sí/no)
Experiencia E Los datos de los que aprende El histórico de pedidos.csv: pedidos pasados con sus características y si finalmente se devolvieron
Rendimiento P Cómo medimos si lo hace bien Porcentaje de aciertos sobre pedidos que el sistema no ha visto (y, más adelante, medidas mejores que veremos en 04-05)

La definición tiene dos consecuencias prácticas que conviene interiorizar desde el primer día:

  • Sin medida de rendimiento no hay aprendizaje. "El modelo parece funcionar" no significa nada; hay que definir P antes de empezar. Es la misma exigencia de la medida de rendimiento del agente racional de 02-01.
  • La mejora debe medirse en datos nuevos. Un sistema que memoriza el histórico y acierta el 100 % de los pedidos que ya ha visto no ha aprendido nada útil: lo que importa es qué hace con el pedido de mañana. A esa capacidad la llamaremos generalización, y será el hilo de 04-05 y 04-06.

Fíjate en que Mitchell no dice nada de "inteligencia", ni de cómo se aprende. Es una definición funcional: si el rendimiento mejora con la experiencia, hay aprendizaje. Esto encaja con la visión de "actuar racionalmente" que adoptamos en 01-02.

  1. De aprender_umbral a machine learning: nada nuevo bajo el sol

Ya hiciste machine learning en 01-02 sin llamarlo así. Recuerda la función aprender_umbral(datos): recorría los 13 pedidos históricos, probaba cada importe como umbral candidato de la regla importe > umbral, contaba los aciertos de cada uno y se quedaba con el mejor (120 €, que acertaba 11 de 13, frente a los 7 de 13 de la regla de Diego). En términos de Mitchell:

  • T: decidir si un pedido tiene riesgo de devolución.
  • E: los 13 pedidos con su resultado real.
  • P: número de aciertos.

Y en términos del módulo 3, aprender_umbral era una búsqueda exhaustiva (03-01) en un espacio de 13 candidatos con una función objetivo (los aciertos) que había que maximizar (03-04). Eso es, exactamente, lo que hace cualquier algoritmo de machine learning, con tres diferencias de grado:

  1. La familia de reglas candidatas es mucho más rica que "un umbral sobre una columna": combinaciones de muchas columnas, árboles de preguntas, sumas ponderadas, redes de neuronas.
  2. El espacio de búsqueda es tan grande (a menudo infinito) que no se puede recorrer entero; se usan las estrategias de 03-04, como el ascenso siguiendo el gradiente, en vez de la fuerza bruta.
  3. La medida de rendimiento se calcula sobre datos apartados que el algoritmo no ha visto, para medir generalización y no memoria.

Por eso cerramos 03-04 con la frase "aprender es optimizar": entrenar un modelo es buscar, en un espacio enorme de modelos posibles, el que minimiza una función de error sobre los datos de entrenamiento, y confiar en que ese modelo también funcione con datos nuevos. Todo el módulo 4 es la versión adulta de aprender_umbral.

  1. Vocabulario esencial

Estos son los términos que aparecerán en cada lección del módulo. Los ejemplos están tomados del predictor de devoluciones que construiremos en la sección 6.

Término Qué es En el predictor de devoluciones
Dataset (conjunto de datos) Tabla con los ejemplos de los que se aprende Los 3.000 pedidos de un día de NovaMarket
Instancia / ejemplo / muestra Una fila del dataset Un pedido concreto
Característica (feature, atributo, variable de entrada) Una columna que describe la instancia y que el modelo puede usar importe, num_articulos, dias_entrega, cliente_nuevo, categoria
Etiqueta / objetivo (label, target, variable de salida) Lo que queremos predecir devuelto (1 = se devolvió, 0 = no)
Modelo La regla (función) que va de las características a la etiqueta "Si importe > 195 € y cliente nuevo → devuelto", o una suma ponderada de columnas
Parámetros Los números internos del modelo que el algoritmo ajusta a partir de los datos El umbral 195 €, los pesos de cada columna
Hiperparámetros Los ajustes del algoritmo que fija la persona antes de entrenar Profundidad máxima del árbol, número de vecinos, fuerza de la regularización
Entrenamiento (ajuste, fit) El proceso de buscar los parámetros que mejor explican los datos modelo.fit(X_train, y_train)
Inferencia / predicción Usar el modelo entrenado con instancias nuevas modelo.predict(pedido_de_manana)
Función de pérdida (coste, error) El número que el entrenamiento intenta minimizar: mide cuánto se equivoca el modelo en el entrenamiento Número de pedidos mal clasificados; en logística, la "pérdida logarítmica"
Generalización Que el modelo funcione bien con datos que no ha visto Acertar en los pedidos de mañana, no solo en los de ayer

Dos aclaraciones que evitan confusiones frecuentes:

  • Parámetros frente a hiperparámetros. En aprender_umbral, el umbral era el parámetro (lo elegían los datos); si hubiéramos decidido "solo probaremos umbrales múltiplos de 10", eso habría sido un hiperparámetro (lo elegimos nosotros). Los parámetros se aprenden; los hiperparámetros se ajustan probando y validando (04-06).
  • Pérdida frente a medida de rendimiento. La pérdida es lo que el algoritmo minimiza por dentro durante el entrenamiento; la medida de rendimiento (P) es lo que a nosotros nos importa al final (aciertos, euros ahorrados). A veces coinciden y a veces no: se minimiza una pérdida matemáticamente cómoda y se evalúa con la métrica de negocio (04-05).

Un último convenio de notación que verás en toda la literatura y en scikit-learn: la tabla de características se llama X (mayúscula, porque es una matriz de filas × columnas) y el vector de etiquetas se llama y (minúscula, porque es una sola columna).

  1. El flujo de trabajo de un proyecto de ML: mapa del módulo

Entrenar el modelo es solo un paso, y ni siquiera el más largo, de un proyecto de machine learning. El flujo completo se parece mucho al ciclo del agente de 02-01, pero aplicado a construir el modelo:

flowchart LR
    A[1. Definir el problema<br/>T, E, P] --> B[2. Obtener los datos]
    B --> C[3. Preparar datos y<br/>características]
    C --> D[4. Entrenar el modelo]
    D --> E[5. Evaluar y validar]
    E -->|no basta| C
    E -->|no basta| D
    E -->|es suficiente| F[6. Desplegar]
    F --> G[7. Monitorizar]
    G -->|los datos cambian| B

Cada paso tiene su lección en este módulo o en otro del curso:

Paso Qué se hace Dónde se profundiza
1. Definir el problema Traducir la necesidad de negocio a T, E, P; decidir si es clasificación, regresión, agrupamiento... Esta lección y 04-02 (tipos de aprendizaje)
2. Obtener los datos Localizar las fuentes, unirlas, comprobar volumen, calidad, sesgo y aspectos legales 02-03 (ya visto)
3. Preparar datos y características Limpiar, codificar, escalar, crear variables nuevas, evitar fugas de información 04-03
4. Entrenar el modelo Elegir un algoritmo y ajustarlo a los datos 04-04 (algoritmos clásicos), módulo 5 (redes neuronales)
5. Evaluar y validar Medir el rendimiento en datos no vistos con las métricas adecuadas; comparar con una línea base 04-05
5 bis. Ajustar Detectar sobreajuste, regularizar, ajustar hiperparámetros, volver a entrenar 04-06
6. Desplegar Integrar el modelo en el sistema (la web, el gestor de pedidos), con revisión humana donde toque 08-01 y 09-04
7. Monitorizar Vigilar que el rendimiento no se degrade cuando cambian los datos (nuevos productos, nueva temporada) 08-01

Dos observaciones sobre el diagrama:

  • Es un ciclo, no una línea. Casi nunca se acierta a la primera: la evaluación revela que faltan características, que hay una fuga de información o que el modelo se sobreajusta, y se vuelve atrás. Marta debe planificar iteraciones.
  • El entrenamiento es la parte pequeña. En un proyecto real, el paso 3 se lleva la mayor parte del tiempo, y el 7 es el que se olvida con más frecuencia y más caro sale. La lección 08-01 recorre este mismo flujo como un proyecto completo, con roles, entregables y decisiones.

  1. Cuándo usar ML y cuándo no

Diego, con razón, pregunta por qué NovaMarket necesita un modelo cuando ya tiene una regla que "funciona". El machine learning no es siempre la respuesta; a veces una regla fija (o una consulta SQL) es mejor. Estas son las señales:

Situación Reglas fijas (programación tradicional) Machine learning
La regla es conocida, simple y estable Sí. "Si el pedido pesa más de 30 kg, va por transportista" no necesita aprender nada No aporta y añade incertidumbre
La regla es difícil de escribir pero hay ejemplos abundantes Cientos de if frágiles Sí: reconocer un fraude, clasificar una reseña, prever la demanda
Los patrones cambian con el tiempo Hay que reescribir la regla cada vez Sí: se reentrena con datos nuevos
Hay muchas variables que interactúan Inmanejable a mano Sí: el modelo combina decenas de columnas
Hay pocos datos o de mala calidad Sí, apoyada en conocimiento experto (módulo 6) Riesgo alto: aprenderá ruido
Se exige explicación exacta de cada decisión (legal, contractual) Sí, o ML con modelos interpretables y revisión humana (02-04) Depende del modelo: un árbol se explica; una red profunda, mucho menos
El coste de un error es catastrófico Reglas verificables, o ML solo como apoyo Solo con validación muy rigurosa y humano en el bucle

Aplicado a los nueve casos de uso de NovaMarket que catalogamos en 01-03: la predicción de devoluciones (3), la previsión de demanda (2), la recomendación (1) y la clasificación de reseñas (4) son candidatos claros a ML (muchos ejemplos, patrones difíciles de escribir, cambian con el tiempo). Las rutas (5) y la asignación (6) las resolvimos en el módulo 3 con optimización, sin aprender nada. Las reglas de devoluciones y garantías (8) son, precisamente, reglas fijas: se resuelven con lógica y sistemas expertos (módulo 6). Elegir bien la herramienta es la primera decisión del paso 1 del flujo.

Una regla de oro práctica: empieza siempre por la regla más simple posible como línea base (la de Diego, por ejemplo) y exige al modelo que la supere de forma medible. Lo haremos ahora mismo.

  1. Ejemplo en Python: los datos de NovaMarket y el primer modelo con scikit-learn

Como en el resto del curso, no disponemos del pedidos.csv real, así que generaremos pedidos ficticios con código. Lo importante es que la función generadora sea reproducible (misma semilla, mismos datos) y que codifique una relación realista pero con ruido, como ocurre en la realidad: los pedidos caros, de clientes nuevos, con entregas lentas y de electrónica se devuelven más, pero ninguna regla acierta siempre. Reutilizaremos esta función en todas las lecciones del módulo, así que guárdala en un fichero novamarket_ml.py.

6.1 La función generadora generar_pedidos_ml

import numpy as np
import pandas as pd

def generar_pedidos_ml(n=3000, semilla=42):
    """Genera n pedidos ficticios de NovaMarket con la etiqueta 'devuelto' (1 = devuelto)."""
    rng = np.random.default_rng(semilla)          # generador reproducible
    importe = np.round(rng.gamma(shape=2.0, scale=60.0, size=n) + 5, 2)   # euros, cola larga
    num_articulos = rng.integers(1, 6, size=n)    # de 1 a 5 artículos
    dias_entrega = rng.integers(1, 8, size=n)     # de 1 a 7 días
    cliente_nuevo = rng.random(n) < 0.30          # el 30 % son clientes nuevos
    categoria = rng.choice(["electronica", "hogar", "informatica", "accesorios"],
                           size=n, p=[0.35, 0.30, 0.20, 0.15])
    zona = rng.choice(["A", "B", "C"], size=n, p=[0.40, 0.35, 0.25])
    # "Verdad oculta": probabilidad de devolución que el modelo tendrá que descubrir
    z = (-3.4
         + 0.010 * (importe - 100)                # más importe, más riesgo
         + 1.6 * cliente_nuevo                    # los clientes nuevos devuelven más
         + 0.35 * (dias_entrega - 4)              # las entregas lentas se devuelven más
         + 1.0 * (categoria == "electronica")
         + 0.5 * (categoria == "informatica")
         - 0.2 * (num_articulos - 2)              # pedidos grandes, algo menos
         + 1.2 * cliente_nuevo * (importe - 100) / 100)   # nuevo + caro: riesgo extra
    prob = 1 / (1 + np.exp(-z))                   # sigmoide: de z a probabilidad
    devuelto = (rng.random(n) < prob).astype(int) # sorteo con esa probabilidad (ruido)
    return pd.DataFrame({
        "importe": importe,
        "num_articulos": num_articulos,
        "dias_entrega": dias_entrega,
        "cliente_nuevo": cliente_nuevo.astype(int),
        "categoria": categoria,
        "codigo_postal_zona": zona,               # NO influye en la devolución
        "devuelto": devuelto,
    })

pedidos = generar_pedidos_ml(3000, 42)
print(pedidos.head())
print(pedidos["devuelto"].value_counts(normalize=True).round(3))

Salida:

   importe  num_articulos  dias_entrega  cliente_nuevo    categoria codigo_postal_zona  devuelto
0   130.51              4             4              1        hogar                  B         0
1   175.12              5             7              0  informatica                  B         0
2   115.23              2             2              1  electronica                  A         0
3   103.70              3             2              1        hogar                  C         0
4   189.76              3             6              0   accesorios                  A         0
devuelto
0    0.836
1    0.164

Explicación línea a línea:

  • np.random.default_rng(semilla) crea un generador de números aleatorios con semilla fija: cada vez que llames a la función con la misma semilla obtendrás exactamente los mismos pedidos. Es imprescindible para que tus resultados y los de esta lección coincidan (salvo pequeñas diferencias entre versiones de NumPy).
  • Cada columna se genera con una distribución razonable: los importes siguen una distribución gamma (muchos pedidos pequeños y una cola de pedidos caros, media en torno a 125 €), los artículos y los días de entrega son enteros uniformes, el 30 % de clientes son nuevos, y la categoría y la zona se sortean con probabilidades fijas.
  • La variable z es la verdad oculta: una puntuación de riesgo que combina las columnas con pesos que nosotros hemos elegido. En el mundo real esa fórmula no existe o nadie la conoce; aquí la escribimos para poder comprobar después si el modelo la descubre. Fíjate en que codigo_postal_zona no aparece en z: la zona no influye en la devolución. Lo hacemos a propósito, recordando el sesgo por código postal de 02-04; en 04-03 comprobaremos que un buen modelo le da una importancia prácticamente nula.
  • prob = 1 / (1 + np.exp(-z)) convierte la puntuación en una probabilidad entre 0 y 1 (esta función, la sigmoide, reaparece en 04-04 con la regresión logística y en el módulo 5).
  • devuelto se decide con un sorteo según esa probabilidad. Esto introduce ruido: dos pedidos idénticos pueden acabar uno devuelto y otro no. Ningún modelo, por bueno que sea, acertará el 100 %; conviene saberlo antes de perseguir imposibles.
  • El resultado es un DataFrame de pandas (una tabla), con un 16,4 % de pedidos devueltos. En 04-05 veremos que este desequilibrio (muchos más "no" que "sí") condiciona cómo hay que evaluar.

6.2 El primer modelo: fit, predict, score

Vamos a entrenar un árbol de decisión con scikit-learn. No entraremos en cómo funciona por dentro (eso es 04-04); ahora nos interesa el patrón de uso, que es idéntico para todos los modelos de la librería. Usaremos solo las columnas numéricas; las de texto (categoria, codigo_postal_zona) necesitan una transformación previa que veremos en 04-03.

from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

columnas = ["importe", "num_articulos", "dias_entrega", "cliente_nuevo"]
X = pedidos[columnas]          # características (matriz de 3000 filas x 4 columnas)
y = pedidos["devuelto"]        # etiqueta (vector de 3000 valores 0/1)

# 1) Apartamos el 25 % de los pedidos: el modelo NO los verá durante el entrenamiento
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y)

# 2) Elegimos el algoritmo y sus hiperparámetros
modelo = DecisionTreeClassifier(max_depth=3, random_state=42)

# 3) Entrenamos: el algoritmo busca los parámetros (las preguntas del árbol)
modelo.fit(X_train, y_train)

# 4) Medimos el rendimiento P: proporción de aciertos
print(f"Acierto en entrenamiento: {modelo.score(X_train, y_train):.3f}")
print(f"Acierto en test:          {modelo.score(X_test, y_test):.3f}")

# 5) Inferencia con pedidos nuevos
nuevos = pd.DataFrame({"importe": [45.0, 350.0, 180.0],
                       "num_articulos": [2, 1, 3],
                       "dias_entrega": [2, 6, 5],
                       "cliente_nuevo": [0, 1, 1]})
print(modelo.predict(nuevos))                 # 0 = no se devolverá, 1 = sí
print(modelo.predict_proba(nuevos).round(2))  # probabilidad de cada clase

Salida:

Acierto en entrenamiento: 0.873
Acierto en test:          0.868
[0 1 0]
[[0.95 0.05]
 [0.05 0.95]
 [0.52 0.48]]

Paso a paso:

  1. train_test_split baraja los pedidos y los reparte en entrenamiento (2.250) y test (750). random_state=42 fija el barajado para que sea reproducible; stratify=y garantiza que ambos trozos tengan la misma proporción de devoluciones (16,4 %). El conjunto de test es la "experiencia futura" con la que mediremos la generalización; no se toca hasta el final. La razón de fondo se desarrolla en 04-05.
  2. DecisionTreeClassifier(max_depth=3) crea el modelo aún vacío. max_depth=3 es un hiperparámetro: como máximo tres preguntas encadenadas. Lo elegimos nosotros; en 04-06 aprenderemos a elegirlo con datos.
  3. modelo.fit(X_train, y_train) es el entrenamiento: la búsqueda de los parámetros (qué columna preguntar en cada nodo y con qué umbral) que mejor separan los pedidos devueltos de los no devueltos. Es la versión sofisticada de aprender_umbral, y en 04-04 veremos exactamente qué optimiza.
  4. modelo.score(X, y) calcula la proporción de aciertos (accuracy). En entrenamiento acierta el 87,3 % y en test el 86,8 %: cifras parecidas, señal de que el modelo generaliza y no memoriza (en 04-06 veremos qué pasa cuando no es así).
  5. predict devuelve la clase (0 o 1) de cada pedido nuevo, y predict_proba la probabilidad estimada de cada clase. El pedido de 350 € de un cliente nuevo tiene un 95 % de probabilidad de devolución; el de 180 € está casi al 50 %, un caso claro para la banda de revisión humana de 02-04.

Este patrón (fit → predict/predict_proba → score) es el mismo para una regresión logística, un bosque aleatorio o una máquina de vectores de soporte: cambia el algoritmo, no la interfaz. Es una de las razones del éxito de scikit-learn, que se presenta como herramienta en 07-03.

6.3 Comparación con la regla de Diego y con la regla de 01-02

Evaluamos las reglas anteriores sobre el mismo conjunto de test, para comparar en igualdad de condiciones:

def acierto_regla(umbral):
    prediccion = (X_test["importe"] > umbral).astype(int)   # 1 si supera el umbral
    return (prediccion == y_test).mean()                    # proporción de aciertos

print(f"Regla de Diego (> 300 €):           {acierto_regla(300):.3f}")
print(f"Regla aprendida en 01-02 (> 120 €): {acierto_regla(120):.3f}")
print(f"'Nunca se devuelve':                {(y_test == 0).mean():.3f}")
print(f"Árbol de decisión:                  {modelo.score(X_test, y_test):.3f}")

pred_arbol = modelo.predict(X_test)
pred_diego = (X_test["importe"] > 300).astype(int)
for nombre, pred in [("árbol", pred_arbol), ("Diego", pred_diego)]:
    detectadas = ((pred == 1) & (y_test == 1)).sum()
    print(f"{nombre}: marca {pred.sum()} pedidos, {detectadas} de ellos devueltos de verdad "
          f"(hay {y_test.sum()} devoluciones en test)")

Salida:

Regla de Diego (> 300 €):           0.843
Regla aprendida en 01-02 (> 120 €): 0.627
'Nunca se devuelve':                0.836
Árbol de decisión:                  0.868
árbol: marca 52 pedidos, 38 de ellos devueltos de verdad (hay 123 devoluciones en test)
Diego: marca 37 pedidos, 21 de ellos devueltos de verdad (hay 123 devoluciones en test)

Lectura de los resultados:

  • La regla de Diego acierta el 84,3 %... pero la regla "ningún pedido se devuelve" acierta el 83,6 %. Como solo el 16 % de los pedidos se devuelve, acertar mucho es fácil: basta con decir siempre que no. Diego apenas mejora esa trivialidad. Esta trampa de la exactitud con clases desequilibradas es el punto de partida de 04-05; de momento, quédate con la idea de que la cifra de aciertos, sola, engaña.
  • La regla de 01-02 (umbral 120 €) sale mucho peor aquí (62,7 %). No es que aquel aprendizaje estuviera mal: es que se aprendió con 13 ejemplos cuidadosamente elegidos y no generaliza a un histórico realista de 3.000 pedidos, en el que la mayoría de los pedidos de más de 120 € no se devuelve. Es la lección de la sección 1: pocos datos, modelo poco fiable.
  • El árbol acierta el 86,8 %, la mejor cifra, y sobre todo hace algo cualitativamente distinto: combina el importe con si el cliente es nuevo y con los días de entrega. Marca 52 pedidos y acierta en 38 (73 %), mientras que Diego marca 37 y acierta en 21 (57 %). Detecta casi el doble de devoluciones con menos falsas alarmas. Aun así, se le escapan 85 de las 123 devoluciones: la mejora es real, pero queda mucho trabajo, y ese trabajo es el resto del módulo (más características en 04-03, mejores algoritmos en 04-04, un umbral ajustado al coste en 04-05, hiperparámetros en 04-06).

Diego, escéptico, hará la pregunta correcta: "¿y qué ha aprendido exactamente el árbol?". Puedes verlo con from sklearn.tree import export_text; print(export_text(modelo, feature_names=columnas)). Verás reglas del tipo "si importe > 195 € y cliente nuevo → devuelto; si importe > 358 € → devuelto". Es decir, el árbol ha descubierto que Diego no iba desencaminado (los pedidos muy caros sí se devuelven), pero que para clientes nuevos el umbral de riesgo baja a unos 195 €. En 04-04 leeremos árboles con detalle.

Errores Comunes y Consejos

  • Evaluar con los mismos datos con los que se entrena. Es el error número uno de quien empieza. Un modelo que memoriza acierta el 100 % de lo que ya ha visto y falla estrepitosamente con lo nuevo. Aparta siempre un conjunto de test antes de entrenar y no lo mires hasta el final.
  • Confundir parámetros con hiperparámetros. Los parámetros los ajusta fit; los hiperparámetros los fijas tú al crear el modelo (max_depth=3). Si te encuentras "probando valores a mano" de algo, es un hiperparámetro, y 04-06 te dará el método para hacerlo bien.
  • Olvidar la línea base. Compara siempre con la regla más tonta razonable ("nunca se devuelve", "la media de la semana pasada") y con la regla manual vigente. Un modelo que no las supera de forma clara no merece desplegarse.
  • Fiarse de la cifra de aciertos. Con clases desequilibradas, el 84 % de la regla de Diego y el 83,6 % de "nunca" son casi lo mismo. Espera a 04-05 antes de sacar conclusiones fuertes de una sola cifra.
  • Saltar directamente al algoritmo. El flujo de la sección 4 empieza por definir T, E y P y por conocer los datos. Marta dedicará mucho más tiempo a preparar los datos (04-03) que a llamar a fit.
  • Fijar la semilla y olvidarlo. random_state=42 hace tus experimentos reproducibles, pero no significa que el resultado sea "el bueno": prueba varias semillas antes de afirmar que un modelo es mejor que otro. Las salidas de esta lección pueden variar ligeramente según la versión de NumPy o scikit-learn.

Ejercicios

Ejercicio 1. Formula con la definición de Mitchell (T, E, P) dos de los casos de uso de NovaMarket distintos del de devoluciones: la previsión de demanda (caso 2) y la clasificación de reseñas (caso 4). Indica en cada uno qué serían las características, la etiqueta y una instancia.

Ejercicio 2. Cambia el hiperparámetro max_depth del árbol a 1 y vuelve a entrenar. Muestra las reglas con export_text y compara el acierto en test con la regla "nunca se devuelve". ¿Qué umbral ha elegido el árbol de una sola pregunta? ¿Por qué un solo umbral sobre importe no logra superar a "nunca" en este dataset, cuando en 01-02 sí superaba a Diego?

Ejercicio 3. Genera un segundo dataset con otra semilla (generar_pedidos_ml(3000, 7)) y evalúa sobre él el árbol ya entrenado (sin volver a llamar a fit), como si fueran los pedidos de la semana siguiente. ¿Se mantiene el acierto? ¿Qué te dice eso sobre la generalización? Repite después evaluando la regla de Diego sobre esos mismos datos.

Soluciones

Solución 1.

  • Previsión de demanda. T: predecir cuántas unidades de un producto se venderán la semana que viene. E: el histórico semanal de ventas (pedidos.csv agregado por producto y semana), con calendario y promociones. P: error medio en unidades entre lo previsto y lo vendido (en 04-05 lo llamaremos MAE). Una instancia es "producto X, semana Y"; las características, la semana del año, las ventas de las semanas anteriores, si hay promoción; la etiqueta, las unidades vendidas esa semana (un número, no una categoría: es un problema de regresión, 04-02).
  • Clasificación de reseñas. T: decidir si una reseña de resenas.csv es positiva, neutra o negativa (o si menciona un problema de envío). E: reseñas pasadas etiquetadas a mano. P: porcentaje de reseñas bien clasificadas, o mejor, medidas por clase (04-05). Una instancia es una reseña; las características, el texto (transformado en números, 04-03) y la puntuación en estrellas; la etiqueta, la clase asignada.

Solución 2. Con max_depth=1 el árbol elige la pregunta importe <= 195.65 y en ambas ramas predice la clase 0, así que su acierto en test es 0,836, idéntico al de "nunca se devuelve". Incluso por encima de 195 € la mayoría de los pedidos no se devuelve (la tasa allí ronda el 40 %), de modo que, si solo se puede hacer una pregunta y se busca maximizar aciertos, lo mejor es decir "no" siempre. En 01-02 el histórico de 13 pedidos estaba equilibrado (casi la mitad devueltos), y por eso un umbral sí ganaba. Moraleja: la misma familia de modelos se comporta de forma distinta según la proporción de clases; y para detectar devoluciones hace falta combinar variables (profundidad 3 ya lo consigue) y usar medidas mejores que la exactitud (04-05).

Solución 3. Con nuevos = generar_pedidos_ml(3000, 7) y modelo.score(nuevos[columnas], nuevos["devuelto"]) obtendrás en torno a 0,88, incluso algo por encima del 0,868 del test: el modelo generaliza a pedidos que nunca ha visto porque los nuevos datos siguen la misma "verdad oculta". La regla de Diego se queda de nuevo cerca del 0,85 (y la de "nunca" en torno a 0,84). Si en la realidad cambiaran las condiciones (una campaña con muchos clientes nuevos, un nuevo proveedor con más defectos), la generalización dejaría de estar garantizada: por eso el paso 7 del flujo, la monitorización, existe.

Conclusión

En esta lección hemos definido el machine learning con la fórmula de Mitchell (tarea, experiencia, rendimiento), hemos comprobado que aprender_umbral de 01-02 ya cumplía esa definición y que "aprender es optimizar" (03-04) es literalmente lo que hace fit, hemos fijado el vocabulario del módulo (dataset, instancia, característica, etiqueta, modelo, parámetros frente a hiperparámetros, entrenamiento, inferencia, función de pérdida, generalización), hemos dibujado el flujo de trabajo completo como mapa de las lecciones que vienen y hemos discutido cuándo el ML compensa frente a una regla fija. En el código hemos creado la función generar_pedidos_ml, que nos acompañará todo el módulo, y hemos entrenado el primer modelo de scikit-learn con el patrón fit/predict/score, que supera a la regla de Diego combinando varias columnas, aunque todavía deja escapar muchas devoluciones y nos ha enseñado que la cifra de aciertos, sola, engaña.

En la siguiente lección, Tipos de Aprendizaje Automático, clasificaremos los problemas que puede resolver el ML: el predictor de devoluciones es un ejemplo de aprendizaje supervisado de clasificación; la previsión de demanda será supervisado de regresión; la segmentación de clientes para el recomendador será no supervisado; y veremos también el aprendizaje por refuerzo, que conecta con los agentes de 02-01 y con AlphaGo. Marta y Diego tendrán así un mapa para decidir, ante cada uno de los nueve casos de uso, qué tipo de aprendizaje necesitan.

Fundamentos de Inteligencia Artificial (IA)

Módulo 1: Introducción a la Inteligencia Artificial

Módulo 2: Principios Básicos de la IA

Módulo 3: Algoritmos en IA

Módulo 4: Aprendizaje Automático (Machine Learning)

Módulo 5: Redes Neuronales y Deep Learning

Módulo 6: Lógica y Sistemas Expertos

Módulo 7: Herramientas y Lenguajes de Programación en IA

Módulo 8: Proyectos y Casos de Estudio

Módulo 9: Ejercicios y Prácticas

Módulo 10: Recursos Adicionales

© Copyright 2026. Todos los derechos reservados