Saltar al contingut principal
Capítol 3.2 intermedi feature engineering lags sklearn dummies estacionals rolling

Variables temporals com a predictors

4 min lectura
Com transformar una sèrie temporal en un dataset tabular per a sklearn usant variables lag, mitjanes mòbils com a features i dummies estacionals.

Una regressió lineal amb només l’índex temporal com a predictor captura la tendència però ignora tot allò altre. La solució no és canviar de model: és construir millors variables. Aquest procés —convertir la sèrie en un dataset tabular— s’anomena feature engineering temporal i és la base de gairebé tots els models de ML aplicats a sèries temporals.


De sèrie a taula

Per usar sklearn necessites un DataFrame on cada fila és un instant de temps i cada columna és una feature. La clau és que totes les features han de ser conegudes en el moment de la predicció: mai pots usar informació futura.

import numpy as np
import pandas as pd

np.random.seed(42)
dates = pd.date_range(start='2020-01-01', periods=60, freq='ME')
t = np.arange(60)
vendes = 50 + 0.8 * t + 10 * np.sin(2 * np.pi * t / 12) + np.random.normal(0, 4, 60)
serie = pd.Series(vendes, index=dates, name='vendes')

df = pd.DataFrame({'vendes': serie})

Variables lag: el passat com a predictor

La feature més natural en una sèrie temporal és el valor de períodes anteriors. Si les vendes d’aquest mes depenen de les del mes passat, el lag 1 captura aquesta dependència.

# Lags: valor de períodes anteriors
df['lag_1'] = df['vendes'].shift(1)   # Valor del mes anterior
df['lag_2'] = df['vendes'].shift(2)   # Valor de fa 2 mesos
df['lag_12'] = df['vendes'].shift(12) # Valor del mateix mes fa 1 any

Compte amb el data leakage: shift(1) és segur perquè usa el valor del mes anterior per predir l’actual. Usar shift(0) seria trampa: estaries predint amb el valor que vols predir.


Mitjanes mòbils: suavitzar el passat

Les mitjanes mòbils capturen tendències recents sense el soroll d’un sol valor:

# Mitjanes mòbils de finestres anteriors (sempre amb shift per evitar leakage)
df['mitj_mov_3'] = df['vendes'].shift(1).rolling(window=3).mean()
df['mitj_mov_6'] = df['vendes'].shift(1).rolling(window=6).mean()
df['std_mov_3'] = df['vendes'].shift(1).rolling(window=3).std()

El shift(1) abans del rolling és important: garanteix que la mitjana dels últims 3 mesos no inclou el mes actual.


L’índex temporal explícit

Per capturar la tendència global, l’índex numèric del temps és una feature vàlida i senzilla:

df['t'] = np.arange(len(df))
df['mes'] = df.index.month
df['trimestre'] = df.index.quarter
df['any'] = df.index.year

Dummies estacionals: capturar l’estacionalitat

Si la sèrie té estacionalitat, els mesos de l’any són features molt informatives:

# Dummies de mes (gener és la categoria de referència amb drop_first=True)
dummies_mes = pd.get_dummies(df['mes'], prefix='mes', drop_first=True)
df = pd.concat([df, dummies_mes], axis=1)
FeatureTipusCaptura
lag_1, lag_2NumèricaDependència de curt termini
lag_12NumèricaEstacionalitat anual via el passat
mitj_mov_3NumèricaTendència recent suavitzada
tNumèricaTendència global
mes_2mes_12BinàriaEfecte estacional per mes

Eliminar files amb NaN i ajustar el model

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error

feature_cols = ['t', 'lag_1', 'lag_2', 'lag_12', 'mitj_mov_3'] + [c for c in df.columns if c.startswith('mes_')]
df_model = df[feature_cols + ['vendes']].dropna()

X = df_model[feature_cols]
y = df_model['vendes']

train_size = len(df_model) - 12
X_train, X_test = X.iloc[:train_size], X.iloc[train_size:]
y_train, y_test = y.iloc[:train_size], y.iloc[train_size:]

model = LinearRegression()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)
mae = mean_absolute_error(y_test, y_pred)
rmse = mean_squared_error(y_test, y_pred) ** 0.5

print(f'MAE:  {mae:.2f}')
print(f'RMSE: {rmse:.2f}')

Quines features afegir segons el tipus de sèrie

Característica de la sèrieFeatures recomanades
Tendència lineal fortat, si és quadràtica
Estacionalitat anuallag_12, dummies mes_*
Alta autocorrelació curt terminilag_1, lag_2, mitj_mov_3
Volatilitat variablestd_mov_3, std_mov_6
Sense estacionalitat claraEvitar dummies de mes

Resum

El feature engineering temporal transforma el problema de predicció de sèries en un problema de regressió estàndard. Les peces clau són: lags per capturar dependència, mitjanes mòbils per suavitzar tendències recents i dummies estacionals per als patrons cíclics. Al pròxim subcapítol veuràs com encaixa tot això en un exemple complet pas a pas.