En la lección anterior entrenamos el primer modelo del curso: un árbol que aprendía, a partir de pedidos etiquetados como devueltos o no, a predecir la etiqueta de pedidos nuevos. Ese es solo uno de los tipos de problema que el machine learning sabe resolver. Cuando Marta revisa la lista de los nueve casos de uso de NovaMarket descubre que no todos tienen la misma forma: en unos hay una respuesta correcta conocida para cada ejemplo histórico (¿se devolvió?, ¿cuántas unidades se vendieron?), en otros no hay ninguna etiqueta y lo que se busca es estructura (¿qué tipos de clientes tenemos?), y en otros ni siquiera hay un dataset fijo, sino un sistema que actúa y recibe premios o castigos (¿qué cupón conviene ofrecer?). Esta lección presenta los cuatro grandes paradigmas del aprendizaje automático (supervisado, no supervisado, semi y auto-supervisado, y por refuerzo), los compara en una tabla y los ilustra con código sobre los datos de NovaMarket. Es importante porque la primera decisión de cualquier proyecto es identificar qué tipo de problema tenemos: de ella dependen los datos que hay que reunir, los algoritmos aplicables y la forma de medir el éxito.

Contenido

  1. Los cuatro paradigmas de un vistazo
  2. Aprendizaje supervisado: clasificación y regresión
  3. Aprendizaje no supervisado: clustering, reducción de dimensionalidad y anomalías
  4. Semi-supervisado y auto-supervisado
  5. Aprendizaje por refuerzo
  6. Tabla comparativa de paradigmas
  7. Ejemplos en Python: clasificación, regresión, clustering y un bandido multibrazo
  8. Errores Comunes y Consejos
  9. Ejercicios
  10. Conclusión

  1. Los cuatro paradigmas de un vistazo

La forma más útil de clasificar los problemas de ML es preguntarse qué información de "respuesta correcta" tenemos en los datos:

flowchart TD
    Q{¿Qué sabemos de cada ejemplo?}
    Q -->|Características + respuesta correcta| S[Supervisado]
    Q -->|Solo características, sin respuesta| U[No supervisado]
    Q -->|Respuesta solo en una parte de los ejemplos| SS[Semi-supervisado /<br/>auto-supervisado]
    Q -->|No hay dataset fijo: el sistema actúa<br/>y recibe recompensas| R[Refuerzo]
    S --> S1[Clasificación: la respuesta es una categoría]
    S --> S2[Regresión: la respuesta es un número]
    U --> U1[Clustering: agrupar]
    U --> U2[Reducción de dimensionalidad: comprimir]
    U --> U3[Detección de anomalías: lo raro]

En el vocabulario de 04-01: el paradigma depende de si tenemos la etiqueta (y), de si la tenemos para todas las instancias o solo para algunas, o de si la "etiqueta" es una recompensa que llega después de actuar.

  1. Aprendizaje supervisado: clasificación y regresión

Es el paradigma más usado en la empresa y el que ocupará la mayor parte del módulo. Supervisado significa que cada ejemplo de entrenamiento lleva su respuesta correcta, como si un supervisor hubiera corregido el ejercicio: el modelo aprende la función que va de las características a la etiqueta y luego la aplica a ejemplos nuevos.

Se divide en dos según el tipo de etiqueta:

Clasificación Regresión
La etiqueta es... Una categoría de un conjunto finito Un número continuo
Pregunta típica ¿De qué tipo es? ¿Sí o no? ¿Cuánto? ¿Cuándo?
Salida del modelo Clase (y normalmente una probabilidad por clase) Un valor numérico
Ejemplos NovaMarket ¿Se devolverá el pedido? (caso 3) · ¿La reseña es positiva/neutra/negativa? (caso 4) · ¿A qué categoría de incidencia pertenece este ticket? (caso 9) ¿Cuántas unidades venderemos la semana que viene? (caso 2) · ¿Cuál será el importe de la próxima compra de este cliente? · ¿Cuántos días tardará la entrega?
Cómo se mide (04-05) Aciertos, precisión, sensibilidad, AUC Error medio (MAE), error cuadrático (RMSE), R²

Matices que conviene tener claros:

  • Binaria vs multiclase. "Devuelto sí/no" es clasificación binaria; "reseña positiva/neutra/negativa" es multiclase (tres clases excluyentes). Existe además la clasificación multietiqueta, en la que un ejemplo puede tener varias etiquetas a la vez (una incidencia puede ser "retraso" y "producto dañado").
  • La frontera es la pregunta, no el dato. El importe de un pedido es un número; predecirlo es regresión. Pero "¿el pedido superará los 100 €?" es clasificación. Un mismo dato admite las dos formulaciones, y elegir bien depende de la decisión de negocio que se va a tomar.
  • La previsión de demanda es regresión sobre series temporales. Tiene una peculiaridad, el orden en el tiempo, que obliga a validar de forma especial (04-05) y que ofrece características propias (semana del año, ventas de la semana anterior: 04-03).

  1. Aprendizaje no supervisado: clustering, reducción de dimensionalidad y anomalías

Aquí no hay etiqueta. Solo tenemos las características de cada ejemplo, y lo que pedimos al algoritmo es que descubra estructura: grupos, direcciones principales, casos raros. Es la situación más frecuente en la práctica (etiquetar cuesta dinero: alguien tiene que leer y clasificar cada reseña) y la que más cuidado exige al interpretar, porque no hay respuesta correcta contra la que comprobar.

Tres tareas principales:

Tarea Qué hace Ejemplo NovaMarket Algoritmos típicos
Clustering (agrupamiento) Reparte los ejemplos en grupos de forma que los de un mismo grupo se parezcan entre sí más que a los de otros Segmentar los clientes de clientes.csv en "ocasionales", "habituales" y "grandes compradores" para adaptar el recomendador (caso 1) y las campañas k-means, clustering jerárquico, DBSCAN
Reducción de dimensionalidad Comprime muchas columnas en pocas conservando lo esencial, para visualizar o para simplificar un modelo posterior Resumir 50 variables de comportamiento de compra en 2 ejes para dibujar el mapa de clientes PCA, t-SNE, UMAP
Detección de anomalías Encuentra ejemplos que se apartan del patrón general Pedidos con una combinación de importe, hora y dirección nunca vista (posible fraude, caso 3, cuando no hay etiquetas de fraude confirmado) Isolation Forest, One-Class SVM, distancia a los vecinos

Un aviso que Marta repetirá a Diego: un algoritmo de clustering siempre devuelve grupos, aunque los datos no tengan estructura. Que k-means diga que hay tres segmentos no demuestra que existan; hay que mirarlos, ponerles nombre de negocio y comprobar que se comportan de forma distinta (en la sección 7 lo haremos). En 04-04 veremos cómo funciona k-means por dentro y cómo elegir el número de grupos.

  1. Semi-supervisado y auto-supervisado

Entre los dos extremos hay situaciones intermedias muy comunes:

  • Semi-supervisado. Tenemos etiquetas para una parte pequeña de los datos y muchos ejemplos sin etiquetar. Es la situación de incidencias.csv en NovaMarket: el equipo de soporte ha clasificado a mano la mitad de los tickets del último trimestre (retraso, producto dañado, error de pedido, garantía...) y la otra mitad está sin categoría. En lugar de tirar la mitad sin etiqueta, los métodos semi-supervisados la usan para aprender mejor la estructura del texto y propagar las etiquetas a los ejemplos parecidos (por ejemplo, entrenar con los etiquetados, predecir los demás, quedarse con las predicciones más seguras como "pseudoetiquetas" y reentrenar).
  • Auto-supervisado. No hay etiquetas humanas, pero el propio dato proporciona la señal de supervisión: se oculta una parte del ejemplo y se pide al modelo que la reconstruya. Es como los grandes modelos de lenguaje aprenden a partir de texto sin etiquetar (predecir la siguiente palabra o la palabra tapada), y como se preentrenan muchos modelos de imagen. Es la razón de que la IA generativa haya despegado: convierte océanos de datos sin etiquetar en experiencia útil. Se desarrolla en 05-05.

Ambos aparecen aquí solo para que reconozcas la situación cuando la encuentres; en este curso trabajaremos sobre todo con supervisado y no supervisado.

  1. Aprendizaje por refuerzo

El cuarto paradigma es distinto de los anteriores: no hay un dataset fijo. Hay un agente (02-01) que actúa en un entorno, observa el estado, elige una acción y recibe una recompensa (positiva o negativa), y su objetivo es aprender una política (qué acción tomar en cada estado) que maximice la recompensa acumulada a largo plazo.

Los elementos, con el ejemplo conceptual de un agente que decide qué cupón ofrecer a cada cliente en el momento del pago:

Elemento Definición Ejemplo del cupón
Agente Quien decide El sistema de cupones de la web
Entorno Todo lo que el agente no controla pero le afecta Los clientes y su comportamiento
Estado La información que ve el agente al decidir Importe del carrito, si el cliente es nuevo, hora, categoría
Acción Lo que puede hacer No ofrecer cupón / 5 % / envío gratis / 10 %
Recompensa La señal que indica lo bien que fue la acción Margen de la compra (más venta, menos coste del cupón); 0 si abandona
Política La regla aprendida estado → acción "A carritos grandes de clientes nuevos, envío gratis; a habituales, nada"

Dos ideas propias del refuerzo:

  • Exploración frente a explotación. El agente solo aprende de las acciones que prueba. Si desde el principio se queda con el cupón que parece mejor (explotar), nunca sabrá si otro habría funcionado más; si prueba al azar todo el tiempo (explorar), desperdicia recompensa. Hay que equilibrar: la estrategia más simple, epsilon-greedy, explora una fracción ε de las veces y explota el resto. La veremos en código.
  • Recompensa retardada. A menudo el premio llega mucho después de la acción que lo causó (en el ajedrez, la victoria llega tras cuarenta jugadas). Asignar el mérito a las acciones correctas (el credit assignment) es la parte difícil, y la resuelven algoritmos como Q-learning o los métodos de gradiente de política, fuera del alcance de este curso.

Conexiones con lo ya visto: el marco agente-entorno-recompensa es el PEAS de 02-01 con la medida de rendimiento convertida en señal de aprendizaje; y AlphaGo (01-01, 03-03) combinó la búsqueda con adversario que estudiamos con minimax con redes neuronales entrenadas por refuerzo jugando millones de partidas contra sí mismo. También se aplica en robótica, control de sistemas (refrigeración de centros de datos, tráfico) y, más recientemente, en el ajuste fino de los grandes modelos de lenguaje a partir de preferencias humanas (05-05).

  1. Tabla comparativa de paradigmas

Paradigma Tipo de datos Objetivo Ejemplos NovaMarket Algoritmos típicos Cómo se evalúa
Supervisado: clasificación Características + etiqueta categórica Predecir la clase Devolución sí/no; sentimiento de reseñas; tipo de incidencia Regresión logística, árboles, bosques, SVM, k-NN, redes Aciertos, precisión/sensibilidad, AUC (04-05)
Supervisado: regresión Características + etiqueta numérica Predecir un valor Demanda semanal; importe de la próxima compra; días de entrega Regresión lineal, árboles/bosques de regresión, gradient boosting, redes MAE, RMSE, R² (04-05)
No supervisado Solo características Encontrar estructura Segmentos de clientes; anomalías en pedidos; compresión de variables k-means, jerárquico, DBSCAN, PCA, Isolation Forest Cohesión de los grupos, interpretación de negocio; no hay "acierto"
Semi / auto-supervisado Pocas etiquetas + muchos sin etiquetar; o el dato como su propia etiqueta Aprovechar los datos sin etiquetar Incidencias a medio etiquetar; preentrenar sobre todo el texto de reseñas Autoentrenamiento, propagación de etiquetas; modelos preentrenados Como el supervisado en la parte etiquetada
Refuerzo Interacción: estado, acción, recompensa Aprender una política que maximice la recompensa acumulada Qué cupón ofrecer; ajuste dinámico de precios; control de la flota Bandidos, Q-learning, gradiente de política Recompensa acumulada frente a una política de referencia

  1. Ejemplos en Python: clasificación, regresión, clustering y un bandido multibrazo

Los cuatro ejemplos son deliberadamente cortos: el objetivo es reconocer la forma de cada tipo de problema. Los algoritmos se explican en 04-04 y la evaluación correcta en 04-05; aquí usaremos medidas provisionales. Suponemos que la función generar_pedidos_ml de 04-01 está guardada en novamarket_ml.py.

7.1 Clasificación: devuelto sí/no

Repetimos el problema de 04-01 con otro algoritmo (regresión logística) para comprobar que la interfaz es idéntica:

from novamarket_ml import generar_pedidos_ml
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

pedidos = generar_pedidos_ml(3000, 42)
columnas = ["importe", "num_articulos", "dias_entrega", "cliente_nuevo"]
X_train, X_test, y_train, y_test = train_test_split(
    pedidos[columnas], pedidos["devuelto"], test_size=0.25, random_state=42,
    stratify=pedidos["devuelto"])

clf = LogisticRegression(max_iter=1000).fit(X_train, y_train)   # entrenar
print("Aciertos en test:", round(clf.score(X_test, y_test), 3))

ejemplo = X_test.iloc[[0]]              # el primer pedido del conjunto de test
print(ejemplo)
print("Predicción:", clf.predict(ejemplo), "Probabilidades:", clf.predict_proba(ejemplo).round(3))

Salida:

Aciertos en test: 0.883
      importe  num_articulos  dias_entrega  cliente_nuevo
1965    87.57              5             7              0
Predicción: [0] Probabilidades: [[0.938 0.062]]

La etiqueta es una categoría (0/1) y la salida, una clase más una probabilidad por clase: la firma de la clasificación. La regresión logística acierta algo más que el árbol de 04-01 (88,3 % frente a 86,8 %), pero recuerda la advertencia sobre la exactitud con clases desequilibradas: no concluyas nada hasta 04-05.

7.2 Regresión: previsión de la demanda semanal

Necesitamos una serie de ventas. La función generar_demanda_semanal crea las unidades vendidas por semana de un producto ficticio (el robot aspirador NovaClean) con una tendencia creciente, una estacionalidad anual, el pico del Black Friday y ruido. Añádela también a novamarket_ml.py:

import numpy as np
import pandas as pd

def generar_demanda_semanal(semanas=104, semilla=42):
    """Unidades vendidas por semana del robot aspirador NovaClean (ficticio)."""
    rng = np.random.default_rng(semilla)
    t = np.arange(semanas)
    tendencia = 400 + 2.5 * t                                  # crecimiento lento
    estacionalidad = 60 * np.sin(2 * np.pi * (t - 13) / 52)    # pico anual
    black_friday = np.where(t % 52 == 47, 250, 0)              # semana del Black Friday
    ruido = rng.normal(0, 25, semanas)
    unidades = np.round(tendencia + estacionalidad + black_friday + ruido).astype(int)
    fechas = pd.date_range("2024-01-01", periods=semanas, freq="W-MON")
    return pd.DataFrame({"semana": t + 1, "fecha": fechas, "unidades": unidades})

Y el modelo, una regresión lineal que usa solo el número de semana como característica:

from sklearn.linear_model import LinearRegression

demanda = generar_demanda_semanal(104, 42)      # dos años de ventas
print(demanda.head(3))

train = demanda[demanda["semana"] <= 78]         # primeros 18 meses para entrenar
test = demanda[demanda["semana"] > 78]           # últimos 6 meses para comprobar

reg = LinearRegression().fit(train[["semana"]], train["unidades"])
print("Pendiente:", reg.coef_.round(2), "Ordenada:", round(reg.intercept_, 1))

prevision = reg.predict(test[["semana"]])
error_medio = np.abs(prevision - test["unidades"]).mean()
print("Error medio en test:", round(error_medio, 1), "unidades")
print("Previsión semana 105:", reg.predict(pd.DataFrame({"semana": [105]})).round(0))

Salida:

   semana      fecha  unidades
0       1 2024-01-01       348
1       2 2024-01-08       317
2       3 2024-01-15       366
Pendiente: [2.74] Ordenada: 391.0
Error medio en test: 47.3 unidades
Previsión semana 105: [679.]

Explicación:

  • La etiqueta (unidades) es un número: regresión. LinearRegression aprende una recta unidades ≈ 391 + 2,74 × semana; la pendiente 2,74 se acerca a la tendencia real de 2,5 unidades por semana que escondimos en el generador.
  • Dividimos por tiempo, no al azar: entrenamos con el pasado (semanas 1-78) y probamos con el futuro (79-104). Barajar semanas mezclaría futuro y pasado, y el resultado sería engañosamente bueno. Es la validación temporal de 04-05.
  • El error medio de 47 unidades es grande porque la recta ignora la estacionalidad y el Black Friday. En 04-03 y 04-04 añadiremos características (semana del año, ventas de la semana anterior) para capturarlos. Lo que importa ahora es la forma del problema: entrada numérica, salida numérica.

7.3 Clustering: segmentar clientes con k-means

Ahora no hay etiqueta. Generamos clientes ficticios con tres características de comportamiento (gasto anual, número de pedidos, antigüedad en meses) y pedimos a k-means que encuentre tres grupos. Añade la función a novamarket_ml.py:

def generar_clientes_ml(n=600, semilla=42):
    """Clientes ficticios de NovaMarket para segmentación (sin etiqueta)."""
    rng = np.random.default_rng(semilla)
    # tres tipos "ocultos": ocasionales, habituales, grandes compradores
    tipo = rng.choice([0, 1, 2], size=n, p=[0.55, 0.35, 0.10])
    gasto = np.where(tipo == 0, rng.normal(150, 50, n),
             np.where(tipo == 1, rng.normal(700, 150, n), rng.normal(2200, 400, n)))
    pedidos = np.where(tipo == 0, rng.poisson(2, n),
               np.where(tipo == 1, rng.poisson(9, n), rng.poisson(20, n)))
    antiguedad = np.where(tipo == 0, rng.integers(1, 18, n),
                  np.where(tipo == 1, rng.integers(6, 48, n), rng.integers(12, 72, n)))
    return pd.DataFrame({
        "gasto_anual": np.clip(gasto, 10, None).round(2),
        "num_pedidos": np.clip(pedidos, 1, None),
        "antiguedad_meses": antiguedad,
    })
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

clientes = generar_clientes_ml(600, 42)
print(clientes.head(3))

escalador = StandardScaler()                     # pone las 3 columnas en la misma escala
X_clientes = escalador.fit_transform(clientes)

kmeans = KMeans(n_clusters=3, n_init=10, random_state=42)
clientes["segmento"] = kmeans.fit_predict(X_clientes)   # no hay y: solo X

resumen = clientes.groupby("segmento").agg(
    n=("gasto_anual", "size"), gasto_medio=("gasto_anual", "mean"),
    pedidos_medios=("num_pedidos", "mean"), antiguedad_media=("antiguedad_meses", "mean")
).round(1)
print(resumen)

Salida:

   gasto_anual  num_pedidos  antiguedad_meses
0       722.29            7                27
1       137.37            3                15
2       762.62            7                37
          n  gasto_medio  pedidos_medios  antiguedad_media
segmento
0       351        185.8             2.5               9.5
1        52       2206.7            20.0              38.9
2       197        699.9             9.2              28.5

Explicación:

  • Fíjate en que fit_predict recibe solo X: no hay etiqueta que aprender. El algoritmo asigna cada cliente al grupo cuyo centro está más cerca (04-04 explica el detalle).
  • StandardScaler es necesario porque k-means mide distancias: sin escalar, el gasto anual (cientos o miles de euros) dominaría por completo frente al número de pedidos (unidades). Escalado y distancias se tratan en 04-03.
  • La interpretación la pone el negocio, no el algoritmo. Mirando el resumen, Marta bautiza los segmentos: el 0 son ocasionales (351 clientes, gastan 186 € al año en 2-3 pedidos, llevan menos de un año), el 2 son habituales (197 clientes, unos 700 € en 9 pedidos, más de dos años) y el 1 son grandes compradores (52 clientes, 2.200 € en 20 pedidos). Para el recomendador (caso 1) esto significa, por ejemplo, que a los ocasionales conviene sugerirles productos de entrada y a los grandes compradores novedades y accesorios de gama alta. Los números de los segmentos (0, 1, 2) son arbitrarios: si cambias la semilla pueden permutarse.
  • Los grupos que k-means ha encontrado coinciden con los tres "tipos ocultos" del generador; en un dataset real no tendríamos esa confirmación, y habría que validar los segmentos con el equipo comercial y con el método del codo (04-04).

7.4 Refuerzo en miniatura: un bandido multibrazo para los cupones

El "bandido multibrazo" es el problema de refuerzo más simple: varias máquinas tragaperras (brazos) con probabilidades de premio desconocidas, y hay que decidir cuál accionar en cada ronda para ganar lo máximo. No hay estado (siempre es la misma situación) y la recompensa es inmediata, así que solo queda el dilema exploración-explotación. Lo programamos en Python puro para los cuatro cupones de NovaMarket; la recompensa es 1 si el cliente vuelve a comprar en el mes siguiente:

import random

def simular_cupones(epsilon, rondas=5000, semilla=1):
    rng = random.Random(semilla)
    # Tasas REALES de recompra tras cada cupón: el agente NO las conoce
    tasas_reales = {"sin cupon": 0.05, "5 %": 0.08, "envio gratis": 0.11, "10 %": 0.09}
    cupones = list(tasas_reales)
    veces = {c: 0 for c in cupones}       # cuántas veces se ha probado cada cupón
    exitos = {c: 0 for c in cupones}      # cuántas recompras ha producido
    total = 0
    for _ in range(rondas):
        if rng.random() < epsilon:                                    # EXPLORAR
            elegido = rng.choice(cupones)
        else:                                                         # EXPLOTAR
            elegido = max(cupones, key=lambda c: exitos[c] / veces[c] if veces[c] else 0)
        recompensa = 1 if rng.random() < tasas_reales[elegido] else 0  # el entorno responde
        veces[elegido] += 1
        exitos[elegido] += recompensa
        total += recompensa
    return total, veces

for eps in (0.0, 0.1, 0.5):
    total, veces = simular_cupones(eps)
    print(f"epsilon={eps}: {total} recompras; pruebas por cupón: {veces}")

Salida:

epsilon=0.0: 294 recompras; pruebas por cupón: {'sin cupon': 5000, '5 %': 0, 'envio gratis': 0, '10 %': 0}
epsilon=0.1: 510 recompras; pruebas por cupón: {'sin cupon': 411, '5 %': 123, 'envio gratis': 4091, '10 %': 375}
epsilon=0.5: 505 recompras; pruebas por cupón: {'sin cupon': 620, '5 %': 610, 'envio gratis': 3118, '10 %': 652}

Explicación:

  • El agente mantiene, para cada cupón, una estimación de su tasa de éxito (exitos / veces). Con probabilidad epsilon elige un cupón al azar (explora); si no, elige el de mejor estimación (explota). La estimación se actualiza con cada recompensa: eso es el aprendizaje.
  • Con epsilon=0 (solo explotar) el agente prueba "sin cupón" en la primera ronda, obtiene una estimación positiva antes que las demás y nunca vuelve a probar otra cosa: 294 recompras. Es la trampa de no explorar, la versión de refuerzo del óptimo local de 03-04.
  • Con epsilon=0.1 descubre pronto que el envío gratis funciona mejor (11 %) y lo usa 4.091 veces: 510 recompras, un 73 % más. Con epsilon=0.5 explora demasiado y pierde un poco (505). El valor de ε es un hiperparámetro y su ajuste es un problema clásico.
  • Un sistema real añadiría el estado (el cupón óptimo depende del carrito y del cliente: "bandido contextual") y el coste del cupón en la recompensa. Pero la esencia ya está aquí: aprender actuando, sin dataset previo, equilibrando exploración y explotación.

Errores Comunes y Consejos

  • Confundir clasificación con regresión por el tipo de dato. La pregunta define el problema: "cuánto" es regresión, "cuál/si" es clasificación. Predecir el importe es regresión; predecir si supera un umbral es clasificación.
  • Usar clustering esperando "la respuesta". k-means siempre encuentra grupos; su valor depende de que sean interpretables y accionables. Ponles nombre, compáralos y valida con negocio.
  • Barajar series temporales. En demanda, entrenar con el pasado y evaluar con el futuro; nunca train_test_split con barajado (04-05 lo formaliza con TimeSeriesSplit).
  • Olvidar escalar antes de agrupar. Sin StandardScaler, la columna de mayor magnitud decide los grupos.
  • Pensar que refuerzo es "mejor" porque suena avanzado. Necesita muchas interacciones y un entorno donde equivocarse sea barato (o simulable). Para la mayoría de los casos de NovaMarket, supervisado y no supervisado son la respuesta; el refuerzo tiene sentido en decisiones repetidas con retroalimentación rápida (cupones, precios).
  • Ignorar los datos sin etiquetar. Si la mitad de incidencias.csv está sin categoría, no la descartes sin pensar: puede servir para semi-supervisado o, al menos, para entender la distribución.

Ejercicios

Ejercicio 1. Clasifica cada uno de los nueve casos de uso de NovaMarket (recomendación, previsión de demanda, fraude/devoluciones, clasificación de reseñas, rutas, asignación de pedidos, asistente, reglas de devoluciones/garantías, diagnóstico de incidencias) según el paradigma o técnica principal que aplicarías: supervisado (clasificación o regresión), no supervisado, refuerzo, o "no es ML" (búsqueda/optimización del módulo 3, lógica del módulo 6, IA generativa del módulo 5). Justifica cada uno en una línea.

Ejercicio 2. En la regresión de la sección 7.2, cambia el corte temporal para entrenar solo con el primer año (semana <= 52) y evaluar con el segundo. ¿Empeora o mejora el error medio? Después, comete a propósito el error de barajar: sustituye el modelo por KNeighborsRegressor(n_neighbors=3) (de sklearn.neighbors, que predice con la media de las 3 semanas más parecidas) y compáralo con la división temporal (semanas 1-78 / 79-104) y con una división barajada train_test_split(demanda[["semana"]], demanda["unidades"], test_size=0.25, random_state=42). ¿Por qué el error sale menor con el barajado y por qué es engañoso?

Ejercicio 3. Modifica simular_cupones para que la exploración cambie con el tiempo: durante las primeras 400 rondas elige siempre al azar (ε = 1) y a partir de ahí explota casi siempre (ε = 0,02). Compara las recompras totales con epsilon=0.1 para varias semillas (semilla=1..5). Prueba también una ε que decrezca rápido, epsilon = max(0.01, 1 / (ronda + 1) ** 0.5). ¿Qué estrategia funciona mejor y por qué?

Soluciones

Solución 1. (1) Recomendación: no supervisado (segmentación) y supervisado (predecir la probabilidad de compra), a veces con refuerzo para elegir qué mostrar. (2) Previsión de demanda: supervisado, regresión sobre serie temporal. (3) Fraude/devoluciones: supervisado, clasificación; detección de anomalías (no supervisado) cuando no hay etiquetas de fraude. (4) Clasificación de reseñas: supervisado, clasificación multiclase sobre texto (con modelos preentrenados auto-supervisados, módulo 5). (5) Rutas: no es ML, es búsqueda/optimización (03-02, 03-04). (6) Asignación de pedidos: optimización (03-04); podría añadirse ML para prever tiempos. (7) Asistente: IA generativa (LLM, 05-05), no ML clásico entrenado por Marta. (8) Reglas de devoluciones/garantías: lógica y sistemas expertos (módulo 6), no ML. (9) Diagnóstico de incidencias: supervisado (clasificación de tickets), con semi-supervisado si faltan etiquetas; también sistemas expertos para la parte de reglas (06-04).

Solución 2. Entrenando solo con el primer año, la recta se ajusta con menos puntos y la tendencia estimada es peor, así que el error en el segundo año crece (unas 59 unidades frente a 47). Con KNeighborsRegressor(n_neighbors=3), la división temporal da un error medio de unas 36 unidades y la barajada, de unas 29: el barajado parece mejor. Es engañoso porque, al barajar, las "3 semanas más parecidas" de una semana de test son sus vecinas inmediatas, que el modelo ha visto en entrenamiento; en producción, para prever la semana 105 no dispones de las ventas de la 104 ni, mucho menos, de la 106. La división temporal reproduce la situación real (predecir el futuro con el pasado) y por eso es la única honesta; en 04-05 la formalizaremos con TimeSeriesSplit.

Solución 3. La estrategia "explorar 400 rondas y luego explotar" iguala o supera a ε = 0,1 en la mayoría de las semillas (en nuestras pruebas, 512/551/517/493/534 recompras frente a 510/552/461/409/508): tras 400 pruebas repartidas (unas 100 por cupón) la estimación de cada tasa ya es razonable y no merece la pena seguir gastando el 10 % de las rondas en explorar. En cambio, la ε que decrece como 1/√ronda funciona peor (unas 380 recompras con la semilla 1): baja tan deprisa que a las pocas decenas de rondas ya casi no explora, y se queda "enganchada" al cupón que tuvo suerte al principio, con estimaciones basadas en muy pocas pruebas. La lección es doble: hay que explorar lo suficiente antes de comprometerse (el equivalente a los reinicios aleatorios de 03-04) y, si el entorno cambia (un cupón deja de funcionar), una ε casi nula tarda mucho en enterarse; en la práctica se mantiene siempre una exploración mínima.

Conclusión

En esta lección hemos organizado el machine learning en sus grandes paradigmas: el supervisado (clasificación cuando la etiqueta es una categoría, regresión cuando es un número), el no supervisado (clustering, reducción de dimensionalidad, detección de anomalías, donde no hay etiqueta y la interpretación la pone el negocio), los intermedios semi-supervisado y auto-supervisado, y el aprendizaje por refuerzo, en el que un agente aprende actuando y recibiendo recompensas, con el dilema exploración-explotación como rasgo distintivo. Los hemos comparado en una tabla y los hemos visto en código sobre NovaMarket: la regresión logística para las devoluciones, la regresión lineal para la demanda del NovaClean (con la nueva función generar_demanda_semanal), k-means para segmentar clientes (con generar_clientes_ml) en ocasionales, habituales y grandes compradores, y un bandido epsilon-greedy para elegir cupones.

Ya sabemos qué tipo de problema es cada caso de uso. Pero, antes de entrenar nada serio, hay que hacer el trabajo que en 04-01 dijimos que se lleva la mayor parte del tiempo: en la siguiente lección, Preparación de Datos y Características, tomaremos una versión "sucia" de los pedidos de NovaMarket (valores ausentes, un importe imposible, categorías en texto, fechas) y construiremos paso a paso el pipeline que los convierte en la matriz numérica que los algoritmos necesitan, evitando por el camino la fuga de información que arruina tantos proyectos.

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