Modelos: aprender de ejemplos
En resumen: Un modelo de machine learning aprende la regla a partir de ejemplos (características X y objetivo y) con fit, predice con predict y se comprueba con los datos de prueba frente a una línea base.
Problema
«¿Cuánta gente pongo en el almacén?»
La jefa hace el horario del almacén para la semana que viene: cuánta gente recibe y empaqueta los pedidos cada día. Hasta ahora lo calcula a ojo. Quiere un número para cada día. Aquí están los pedidos del último año, por días:
Son 365 días, y llegan de media 30,45 pedidos por día. Contamos todos los pedidos, también los cancelados: la pregunta es cuántos llegan, y un pedido cancelado también se recibe y se tramita. Junto a cada día están el día de la semana (0 es lunes, 6 es domingo) y el mes. ¿Cómo sacas, a partir de estos ejemplos, un número para el viernes 6 de noviembre?
La idea
Primero la pregunta
Antes del modelo preguntas qué decisión vas a tomar con la predicción. Aquí es cuánta gente poner cada día. De ahí salen tres cosas:
- Qué predices. El número de pedidos del día, no los ingresos: el empaquetado depende de los pedidos.
- Qué sabes de antemano. El horario se hace el domingo. Entonces conoces el día de la semana y el mes de cada día. Cuántos pedidos llegarán hasta el mediodía del miércoles no lo sabes.
- Qué exactitud necesita. La suficiente para no cambiar la decisión: si la predicción se equivoca en menos de lo que atiende una persona, el horario es el mismo.
Si el horario no cambia sea cual sea la predicción, no necesitas un modelo.
La idea
Un modelo es una función aprendida de ejemplos
Un modelo es una función: le das el día y devuelve una predicción. No escribes la regla. Das ejemplos, días con su número de pedidos conocido, y el modelo encuentra solo una regla que se ajuste a ellos. La entrada se llama características y se escribe X. Lo que predices es el objetivo, y.
El día de la semana es un número de 0 a 6, pero no es una cantidad: el domingo (6) no es «tres veces el miércoles» (2). Por eso cada valor se convierte en su propia columna de 0 y 1. Es la codificación one-hot, y pd.get_dummies la hace:
Son 19 columnas: 7 para los días y 12 para los meses. El 1 de noviembre de 2025 es sábado, así que su fila tiene un 1 solo en weekday_5 (y en month_11, que está más a la derecha).
La idea
fit, predict y la prueba
Los modelos de scikit-learn tienen los mismos dos pasos:
fit(X, y)aprende de los ejemplos;predict(X)da una predicción para filas nuevas.
Si el modelo es bueno lo compruebas con días que no ha visto. train_test_split baraja las filas y las divide: el 75 % es para el entrenamiento y el 25 % para la prueba. Con random_state=42 la división es la misma en cada ejecución. La primera carga de scikit-learn (junto con scipy) descarga unos 18 MB y tarda unos segundos:
El modelo aprende de 273 días, y 92 días son para la prueba. En ellos se equivoca en 4,38 pedidos al día de media: el promedio de las diferencias entre el hecho y la predicción, sin signo. En los días de entrenamiento el error es 4,09. Allí el modelo siempre se ve mejor, porque ha visto las respuestas. Por eso el número que informas es el de la prueba.
LinearRegression es un modelo que suma un número por cada columna. Cómo los encuentra está en la próxima lección. Aquí solo importan fit y predict, y son iguales en cualquier modelo.
Más precisamente, para curiosos
Los días están ordenados en el tiempo, y train_test_split los baraja. Aquí es una simplificación: el modelo aprende sobre septiembre también con días posteriores al día de prueba. En la próxima lección verás por qué en una predicción es más honesto dividir por tiempo: entrenas con los meses anteriores y compruebas con los posteriores. Cómo aprende un modelo a mano, sin biblioteca, está en la lección Regresión lineal del curso de IA.
La idea
Primero una línea base
¿Es bueno un error de 4,38 pedidos? Sin comparar no lo sabes. Comparas con una línea base (baseline): una predicción sin modelo, que a cualquiera se le ocurriría. Por ejemplo «siempre la media». DummyRegressor es justo eso, con los mismos fit y predict:
La línea base dice 30,34 para cada día: la media de los días de entrenamiento. Se equivoca en 5,76 pedidos, y el modelo en 4,38. El modelo es 1,38 pedidos más exacto, con un error un 24 % menor. Tiene sentido.
Un modelo que no supera la línea base no vale nada. Es código, datos y mantenimiento, y da tanto como «siempre 30». Por eso la línea base va primero. Otra buena línea base es lo que hace la gente ahora, por ejemplo «tantos como el mismo día de la semana pasada».
Pruébalo
La regla «como la semana pasada»
Ahora mismo la jefa planifica «tantos como el mismo día de la semana pasada». ¿Cuánto se equivoca esta regla en los días de prueba? Pon en last_week los pedidos de 7 días antes para cada día, y en err el error medio sin signo en los días de y_test.
Solución
import numpy as np
import pandas as pd
orders = pd.read_csv('year_orders.csv')
orders['ordered_at'] = pd.to_datetime(orders['ordered_at'])
daily = orders.set_index('ordered_at').resample('D').size().rename('orders').to_frame()
daily['weekday'] = daily.index.dayofweek
daily['month'] = daily.index.month
X = pd.get_dummies(daily[['weekday', 'month']], columns=['weekday', 'month'], dtype=int)
y = daily['orders']
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
model = LinearRegression().fit(X_train, y_train)
last_week = y.shift(7)
err = (y_test - last_week[y_test.index]).abs().mean()
print(round(err, 2))La regla se equivoca en 6,16 pedidos de media en los días de prueba: más que incluso «siempre la media» (5,76). Un solo día de la semana pasada trae su propio ruido, y la media de 273 días lo suaviza. shift(7) toma el valor de 7 filas antes, es decir, de una semana antes. Tres de los días de prueba caen en la primera semana y no tienen semana anterior, y mean() se salta los vacíos. shift(-7) tomaría la semana que viene: un futuro que no conoces cuando haces el horario.
Ejercicio
¿Basta el día? Y el plan para la semana que viene
¿Basta el día de la semana solo, sin el mes? Entrena LinearRegression solo con las columnas de día de la semana de X_train. Pon en err el error medio en los días de prueba, en base el error de «siempre la media del entrenamiento» y en beats si el modelo la supera.
Solución
import numpy as np
import pandas as pd
orders = pd.read_csv('year_orders.csv')
orders['ordered_at'] = pd.to_datetime(orders['ordered_at'])
daily = orders.set_index('ordered_at').resample('D').size().rename('orders').to_frame()
daily['weekday'] = daily.index.dayofweek
daily['month'] = daily.index.month
X = pd.get_dummies(daily[['weekday', 'month']], columns=['weekday', 'month'], dtype=int)
y = daily['orders']
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
model = LinearRegression().fit(X_train, y_train)
week_cols = [c for c in X.columns if c.startswith('weekday')]
week_model = LinearRegression().fit(X_train[week_cols], y_train)
err = np.abs(y_test - week_model.predict(X_test[week_cols])).mean()
base = np.abs(y_test - y_train.mean()).mean()
beats = err < base
print(round(err, 2), round(base, 2), beats)Solo con el día, el modelo se equivoca en 5,52 pedidos, y la línea base en 5,76. La supera, pero por 0,24 pedidos: por los pelos. El mes aporta más: con él el error es 4,38. Medido en los días de entrenamiento el modelo se ve mejor (5,00), pero esos días los ha visto. Y la media de y_test como línea base es una respuesta que no debes conocer.
La prueba dijo que el modelo con el día y el mes supera la línea base. Ahora la predicción para la semana real, del lunes 2 al domingo 8 de noviembre de 2026. Entrena el modelo otra vez con los 365 días, crea X_new con las columnas de X y pon en plan la predicción para cada día (una Series con las fechas como índice).
Solución
import numpy as np
import pandas as pd
orders = pd.read_csv('year_orders.csv')
orders['ordered_at'] = pd.to_datetime(orders['ordered_at'])
daily = orders.set_index('ordered_at').resample('D').size().rename('orders').to_frame()
daily['weekday'] = daily.index.dayofweek
daily['month'] = daily.index.month
X = pd.get_dummies(daily[['weekday', 'month']], columns=['weekday', 'month'], dtype=int)
y = daily['orders']
from sklearn.linear_model import LinearRegression
final = LinearRegression().fit(X, y)
dates = pd.date_range('2026-11-02', periods=7)
week = pd.DataFrame({'weekday': dates.dayofweek, 'month': dates.month}, index=dates)
X_new = pd.get_dummies(week, columns=['weekday', 'month'], dtype=int).reindex(columns=X.columns, fill_value=0)
plan = pd.Series(final.predict(X_new), index=dates).round(1)
print(plan)La predicción es 32,9, 32,0, 31,6, 33,1, 37,9, 29,6 y 26,0 pedidos de lunes a domingo. El viernes es el más fuerte y el domingo el más débil. Después de la comprobación, el modelo se entrena con todos los días: los últimos meses son los más cercanos a lo que viene. get_dummies sobre los siete días da solo month_11, y reindex(columns=X.columns, fill_value=0) añade las columnas que faltan con 0 en el orden de X. Si le das al modelo el día y el mes como números, la predicción baja de forma pareja de 35,6 el lunes a 31,3 el domingo: el modelo ve el día como una cantidad.
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Seleccionar: [], loc e iloc · Columnas nuevas · Tipos y valores faltantes · Fechas y series temporales
- Continúa en: Regresión lineal · Clasificación · Fuga de datos · Validación cruzada
- Ejercicios sobre el tema: Modelos con scikit-learn