Guía completa de ARIMA: Implementación para series temporales

Guía completa de ARIMA: Implementación para series temporales

La predicción de series temporales —el proceso de predecir valores futuros basándose en datos históricos— es un componente fundamental de las operaciones empresariales inteligentes. Para los directores de tecnología y líderes de ingeniería, las capacidades de predicción sólidas son esenciales para optimizar el inventario, gestionar los recursos informáticos, proyectar el rendimiento financiero y detectar anomalías.

Mientras que los modelos de aprendizaje profundo modernos (LSTMs, Transformers) están ganando una atención significativa, los métodos estadísticos clásicos siguen siendo poderosos, interpretables y altamente efectivos, especialmente para series de tiempo unidimensionales. El más destacado de estos es ARIMA, o ARIMA (Promedio Integrado Autorregresivo).

ARIMA es una clase de modelo que captura una variedad de estructuras temporales diferentes en los datos de series temporales. Este artículo proporciona una guía técnica completa y práctica, basada en código, para implementar ARIMA, centrándose en los pasos prácticos, los procedimientos de diagnóstico y las consideraciones arquitectónicas necesarias para una aplicación de nivel empresarial.

Desglosando el modelo ARIMA(p, d, q)

Antes de la implementación, es crucial comprender los tres componentes que definen el modelo, denominados ARIMA(p, d, q):

  • $p$ (AutoRegresivo - AR): Este componente modela la relación entre una observación y un número específico de observaciones rezagadas (es decir, pasos de tiempo anteriores). El parámetro $p$ define cuántos periodos anteriores se utilizan para predecir el valor actual. Un $p$ de 2 significa que el valor actual se predice basándose en los valores de los dos periodos anteriores.
  • $d$ (Integrado - I): Este componente aborda un requisito fundamental para ARIMA: estacionariedad. Una serie temporal estacionaria es aquella cuyos parámetros estadísticos (media, varianza, autocorrelación) son constantes a lo largo del tiempo. Si una serie presenta tendencias (por ejemplo, crecimiento constante), es no estacionaria. El parámetro $d$ representa el número de veces que los datos brutos deben diferenciarse (es decir, restar el valor anterior al valor actual) para lograr la estacionariedad.
  • $q$ (Media Móvil - MA): Este componente modela la relación entre una observación y los errores residuales de un modelo de media móvil aplicado a $q$ observaciones rezagadas.

El objetivo del proceso de implementación es encontrar los valores óptimos para ($p, d, q$) que mejor describan los datos subyacentes.

Servicios de Ingeniería de Productos

Trabaje con nuestros gestores de proyectos, ingenieros de software y testers de control de calidad para desarrollar su nuevo producto de software personalizado o para apoyar su flujo de trabajo actual, siguiendo metodologías Agile, DevOps y Lean.

Build with 4Geeks

El flujo de trabajo de implementación: Un enfoque paso a paso

Utilizaremos Python con la pila estándar de ciencia de datos:pandas para la manipulación de datos, matplotlib para la visualización, statsmodels para las pruebas estadísticas y el modelo principales, y pmdarima para la optimización automática de parámetros.

Primero, asegúrese de que las bibliotecas necesarias estén instaladas:

pip install pandas matplotlib statsmodels pmdarima scikit-learn

Paso 1: Carga y visualización de datos

Supongamos que tenemos un archivo CSV simple (dataset.csv) con datos de ventas mensuales:

читаем
import pandas as pd
import matplotlib.pyplot as plt

# Load and prepare the data
# parse_dates=True and index_col=0 are critical for time-series analysis
data = pd.read_csv('dataset.csv', 
                   parse_dates=['month'], 
                   index_col='month')

# Ensure the index is a DatetimeIndex with a defined frequency
data.index = pd.to_datetime(data.index)
data = data.asfreq('MS') # 'MS' = Month Start frequency

# Visualize the data to identify trends and seasonality
plt.figure(figsize=(12, 6))
plt.plot(data['sales'])
plt.title('Monthly Sales Over Time')
plt.xlabel('Date')
plt.ylabel('Sales')
plt.show()

A partir de este gráfico, inspeccionaríamos visualmente para detectar una tendencia ascendente o descendente (no estacionariedad en la media) o estacionalidad (patrones cíclicos).

Paso 2: Asegurar la estacionariedad (Encontrar $d$)

Los modelos ARIMA requieren datos estacionarios. Utilizamos la prueba de Dickey-Fuller aumentada (ADF) para verificar la estacionariedad.

  • Hipótesis nula ($H_0$): La serie no es estacionaria (tiene una raíz unitaria).
  • Hipótesis alternativa ($H_a$): La serie es estacionaria.

Buscamos un valor p < 0.05valor p < 0.05para rechazar la hipótesis nula y confirmar la estacionariedad.

from statsmodels.tsa.stattools import adfuller

def check_stationarity(timeseries):
    """
    Performs the ADF test and prints the results.
    """
    print('Results of Dickey-Fuller Test:')
    dftest = adfuller(timeseries, autolag='AIC')
    dfoutput = pd.Series(dftest[0:4], 
                         index=['Test Statistic', 'p-value', '#Lags Used', 'Number of Observations'])
    print(dfoutput)
    
    if dftest[1] > 0.05:
        print("\n[!] Series is Non-Stationary (p-value > 0.05). Differencing is required.")
    else:
        print("\n[✓] Series is Stationary (p-value <= 0.05).")

# Check original data
check_stationarity(data['sales'])

Si el valor p es mayor que 0.05, los datos no son estacionarios. Aplicamos la diferenciación (la 'I' en ARIMA) y volvemos a probar. Este proceso nos da nuestro parámetro d.

# Apply first-order differencing (d=1)
sales_diff_1 = data['sales'].diff().dropna()

# Check stationarity again
print("\n--- Checking First-Order Differencing (d=1) ---")
check_stationarity(sales_diff_1)

# If still non-stationary, try second-order differencing (d=2)
# sales_diff_2 = sales_diff_1.diff().dropna()
# check_stationarity(sales_diff_2)

El valor de $d$ es el número de operaciones de diferenciación necesarias para alcanzar la estacionariedad. Para la mayoría de los datos empresariales, $d$ es 1 o 2.

Paso 3: Identificar los parámetros $p$ y $q$

Una vez que tengamos una serie estática (nuestros datos diferenciados), podemos encontrar $p$ y $q$.

Método 1: Inspección manual con gráficos de ACF/PACF

  • Gráfico de la Función de Autocorrelación (ACF): Ayuda a identificar el parámetro $q$. Busque el último pico significativo fuera del intervalo de confianza (área sombreada en azul) antes de un "corte" pronunciado.
  • Gráfico de la Función de Autocorrelación Parcial (PACF): Ayuda a identificar el parámetro $p$. Busque el último pico significativo fuera del intervalo de confianza.
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# Use the stationary data (e.g., sales_diff_1)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))

# ACF plot (for q)
plot_acf(sales_diff_1, ax=ax1, lags=20)

# PACF plot (for p)
plot_pacf(sales_diff_1, ax=ax2, lags=20)

plt.show()

Este método manual es subjetivo y complejo. Una "ruptura" puede ser ambigua.

Método 2: Búsqueda automatizada en la cuadrícula (Recomendado)

Un enfoque más sólido y preferido es utilizar un algoritmo automatizado que itera a través de combinaciones de (p, d, q) y selecciona el mejor modelo en función de un criterio de información, como Criterio de Información de Akaike (AIC)AIC (Criterio de Información de Akaike). La pmdarima proporciona una excelente función auto_arima

Servicios de Ingeniería de Productos

Colabore con nuestros gestores de proyectos, ingenieros de software y probadores de calidad para desarrollar su nuevo producto de software personalizado o para apoyar su flujo de trabajo actual, siguiendo metodologías Agile, DevOps y Lean.

Build with 4Geeks

auto_arimaTambién gestionará la diferencia ($d$) y, además, la estacionalidad (SARIMA) de forma automática.

import pmdarima as pm

# auto_arima will find the best (p, d, q) combination
# We pass the *original* data, not the differenced data
# m=12 indicates a yearly seasonal cycle (12 months)
# 'stepwise=True' speeds up the search
auto_model = pm.auto_arima(data['sales'], 
                           start_p=1, start_q=1,
                           test='adf',       # Use ADF test to find d
                           max_p=3, max_q=3,  # Max p and q
                           m=12,             # Frequency of the series (12 for monthly)
                           d=None,           # Let the test determine d
                           seasonal=True,    # Test for seasonality
                           start_P=0, 
                           D=None,           # Let the test determine D
                           trace=True,       # Print results
                           error_action='ignore',
                           suppress_warnings=True,
                           stepwise=True)

print(auto_model.summary())

El resumen de auto_arima proporcionará los parámetros del modelo más adecuado, como SARIMAX(1, 1, 1)(0, 1, 1, 12), lo que significa:

  • ARIMA (p,d,q):(1, 1, 1)
  • Estacional (P,D,Q)m:(0, 1, 1, 12)

Esto indica un modelo ARIMA(1,1,1) con un componente estacional de (0,1,1) basado en un ciclo de 12 meses. Este modelo combinado es SARIMA, una extensión de ARIMA que maneja explícitamente la estacionalidad.

Paso 4: Validación del modelo y diagnóstico

Ajustar un modelo no es suficiente. Debemos validar que sus supuestos subyacentes sean correctos. Lo hacemos analizando los residuos (la diferencia entre las predicciones del modelo y los valores reales).

Los residuos ideales deberían comportarse comoruido blanco:

  1. Deberían ser independientes (sin patrones).
  2. Deberían tener una media de cero.
  3. Deberían tener una varianza constante.

El auto_arima(o statsmodels) objeto de ajuste proporciona un plot_diagnostics método conveniente.

auto_model.plot_diagnostics(figsize=(15, 12))
plt.show()
  • Esquina superior izquierda (Residuos estandarizados): No debería mostrar ninguna tendencia o patrón obvio.
  • Esquina superior derecha (Histograma más KDE): Debería parecerse estrechamente a una distribución normal (curva en forma de campana), lo que indica que los residuos están distribuidos normalmente alrededor de cero.
  • Esquina inferior izquierda (Gráfico Q-Q): Los puntos deberían estar muy cerca de la línea diagonal roja, confirmando la normalidad.
  • Esquina inferior derecha (Correlograma/ACF): No deberían haber picos significativos después de un retraso de 0. Esto confirma que los residuos están no correlacionados.

Si estos resultados diagnósticos son buenos, el modelo es estadísticamente sólido.

Paso 5: Pruebas retrospectivas (División Entrenamiento/Prueba)

Antes de realizar las predicciones, debemos validar el rendimiento con datos no vistos.

from sklearn.metrics import mean_squared_error
from numpy import sqrt

# Split data (e.g., 80% train, 20% test)
train_size = int(len(data) * 0.8)
train_data = data.iloc[:train_size]
test_data = data.iloc[train_size:]

# We must re-fit the model *only* on the training data
# We use the parameters found by auto_arima
from statsmodels.tsa.statespace.sarimax import SARIMAX

# Example parameters from auto_arima: SARIMAX(1, 1, 1)(0, 1, 1, 12)
model = SARIMAX(train_data['sales'],
                order=(1, 1, 1),
                seasonal_order=(0, 1, 1, 12))

# Fit the model
model_fit = model.fit(disp=False)

# Make predictions on the test set
start = len(train_data)
end = len(train_data) + len(test_data) - 1
predictions = model_fit.predict(start=start, end=end, dynamic=False)

# Compare predictions to actual test data
plt.figure(figsize=(12, 6))
plt.plot(train_data['sales'], label='Training Data')
plt.plot(test_data['sales'], label='Actual Data (Test)', color='orange')
plt.plot(predictions, label='ARIMA Predictions', color='green', linestyle='--')
plt.legend()
plt.show()

# Calculate RMSE
rmse = sqrt(mean_squared_error(test_data['sales'], predictions))
print(f'Test RMSE: {rmse:.3f}')

Paso 6: Pronóstico final

Una vez validado, ajustamos el modelo en todo el conjunto de datos y lo utilizamos para predecir el futuro.conjunto de datos completo

# Fit the final model on ALL data
final_model = SARIMAX(data['sales'],
                      order=(1, 1, 1),
                      seasonal_order=(0, 1, 1, 12))
final_model_fit = final_model.fit(disp=False)

# Forecast the next 12 periods (months)
n_periods = 12
forecast = final_model_fit.get_forecast(steps=n_periods)

# Get confidence intervals
forecast_ci = forecast.conf_int(alpha=0.05) # 95% confidence

# Plot the forecast
plt.figure(figsize=(14, 7))
plt.plot(data['sales'], label='Historical Data')
plt.plot(forecast.predicted_mean, label='Forecast', color='red')
plt.fill_between(forecast_ci.index,
                 forecast_ci.iloc[:, 0],
                 forecast_ci.iloc[:, 1], color='r', alpha=0.1, label='95% Confidence Interval')
plt.title('Sales Forecast')
plt.legend()
plt.show()

Consideraciones arquitectónicas y de rendimiento

Si bien es potente, ARIMA no es una solución universal.

  • Escalabilidad: ARIMA es univariado. Para predecir 10,000 productos diferentes, debe entrenar 10,000 modelos individuales. Esto puede ser computacionalmente costoso. Los marcos de computación distribuida (como Spark con Pandas UDF) pueden ser necesarios para paralelizar el entrenamiento de modelos.
  • Análisis Multivariado: ARIMA (y SARIMA) no pueden usar de forma nativa regresores externos o series de tiempo relacionadas (por ejemplo, usar el precio de un competidor para predecir sus ventas). Para esto, SARIMAX (que auto_arima a menudo encuentra) o VAR (Vector AutoRegresión) son necesarios.
  • Interpretación frente a Rendimiento: ARIMA es altamente interpretable. Puede especificar con precisión las relaciones estadísticas (por ejemplo, $p=1$ significa que las ventas dependen de las ventas del mes anterior). Los modelos de Deep Learning (LSTMs, etc.) pueden lograr una mayor precisión en datos complejos y no lineales, pero son significativamente menos interpretables ("caja negra").
  • Pila de Datos: Un sistema de predecir de nivel de producción requiere una pila de datos robusta para el re-entrenamiento automatizado. Un modelo entrenado con datos de 2023 se volverá "obsoleto" y funcionará mal con los datos de 2025. Se debe establecer una pila de MLOps para extraer automáticamente nuevos datos, volver a ejecutar auto_arima para comprobar las desviaciones de los parámetros y desplegar el nuevo modelo.

Finalmente

Los modelos ARIMA/SARIMA proporcionan una base sólida y basada en la estadística para la predicción de series temporales. Su fortaleza reside en su capacidad para modelar tendencias y estacionalidad con alta interpretabilidad. Para muchas necesidades empresariales, como la gestión de inventario, las finanzas o la planificación de recursos, un modelo SARIMA bien diagnosticado suele ser suficiente y preferible a soluciones más complejas.

Servicios de Ingeniería de Productos

Colabore con nuestros gestores de proyectos, ingenieros de software y probadores de calidad internos para desarrollar su nuevo producto de software personalizado o para apoyar su flujo de trabajo actual, siguiendo metodologías Agile, DevOps y Lean.

Build with 4Geeks

La clave para una implementación exitosa no es solo adaptar el modelo, sino cumplir rigurosamente con el flujo de trabajo: validar la estacionariedad (d), ajustar los parámetros (p, q, P, Q) de forma sistemática y comprobar exhaustivamente los diagnósticos del modelo.

Si bien esta guía proporciona los elementos básicos, escalar estos métodos en un motor de pronóstico automatizado y fiable en múltiples unidades de negocio es un desafío importante. Aquí es donde los servicios especializados de ingeniería de IA para empresas se vuelven invaluables, traduciendo los modelos estadísticos en plataformas de pronóstico de alta disponibilidad y aptas para producción.

Preguntas frecuentes

¿Qué es un modelo ARIMA y qué significan sus componentes (p, d, q)?

ARIMA, o Media Móvil Integrada Autorregresiva, es una clase de modelos estadísticos utilizados para capturar y predecir estructuras temporales en datos de series temporales. El modelo se define por tres parámetros:  p,  d, y  q.

    p (Autorregresivo): Este componente modela la relación entre una observación actual y un número específico (p) de observaciones anteriores (retrasadas).d (Integrado): Esto representa el número de veces que los datos brutos deben ser "diferenciados" (restando el valor anterior del valor actual) para lograr estacionariedad, un estado en el que las propiedades estadísticas de los datos (como la media y la varianza) son constantes con el tiempo.q (Media Móvil): Este componente modela la relación entre una observación y los errores residuales de un modelo de media móvil basado en  q  observaciones retrasadas, capturando fluctuaciones aleatorias a corto plazo.

¿Qué es la estacionariedad y por qué es esencial para la predicción ARIMA?

Estacionariedad es un requisito fundamental para construir un modelo ARIMA. Una serie temporal se considera estacionaria si sus propiedades estadísticas—como su media, varianza y autocorrelación—son constantes a lo largo del tiempo. No debe mostrar tendencias claras (como un crecimiento constante) ni patrones cíclicos. El componente "Integrado" (d) del ARIMA está específicamente diseñado para abordar la no estacionariedad. Este parámetro indica cuántas operaciones de diferenciación se necesitan para transformar los datos en una serie estacionaria, lo cual es necesario para que funcionen correctamente los componentes AutoRegresivo (p) y Promedio Móvil (q). El Prueba de Dickey-Fuller aumentada (ADF) se utiliza comúnmente para comprobar si una serie es estacionaria.

¿Cuáles son los pasos clave para implementar un modelo de pronóstico ARIMA?

Un flujo de trabajo típico para implementar un modelo ARIMA implica varios pasos clave:

  1. Carga y visualización de datos: Primero, los datos de series temporales se cargan y visualizan para identificar cualquier tendencia, estacionalidad o patrón cíclico obvio.
  2. Asegurar la estacionariedad: Los datos se prueban para verificar la estacionariedad utilizando una prueba estadística como la prueba de Dickey-Fuller (ADF). Si los datos no son estacionarios, se aplica la diferenciación (lo que determina el parámetro d).
  3. Identificar los parámetros (p y q): Una vez que los datos son estacionarios, se identifican los parámetros p (Autoregresivo) y q (Promedio móvil). Esto se puede hacer manualmente inspeccionando los gráficos de autocorrelación (ACF) y autocorrelación parcial (PACF) o, más comúnmente, utilizando un algoritmo automatizado como auto_arima, que encuentra los mejores parámetros según un criterio como AIC.
  4. Validación y diagnóstico del modelo: Después de ajustar el modelo, se analizan sus residuos (los errores). Los residuos deben idealmente comportarse como "ruido blanco"—sin correlación, con una media de cero y una varianza constante.
  5. Pruebas retroactivas y pronóstico: El modelo se valida en un conjunto de datos de prueba sin ver para medir su rendimiento (por ejemplo, utilizando RMSE). Una vez validado, el modelo final se entrena con todo el conjunto de datos y se utiliza para pronosticar valores futuros.