Series temporales
Librerías de Python para forecasting clásico, ML unificado y deep learning
Sobre series temporales en Python
El ecosistema Python para series temporales se entiende mejor leyéndolo como tres eras superpuestas, cada una con su propia filosofía y su propia trampa principal:
- Estadística clásica (años 70-2000). ARIMA, ETS, VAR, descomposición STL. La referencia operativa en Python es
statsmodels, conpmdarimacomo envoltorio para la selección automática estiloauto.arima. La virtud es la interpretabilidad, coeficientes, intervalos de confianza, tests de raíz unitaria, y el coste es el trabajo manual de diagnóstico (estacionariedad, autocorrelación residual, diferenciación). - Wrappers de ML (2017-2022).
prophet(Meta) populariza el enfoque aditivo trend + seasonality + holidays para usuarios no estadísticos.sktimepropone una API unificada estilo scikit-learn para forecasting, clasificación y anomaly detection sobre series.tsfreshautomatiza la extracción de cientos de features estadísticas para empujar el problema a un pipeline tabular clásico. - Deep learning y forecasting probabilístico (2020-).
dartsintegra modelos clásicos y neuronales (N-BEATS, TFT, RNN, TCN) con un objetoTimeSeriespropio y soporte nativo de cuantiles.neuralforecast(Nixtla) ofrece SOTA neural baselines (NHITS, TFT, PatchTST) con foco en rendimiento y multi-series. Son la opción razonable cuando tienes muchas series correlacionadas o necesitas distribuciones predictivas, no solo puntuales.
Convivencias prácticas:
# Versiones de referencia para esta página
# pip install statsmodels==0.14 prophet==1.1 sktime==0.32 darts==0.31 \
# neuralforecast==1.7 pmdarima==2.0 tsfresh==0.20Tres principios que conviene tener interiorizados antes de elegir librería:
- El índice manda. Un
DatetimeIndexcon frecuencia explícita (asfreq("D"),"H","MS"…) y sin duplicados es prerrequisito para casi todo. La mayoría de errores opacos en producción nacen de timestamps irregulares, gaps silenciosos o zonas horarias inconsistentes. - Validación temporal, no aleatoria. Cualquier split que no respete el orden cronológico es data leakage. Usa
TimeSeriesSplit(sklearn) oExpandingWindowSplitter/SlidingWindowSplitter(sktime). Nuncatrain_test_splitaleatorio sobre series temporales. - Multi-horizonte vs recursivo. Predecir 24 pasos puede hacerse con un modelo direct (un modelo por horizonte o un output multi-step) o iterando un modelo one-step ahead. La elección afecta la propagación del error y el coste de entrenamiento. Conviene decidirla antes de tocar código.
Esta página cataloga siete librerías que cubren los flujos más habituales. El orden refleja jerarquía conceptual: primero la estadística clásica (statsmodels, pmdarima), después los wrappers (prophet, sktime), luego deep learning (darts, neuralforecast) y finalmente la extracción de features (tsfresh).
statsmodels
statsmodels es la referencia operativa de la estadística clásica de series temporales en Python. Incluye ARIMA / SARIMA / SARIMAX, suavizado exponencial (ETS), VAR / VECM, modelos de espacio de estados, descomposición STL, tests de raíz unitaria (ADF, KPSS) y herramientas de diagnóstico (ACF, PACF, Ljung-Box, Jarque-Bera).
Es la pieza más baja del stack. Muchas otras librerías (pmdarima, sktime, darts en su rama clásica) envuelven o reimplementan partes de statsmodels. Internalizar su API ahorra tiempo a lo largo de cualquier proyecto serio.
Cuándo usarlo
- ARIMA / SARIMA / SARIMAX con variables exógenas, cuando necesitas interpretabilidad de coeficientes y diagnóstico residual.
- ETS y modelos de espacio de estados (Kalman) para series con estructura clara de nivel / tendencia / estacionalidad.
- VAR / VECM para sistemas multivariantes con interés en relaciones de cointegración.
- Tests formales de estacionariedad (ADF, KPSS, Phillips-Perron) y changepoints básicos.
Cuándo NO usarlo
- Muchas series en paralelo.
statsmodelsajusta cada modelo individualmente. Para miles de series,neuralforecastostatsforecast(Nixtla) son órdenes de magnitud más rápidos. - Modelos profundos (RNN, TCN, Transformers). Quedan fuera del alcance, usa
dartsoneuralforecast. - Forecasting probabilístico complejo (cuantiles condicionales, distribuciones flexibles). Los intervalos de confianza de
statsmodelsson válidos pero asumen normalidad de residuos.
Conceptos clave
SARIMAX(endog, exog, order=(p,d,q), seasonal_order=(P,D,Q,s))es la API moderna. Reemplaza a la antiguaARIMAy soporta variables exógenas de serie.model.fit()devuelve unSARIMAXResults. Elforecast(steps)produce predicciones puntuales yget_forecast(steps).conf_int()los intervalos.- Diferenciación. El parámetro
d(yDestacional) aplica diferenciación interna. Si diferenciaste tú la serie antes de pasarla al modelo, no la vuelvas a diferenciar dentro, un error clásico. seasonal_decomposeySTL(más robusto) separan tendencia, estacionalidad y residuo. STL admite estacionalidad no entera y es preferible para series irregulares.- Diagnóstico residual:
plot_diagnostics()cubre ACF, histograma, Q-Q y test de Ljung-Box. Si los residuos siguen autocorrelacionados, el modelo está mal especificado.
Patrón mínimo
import pandas as pd
import statsmodels.api as sm
# y: pd.Series con DatetimeIndex y frecuencia regular (p. ej. "MS" mensual)
y = pd.read_csv("ventas.csv", parse_dates=["fecha"], index_col="fecha")["y"].asfreq("MS")
train, test = y.iloc[:-12], y.iloc[-12:]
# SARIMA con estacionalidad anual
model = sm.tsa.SARIMAX(
train,
order=(1, 1, 1),
seasonal_order=(0, 1, 1, 12),
enforce_stationarity=False,
enforce_invertibility=False,
)
res = model.fit(disp=False)
fcst = res.get_forecast(steps=12)
mean = fcst.predicted_mean
ci = fcst.conf_int(alpha=0.05)Trampas habituales
freqfaltante. Si el índice no tiene frecuencia (y.index.freq is None),statsmodelsemite warnings y los horizontes pueden no respetar el calendario. Forzar.asfreq("MS")o equivalente al cargar es disciplina mínima.- Doble diferenciación. Pasar una serie ya diferenciada con
d=1la diferencia otra vez. Si la has diferenciado a mano, usad=0o pasa la serie original. - Predicción en niveles vs diferencias. Si entrenaste sobre una transformación (log, diff), las predicciones están en la misma escala. Hay que invertir la transformación con cuidado para obtener intervalos en escala original, no es la simple
exp(...)en general. enforce_stationarity=Truepor defecto puede fallar con datos reales. Suele ser razonable desactivarlo durante el ajuste y comprobar después.
Enlaces
Relacionados en esta página
pmdarima, selección automática de órdenes ARIMA estiloauto.arima.sktime, envuelvestatsmodelsbajo una API unificada.
pmdarima
pmdarima es el port directo a Python de auto.arima (Hyndman, R forecast). Selecciona automáticamente los órdenes (p, d, q) y (P, D, Q, s) minimizando AIC / BIC y validando con tests de raíz unitaria (ADF, KPSS). El motor de ajuste es statsmodels. pmdarima aporta la búsqueda y una API estilo scikit-learn (.fit(), .predict()).
Es la opción razonable cuando necesitas un baseline ARIMA decente sin invertir tiempo en diagnóstico manual. No sustituye al análisis cuidadoso, pero produce un punto de partida muy aceptable.
Cuándo usarlo
- Baseline ARIMA / SARIMA automático sobre series individuales.
- Comparaciones rápidas en benchmarks contra modelos más sofisticados.
- Pipelines donde no hay tiempo (ni necesidad) de tunear el modelo a mano.
Cuándo NO usarlo
- Series muy largas o muy numerosas. La búsqueda stepwise es lenta. Para miles de series,
statsforecast(Nixtla) ejecutaAutoARIMAmucho más rápido y con paralelización. - Estructuras no ARIMA. Si la serie es claramente no lineal o tiene cambios de régimen, ningún
auto.arimalo resolverá. Pasa a Prophet, modelos de espacio de estados o deep learning. - Producción crítica. Por dependencia de
numpy.distutilsy compatibilidad ocasionalmente frágil con versiones recientes de Python / numpy, fija versiones explícitas si lo usas en pipelines productivos.
Conceptos clave
auto_arima(y, seasonal=True, m=12, ...)ejecuta la búsqueda.mes la longitud del ciclo estacional (12 = mensual con anual, 7 = diario con semanal, 24 = horario con diario).- Por defecto usa búsqueda stepwise (Hyndman-Khandakar). Pasar
stepwise=Falseactiva la búsqueda exhaustiva, más exacta y mucho más lenta. exogenous(renombradoXen versiones recientes) acepta variables exógenas, replicando SARIMAX.- El objeto devuelto es una
ARIMA(envoltorio sobreSARIMAXResults) que expone.predict(n_periods)y.predict(..., return_conf_int=True).
Patrón mínimo
import pmdarima as pm
# y: pd.Series con DatetimeIndex y frecuencia "MS"
train, test = y.iloc[:-12], y.iloc[-12:]
model = pm.auto_arima(
train,
seasonal=True, m=12,
stepwise=True,
suppress_warnings=True,
error_action="ignore",
)
print(model.summary())
pred, ci = model.predict(n_periods=12, return_conf_int=True, alpha=0.05)Trampas habituales
mincorrecto. El parámetro estacionalmdebe corresponderse con la frecuencia real del ciclo, no con la frecuencia muestral. Para datos semanales con estacionalidad anual,m=52. Para datos diarios con estacionalidad semanal,m=7. Equivocarlo invalida la selección.stepwise=Trueno garantiza el óptimo. Es una búsqueda greedy. En series exigentes, comparar constepwise=Falsepuede revelar modelos mejores.- Compatibilidad numpy / Python. Fija versiones en
requirements.txt.pmdarimaha sufrido roturas históricas con releases de numpy.
Enlaces
Relacionados en esta página
statsmodels, motor subyacente.sktime, alternativa con API unificada y wrapper aAutoARIMA.
Prophet
Prophet (Meta) es un modelo aditivo de descomposición que separa la serie en tendencia (lineal o logística), estacionalidad (Fourier), efectos de festivos y eventos especiales, todo dentro de un marco bayesiano ajustado con Stan. Está diseñado para producir baselines decentes con poca intervención, tolerar outliers y gaps, y permitir incorporar conocimiento de dominio (festivos, changepoints) de forma explícita.
Su público objetivo natural es el analista de negocio que necesita predicciones razonables sobre series con estacionalidad fuerte y festivos relevantes, sin invertir en diagnóstico ARIMA.
Cuándo usarlo
- Series con estacionalidades múltiples (diaria + semanal + anual) y / o festivos importantes, la API para inyectar calendarios de festivos por país es la mejor del ecosistema.
- Tendencias con cambios suaves y changepoints que quieres modelar explícitamente.
- Cuando necesitas un baseline rápido y comunicable a stakeholders no técnicos (descomposición gráfica clara).
Cuándo NO usarlo
- Series cortas o sin estacionalidad clara. El modelo asume estructura aditiva. Si la serie es ruido sobre una media plana, ARIMA / ETS clásicos suelen ser mejores.
- Forecasting probabilístico riguroso. Los intervalos de Prophet son intervalos de incertidumbre simulados sobre la tendencia, no calibrados por validación. Para cuantiles bien calibrados, mejor
dartsoneuralforecastcon quantile loss. - Multi-series correlacionadas. Prophet entrena una serie a la vez. Para global models sobre muchas series, pasa a
neuralforecastodarts. - Dependencias autorregresivas fuertes. Prophet no modela
y_{t-1}directamente. Si la serie depende fuertemente de su propio pasado a corto plazo, un ARIMA captará eso mejor.
Conceptos clave
- DataFrame de entrada con dos columnas exactas:
ds(timestamp) ey(valor). La rigidez del esquema es deliberada. growth="linear"(por defecto) ogrowth="logistic"(concapyfloor) para tendencias acotadas.add_seasonality(name, period, fourier_order)añade estacionalidades a medida (p. ej. mensual conperiod=30.5).add_country_holidays(country_name="ES")inyecta el calendario nacional.holidays(DataFrame conholiday,ds, opcionalmentelower_window/upper_window) permite festivos personalizados.add_regressor(name)admite variables exógenas (precio, promociones). Deben estar disponibles también en el horizonte de predicción.
Patrón mínimo
import pandas as pd
from prophet import Prophet
df = pd.read_csv("ventas.csv", parse_dates=["fecha"]).rename(
columns={"fecha": "ds", "valor": "y"}
)
m = Prophet(
yearly_seasonality=True,
weekly_seasonality=True,
daily_seasonality=False,
)
m.add_country_holidays(country_name="ES")
m.fit(df)
future = m.make_future_dataframe(periods=90, freq="D")
fcst = m.predict(future)
# fcst[["ds", "yhat", "yhat_lower", "yhat_upper"]]
fig = m.plot_components(fcst)Trampas habituales
- Doble conteo de festivos. Si
add_country_holidays()ya incluye Navidad y tú añades manualmente “Navidad” enholidays=, el efecto se duplica. Compruebam.train_holiday_namesdespués delfit. - Festivos en el horizonte. El calendario debe cubrir también el futuro a predecir. Si tu DataFrame de festivos personalizados solo contiene el pasado, Prophet asumirá cero efecto en el horizonte.
capyflooren crecimiento logístico. Olvidarlos lleva a errores opacos. Si usasgrowth="logistic", debes incluircap(y opcionalmentefloor) tanto en el training set como en elfuture.- Frecuencia del
make_future_dataframe. El parámetrofreqdebe coincidir con la frecuencia de los datos. Mezclarfreq="D"con datos semanales produce predicciones rotas. - Variables exógenas en el horizonte.
add_regressorexige valores futuros del regresor para predecir. Si no los tienes, no es la herramienta.
Enlaces
Relacionados en esta página
statsmodels, alternativa clásica para series con dependencia autorregresiva fuerte.darts, incluye una implementación de Prophet entre sus modelos.
sktime
sktime es la API unificada estilo scikit-learn para series temporales: forecasting, clasificación, regresión, clustering y anomaly detection. Su valor real no son los algoritmos propios sino la interfaz consistente sobre statsmodels, pmdarima, prophet, xgboost, tbats, darts y otros, con cross-validation temporal correcta y pipelines compatibles con sklearn.
Es la elección razonable cuando quieres comparar familias de modelos en igualdad de condiciones, o cuando construyes pipelines reproducibles que combinan transformaciones (detrending, deseasonalizing) con modelos finales.
Cuándo usarlo
- Benchmarking de varias familias de modelos sobre la misma serie con métricas y validación homogéneas.
- Pipelines que combinan detrending / deseasonalizing + modelo final como en sklearn.
- Reduction: convertir un problema de forecasting en uno de regresión tabular usando
make_reduction(estimator, window_length, strategy)con un regressor sklearn. - Forecasting jerárquico (
HierarchicalForecaster) y reconciliación de niveles.
Cuándo NO usarlo
- Cuando solo necesitas un modelo concreto. Si vas a usar SARIMAX y nada más, ir directo a
statsmodelses más simple. La abstracción desktimese paga en complejidad. - Deep learning serio.
sktimeintegra algunas redes pero el centro de gravedad de DL para series está endartsyneuralforecast. - Producción de baja latencia. Las capas de envoltura añaden overhead. Para inference a milisegundos, baja al motor subyacente.
Conceptos clave
ForecastingHorizon(fh, is_relative=True)define el horizonte como offsets relativos (p. ej.[1, 2, 3]) o timestamps absolutos.- Cross-validation:
ExpandingWindowSplitter(ventana creciente) ySlidingWindowSplitter(ventana fija). Ambos respetan el orden temporal. ForecastingPipelineencadena transformadores + forecaster comosklearn.Pipeline.make_reduction(estimator, strategy="recursive" | "direct" | "multioutput")adapta un regressor sklearn al problema de forecasting con la estrategia elegida.- Métricas dedicadas en
sktime.performance_metrics.forecasting:MeanAbsolutePercentageError,MeanAbsoluteScaledError,MeanSquaredError.
Patrón mínimo
from sktime.forecasting.model_selection import ExpandingWindowSplitter
from sktime.forecasting.compose import make_reduction
from sktime.forecasting.naive import NaiveForecaster
from sktime.forecasting.base import ForecastingHorizon
from sktime.performance_metrics.forecasting import MeanAbsoluteScaledError
from sklearn.ensemble import RandomForestRegressor
# y: pd.Series con PeriodIndex o DatetimeIndex regular
fh = ForecastingHorizon(list(range(1, 13)), is_relative=True)
# Baseline naive estacional
naive = NaiveForecaster(strategy="last", sp=12)
# Forecaster por reducción: window de 24 -> RandomForest, estrategia recursive
rf = make_reduction(
RandomForestRegressor(n_estimators=200, random_state=0),
window_length=24,
strategy="recursive",
)
# Validación walk-forward
cv = ExpandingWindowSplitter(initial_window=60, step_length=12, fh=fh)
from sktime.forecasting.model_evaluation import evaluate
results = evaluate(
forecaster=rf, y=y, cv=cv,
scoring=MeanAbsoluteScaledError(sp=12),
return_data=False,
)
print(results)Trampas habituales
PeriodIndexvsDatetimeIndex.sktimeprefierePeriodIndexpara muchas operaciones de forecasting. Si trabajas conDatetimeIndex, fija frecuencia explícita y prepárate a convertir.- Mezclar APIs. No combines
evaluate()(alto nivel) con bucles manuales sobrecv.split()sin entender qué subconjunto de datos ve cada paso. Es la fuente número uno de data leakage en este ecosistema. make_reduction(strategy="recursive")propaga error. Para horizontes largos, considerastrategy="direct"(un modelo por horizonte) o"multioutput"si el regressor lo soporta.- Compatibilidad de versiones.
sktimeactualiza dependencias con frecuencia. Fija versiones y revisa el changelog antes de actualizar, la API ha tenido breaking changes notables.
Enlaces
Relacionados en esta página
statsmodels,pmdarima,prophet, accesibles desdesktimecon la misma API.darts, alternativa con su propio objetoTimeSeriesy mejor soporte de DL.
darts
darts es una librería integrada de forecasting con un objeto propio (TimeSeries, basado en xarray) que unifica modelos clásicos (ARIMA, ExponentialSmoothing, Theta), de gradient boosting (LightGBMModel, XGBModel, CatBoostModel) y profundos (RNNModel, BlockRNNModel, TCNModel, NBEATSModel, TFTModel, TransformerModel, DLinearModel). Soporta global models sobre múltiples series, covariables pasadas y futuras, y forecasting probabilístico (cuantiles, distribuciones) de forma nativa.
Es probablemente la mejor opción cuando necesitas comparar familias muy distintas de modelos con la misma API y outputs probabilísticos coherentes.
Cuándo usarlo
- Global models sobre muchas series correlacionadas (cientos a miles) con un único modelo neuronal compartido.
- Forecasting probabilístico (cuantiles, intervalos calibrados) con
likelihood=...onum_samplesen inference. - Comparativa homogénea de ARIMA / ETS / LightGBM / N-BEATS / TFT sobre la misma serie.
- Covariables pasadas (solo conocidas hasta
t) y futuras (conocidas en el horizonte: día de la semana, festivo, promoción planificada).
Cuándo NO usarlo
- Dataset minúsculo (< 100 puntos). Los modelos neuronales no aportan nada. Quédate en
statsmodelsopmdarima. - Inference ultraligera. Los wrappers añaden capas. Para servir un ARIMA en milisegundos, baja a
statsmodels. - Necesidad de inferencia estadística clásica (p-values, intervalos basados en likelihood, tests de hipótesis sobre coeficientes).
dartsno es esa herramienta.
Conceptos clave
TimeSerieses la unidad básica. Se construye conTimeSeries.from_dataframe(df, time_col, value_cols)ofrom_series. Es inmutable: las transformaciones devuelven nuevos objetos.- Covariables:
past_covariates(conocidas solo hasta el presente, p. ej. otra serie observada) yfuture_covariates(conocidas en el horizonte, p. ej. calendario). La distinción es crítica: pasarlas en el slot equivocado es el error número uno. - Multi-series:
fit([ts1, ts2, ts3], ...)entrena un único modelo global sobre múltiples series. Elpredictse hace serie a serie o vectorialmente. - Probabilístico:
num_samples=500enpredict()genera muestras de la distribución predictiva. Conlikelihood=QuantileRegression(...)el modelo aprende cuantiles directamente. - Scalers (
Scaler,BoxCox) son objetos fittable compatibles con multi-series y reversibles automáticamente enpredict.
Patrón mínimo
from darts import TimeSeries
from darts.models import NBEATSModel
from darts.dataprocessing.transformers import Scaler
from darts.metrics import mape
series = TimeSeries.from_dataframe(df, time_col="ds", value_cols="y", freq="D")
train, val = series[:-90], series[-90:]
scaler = Scaler()
train_s = scaler.fit_transform(train)
val_s = scaler.transform(val)
model = NBEATSModel(
input_chunk_length=60,
output_chunk_length=14,
n_epochs=50,
random_state=0,
)
model.fit(train_s)
fcst_s = model.predict(n=90, num_samples=200) # forecasting probabilístico
fcst = scaler.inverse_transform(fcst_s)
print("MAPE:", mape(val, fcst))Trampas habituales
- Confundir
past_covariatesyfuture_covariates. Si pasas comofuture_covariatesalgo que no conoces en el horizonte, estás filtrando información del futuro al entrenamiento, data leakage puro. - Longitudes desalineadas.
dartsexige que las covariables cubran exactamente el rango requerido. Los errores son crípticos. Depura conseries.time_index[0],series.time_index[-1]. input_chunk_lengthvsoutput_chunk_length. El primero es la ventana histórica, el segundo el horizonte interno del modelo. Para predicciones más largas queoutput_chunk_length,dartsitera internamente (estrategia auto-recursiva), el error se propaga.- GPU silenciosa. Modelos grandes (TFT, Transformer) tardan mucho sin GPU.
pl_trainer_kwargs={"accelerator": "gpu"}activa CUDA si está disponible. - Reproducibilidad. Fija
random_statey, para PyTorch Lightning bajo el capó,torch.manual_seed. Sin ello, los resultados varían entre runs.
Enlaces
Relacionados en esta página
neuralforecast, alternativa centrada en SOTA neural baselines, más rápida en multi-series.sktime, API unificada con menor foco en DL.
neuralforecast
neuralforecast (de Nixtla) es una librería de modelos neuronales SOTA para forecasting con énfasis en velocidad, soporte multi-series nativo y compatibilidad con el resto del stack Nixtla (statsforecast, mlforecast, hierarchicalforecast). Incluye NHITS, N-BEATS, TFT, PatchTST, iTransformer, TimesNet, NLinear, DLinear y más, todos sobre PyTorch Lightning con una API homogénea.
Su diferencial frente a darts es la eficiencia en multi-series (entrenamiento global sobre miles de series con un único modelo) y la integración con el ecosistema Nixtla, que cubre desde ARIMA distribuido (statsforecast) hasta reconciliación jerárquica.
Cuándo usarlo
- Multi-series a escala (cientos a millones de series). El diseño global model es de primera clase y muy eficiente.
- Cuando quieres baselines neuronales fuertes (NHITS, PatchTST, TFT) sin escribir PyTorch.
- Pipelines integrados con
statsforecast(clásico) ymlforecast(gradient boosting) para comparar familias. - Forecasting probabilístico vía
loss=MQLoss(quantiles=[...]).
Cuándo NO usarlo
- Una sola serie corta. El overhead de PyTorch Lightning no compensa. Usa
statsforecastostatsmodels. - Interpretabilidad clásica. Los modelos neuronales son opacos. Si necesitas justificar coeficientes a un comité, no es la herramienta.
- Inferencia bayesiana / intervalos basados en likelihood. Aquí los intervalos vienen de regresión cuantílica, no de un modelo generativo completo.
Conceptos clave
- Esquema largo (
long format):unique_id,ds,y. Cada serie se identifica porunique_id. Multi-series es el caso por defecto, no la excepción. NeuralForecast(models=[...], freq="D")envuelve la lista de modelos. Cada modelo tieneh(horizonte) einput_sizepropios.- Exógenas estáticas (
stat_exog_list, p. ej. categoría del producto) e históricas (hist_exog_list) y futuras (futr_exog_list). La distinción es estructuralmente la misma que endarts. - Cross-validation:
nf.cross_validation(df, n_windows, step_size)ejecuta walk-forward sobre todas las series en paralelo. loss=MQLoss(quantiles=[0.1, 0.5, 0.9])produce predicciones cuantílicas directamente.
Patrón mínimo
from neuralforecast import NeuralForecast
from neuralforecast.models import NHITS
from neuralforecast.losses.pytorch import MQLoss
# df: columnas unique_id, ds, y (long format)
horizon = 14
models = [
NHITS(
h=horizon,
input_size=2 * horizon,
loss=MQLoss(quantiles=[0.1, 0.5, 0.9]),
max_steps=500,
random_seed=0,
)
]
nf = NeuralForecast(models=models, freq="D")
nf.fit(df)
fcst = nf.predict() # incluye columnas NHITS-q-10, NHITS-q-50, NHITS-q-90
cv = nf.cross_validation(df, n_windows=4, step_size=horizon)Trampas habituales
input_sizemal dimensionado. Siinput_sizees menor que la estacionalidad principal, el modelo no la captará. Una heurística sólida esinput_size >= 2 * estacionalidad.- Frecuencia inconsistente.
freq="D"exigedsregular diario en todas las series. gaps o duplicados rompen elfitcon mensajes confusos. Prefiltrar conmlforecast’s utilities o pandas (asfreq,dropna) es disciplina mínima. - GPU silenciosa. Sin
accelerator="gpu"entrainer_kwargs, entrena en CPU aunque haya CUDA disponible. Modelos grandes tardan órdenes de magnitud más. - Cross-validation con
step_sizemal elegido. Sistep_size < h, los folds se solapan en el horizonte, está bien si lo entiendes, pero las métricas dejan de ser independientes. - Reproducibilidad. Fija
random_seedpor modelo.neuralforecastno propaga un seed global a todos los componentes automáticamente.
Enlaces
Relacionados en esta página
darts, alternativa con catálogo similar yTimeSeriespropio.sktime, API unificada que también puede orquestar modelos neuronales.
tsfresh
tsfresh es una librería que extrae automáticamente cientos de features estadísticas de cada serie temporal (o de cada ventana) y filtra las relevantes para una variable objetivo mediante tests de hipótesis con corrección por false discovery rate. Su utilidad principal es convertir un problema de series en uno de clasificación o regresión tabular, donde los pipelines clásicos de sklearn / XGBoost se aplican directamente.
No es una librería de forecasting. Es la herramienta cuando lo que necesitas es representación tabular de series para clasificación (anomalía vs normal, fallo vs no fallo, paciente A vs B), regresión sobre features (estimar un parámetro de un proceso a partir de su serie observada) o clustering de series.
Cuándo usarlo
- Clasificación o regresión donde la unidad de entrada es una serie temporal completa o una ventana, no un punto.
- Detección de anomalías reducida a clasificación binaria con features extraídas por ventana.
- Generar features de entrada para un modelo downstream (gradient boosting, red neuronal tabular).
- Feature engineering exploratorio cuando no sabes qué propiedades estadísticas son relevantes para tu problema.
Cuándo NO usarlo
- Forecasting puro.
tsfreshno predice valores futuros, extrae features del pasado. - Series muy largas con poca variación local. Calcular ~750 features sobre series de millones de puntos es prohibitivo en tiempo. Considera muestrear ventanas.
- Cuando el modelo downstream aprende su propia representación. Si vas a entrenar un Transformer sobre la serie cruda, las features de
tsfreshañaden ruido más que valor.
Conceptos clave
- Entrada en formato largo: DataFrame con
id(identifica cada serie / ventana),time,value. Un único DataFrame contiene todas las series. extract_features(df, column_id="id", column_sort="time", column_value="value")produce una matriz tabularid × features.select_features(X, y)aplica tests de hipótesis (Mann-Whitney, Kolmogorov-Smirnov, Kendall, según el tipo de target) con corrección Benjamini-Yekutieli para FDR.- Settings:
ComprehensiveFCParameters()(default, ~750 features),EfficientFCParameters()(~600, sin las más costosas),MinimalFCParameters()(~10, para sanity check rápido). - Paralelización con
n_jobs(multiprocessing local) o víadistributor(Dask).
Patrón mínimo
from tsfresh import extract_features, select_features
from tsfresh.feature_extraction import EfficientFCParameters
from tsfresh.utilities.dataframe_functions import impute
# df_long: columnas id, time, value
X = extract_features(
df_long,
column_id="id", column_sort="time", column_value="value",
default_fc_parameters=EfficientFCParameters(),
n_jobs=4,
)
impute(X) # in-place: NaN -> mediana / extremos finitos
# y: pd.Series con índice = id, target binario o continuo
X_filtered = select_features(X, y)
# Pipeline downstream estándar
from sklearn.ensemble import GradientBoostingClassifier
clf = GradientBoostingClassifier(random_state=0).fit(X_filtered, y)Trampas habituales
- Coste computacional.
ComprehensiveFCParameterssobre miles de series largas puede tardar horas. Empieza conMinimalFCParameters()oEfficientFCParameters()para tener un primer baseline. - NaN en el output. Muchas features generan
NaNoinflegítimamente.impute()es necesario antes de entregar a sklearn. select_featuresrequiere unyclaro. Si tu target es ruidoso o muy desbalanceado, el filtrado pierde sentido. Inspecciona la distribución deyantes.- Data leakage por ventanas mal definidas. Si tus ventanas de entrenamiento incluyen información futura respecto al target (p. ej. extraes features de toda la serie y predices su clase), estás filtrando. Las ventanas deben terminar antes del instante a predecir.
- Compatibilidad de versiones.
tsfreshha cambiado nombres de features entre versiones. Para reproducibilidad, fija versión y guarda la lista de features seleccionadas.
Enlaces
Relacionados en esta página
sktime, incluye un transformadorTSFreshFeatureExtractorpara integrartsfreshen pipelines sktime.