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
- Los cuatro paradigmas de un vistazo
- Aprendizaje supervisado: clasificación y regresión
- Aprendizaje no supervisado: clustering, reducción de dimensionalidad y anomalías
- Semi-supervisado y auto-supervisado
- Aprendizaje por refuerzo
- Tabla comparativa de paradigmas
- Ejemplos en Python: clasificación, regresión, clustering y un bandido multibrazo
- Errores Comunes y Consejos
- Ejercicios
- Conclusión
- 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.
- 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).
- 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.
- 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.csven 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.
- 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).
- 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 |
- 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.LinearRegressionaprende una rectaunidades ≈ 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.5Explicación:
- Fíjate en que
fit_predictrecibe 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). StandardScaleres 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 probabilidadepsilonelige 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.1descubre pronto que el envío gratis funciona mejor (11 %) y lo usa 4.091 veces: 510 recompras, un 73 % más. Conepsilon=0.5explora 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_splitcon barajado (04-05 lo formaliza conTimeSeriesSplit). - 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.csvestá 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
- 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
