Presentar datos de series temporales en un formato tabular estándar para modelos de aprendizaje automático clásicos y mejorar la precisión con AutoML
Este artículo profundiza en la mejora del proceso de previsión de los niveles diarios de consumo de energía transformando un conjunto de datos de series temporales en un formato tabular utilizando bibliotecas de código abierto. Exploramos la aplicación de un popular modelo de clasificación multiclase y aprovechamos AutoML con Cleanlab Studio para aumentar significativamente nuestra precisión fuera de muestra.
La conclusión clave de este artículo es que podemos utilizar métodos más generales para modelar un conjunto de datos de series de tiempo convirtiéndolo a una estructura tabular, e incluso encontrar mejoras al intentar predecir estos datos de series de tiempo.
A un alto nivel:
- Establezca una precisión de referencia ajustando un modelo de pronóstico de Prophet a nuestros datos de series de tiempo
- Convierta nuestros datos de series de tiempo a un formato tabular mediante el uso de bibliotecas de características de código abierto y luego demostrará que puede superar a nuestro modelo Prophet con un enfoque estándar de clasificación multiclase (Gradient Boosting) mediante un Reducción del 67% en el error de predicción (aumento de un 38 % de puntos porcentuales brutos en la precisión fuera de la muestra).
- Utilice una solución de AutoML para la clasificación multiclase resultó en una reducción del 42% en el error de predicción (aumento del 8% en puntos porcentuales brutos en precisión fuera de muestra) en comparación con nuestro modelo de aumento de gradiente y resultó en una reducción del 81% en el error de predicción (aumento del 46 % en puntos porcentuales brutos en la precisión fuera de la muestra) en comparación con nuestro modelo de pronóstico Prophet.
Para ejecutar el código demostrado en este artículo, aquí está el cuaderno completo.
Puedes descargar el conjunto de datos. aquí.
Los datos representan el consumo de energía por hora de PJM (en megavatios) por hora. PJM Interconnection LLC (PJM) es una organización de transmisión regional (RTO) en los Estados Unidos. Es parte de la red de Interconexión del Este que opera un sistema de transmisión eléctrica que presta servicio a muchos estados.
Echemos un vistazo a nuestro conjunto de datos. Los datos incluyen una columna de fecha y hora (object
tipo), y el consumo de energía en megavatios (float64
) tipo) columna que intentamos pronosticar como una variable discreta (correspondiente al cuartil de los niveles de consumo de energía por hora). Nuestro objetivo es entrenar un modelo de pronóstico de series de tiempo para poder pronosticar el nivel de consumo de energía diario de mañana en 1 de 4 niveles: low
, below average
, above average
o high
(Estos niveles se determinaron con base en cuartiles de la distribución general del consumo diario). Primero demostramos cómo aplicar métodos de pronóstico de series temporales como Prophet a este problema, pero están restringidos a ciertos tipos de modelos ML adecuados para datos de series temporales. A continuación, demostramos cómo replantear este problema en un problema de clasificación multiclase estándar al que podemos aplicar cualquier modelo de aprendizaje automático, y mostramos cómo podemos obtener pronósticos superiores mediante el uso de un potente aprendizaje automático supervisado.
Primero convertimos estos datos en un consumo de energía promedio a nivel diario y cambiamos el nombre de las columnas al formato que espera el modelo de pronóstico de Prophet. Estos niveles de consumo de energía diario de valor real se convierten en cuartiles, que es el valor que estamos tratando de predecir. Nuestros datos de entrenamiento se muestran a continuación junto con el cuartil en el que se encuentra cada nivel de consumo de energía diario. Los cuartiles se calculan utilizando datos de entrenamiento para evitar la fuga de datos.
Luego mostramos los datos de prueba a continuación, que son los datos con los que estamos evaluando nuestros resultados de pronóstico.
Luego mostramos los datos de prueba a continuación, que son los datos con los que estamos evaluando nuestros resultados de pronóstico.
Como se ve en las imágenes de arriba, usaremos una fecha límite de 2015-04-09
para finalizar el rango de nuestros datos de entrenamiento y comenzar nuestros datos de prueba en 2015-04-10
. Calculamos umbrales de cuartil de nuestro consumo diario de energía utilizando ÚNICAMENTE datos de entrenamiento. Esto evita la fuga de datos: el uso de datos fuera de la muestra que solo estarán disponibles en el futuro.
A continuación, pronosticaremos el nivel de consumo de energía diario de PJME (en MW) durante la duración de nuestros datos de prueba y representaremos los valores pronosticados como una variable discreta. Esta variable representa en qué cuartil cae el nivel de consumo energético diario, representado categóricamente como 1 (low
), 2 (below average
), 3 (above average
), o 4 (high
). Para la evaluación vamos a utilizar el accuracy_score
función de scikit-learn
para evaluar el rendimiento de nuestros modelos. Dado que estamos formulando el problema de esta manera, podemos evaluar los pronósticos del día siguiente de nuestro modelo (y comparar modelos futuros) utilizando la precisión de la clasificación.
import numpy as np
from prophet import Prophet
from sklearn.metrics import accuracy_score# Initialize model and train it on training data
model = Prophet()
model.fit(train_df)
# Create a dataframe for future predictions covering the test period
future = model.make_future_dataframe(periods=len(test_df), freq='D')
forecast = model.predict(future)
# Categorize forecasted daily values into quartiles based on the thresholds
forecast('quartile') = pd.cut(forecast('yhat'), bins = (-np.inf) + list(quartiles) + (np.inf), labels=(1, 2, 3, 4))
# Extract the forecasted quartiles for the test period
forecasted_quartiles = forecast.iloc(-len(test_df):)('quartile').astype(int)
# Categorize actual daily values in the test set into quartiles
test_df('quartile') = pd.cut(test_df('y'), bins=(-np.inf) + list(quartiles) + (np.inf), labels=(1, 2, 3, 4))
actual_test_quartiles = test_df('quartile').astype(int)
# Calculate the evaluation metrics
accuracy = accuracy_score(actual_test_quartiles, forecasted_quartiles)
# Print the evaluation metrics
print(f'Accuracy: {accuracy:.4f}')
>>> 0.4249
La precisión fuera de muestra es bastante pobre: 43%. Al modelar nuestras series de tiempo de esta manera, nos limitamos a utilizar únicamente modelos de pronóstico de series de tiempo (un subconjunto limitado de posibles modelos de ML). En la siguiente sección, consideramos cómo podemos modelar estos datos de manera más flexible transformando la serie temporal en un conjunto de datos tabular estándar mediante la caracterización adecuada. Una vez que la serie temporal se ha transformado en un conjunto de datos tabulares estándar, podemos emplear cualquier modelo de ML supervisado para pronosticar estos datos de consumo de energía diario.
Ahora convertimos los datos de series de tiempo a un formato tabular y presentamos los datos utilizando las bibliotecas de código abierto. sktime
, tsfresh
y tsfel
. Al emplear bibliotecas como estas, podemos extraer una amplia gama de características que capturan patrones y características subyacentes de los datos de series temporales. Esto incluye características estadísticas, temporales y posiblemente espectrales, que proporcionan una instantánea completa del comportamiento de los datos a lo largo del tiempo. Al dividir las series temporales en características individuales, resulta más fácil comprender cómo los diferentes aspectos de los datos influyen en la variable objetivo.
TSFreshFeatureExtractor
es una herramienta de extracción de características del sktime
biblioteca que aprovecha las capacidades de tsfresh
para extraer características relevantes de datos de series temporales. tsfresh
está diseñado para calcular automáticamente una gran cantidad de características de series temporales, lo que puede resultar muy beneficioso para comprender dinámicas temporales complejas. Para nuestro caso de uso, utilizamos el conjunto mínimo y esencial de características de nuestro TSFreshFeatureExtractor
para caracterizar nuestros datos.
tsfel
, o Biblioteca de extracción de características de series temporales, ofrece un conjunto completo de herramientas para extraer características de datos de series temporales. Hacemos uso de una configuración predefinida que permite construir un rico conjunto de características (por ejemplo, estadísticas, temporales, espectrales) a partir de los datos de series temporales de consumo de energía, capturando una amplia gama de características que podrían ser relevantes para nuestra tarea de clasificación.
import tsfel
from sktime.transformations.panel.tsfresh import TSFreshFeatureExtractor# Define tsfresh feature extractor
tsfresh_trafo = TSFreshFeatureExtractor(default_fc_parameters="minimal")
# Transform the training data using the feature extractor
X_train_transformed = tsfresh_trafo.fit_transform(X_train)
# Transform the test data using the same feature extractor
X_test_transformed = tsfresh_trafo.transform(X_test)
# Retrieves a pre-defined feature configuration file to extract all available features
cfg = tsfel.get_features_by_domain()
# Function to compute tsfel features per day
def compute_features(group):
# TSFEL expects a DataFrame with the data in columns, so we transpose the input group
features = tsfel.time_series_features_extractor(cfg, group, fs=1, verbose=0)
return features
# Group by the 'day' level of the index and apply the feature computation
train_features_per_day = X_train.groupby(level='Date').apply(compute_features).reset_index(drop=True)
test_features_per_day = X_test.groupby(level='Date').apply(compute_features).reset_index(drop=True)
# Combine each featurization into a set of combined features for our train/test data
train_combined_df = pd.concat((X_train_transformed, train_features_per_day), axis=1)
test_combined_df = pd.concat((X_test_transformed, test_features_per_day), axis=1)
A continuación, limpiamos nuestro conjunto de datos eliminando las características que mostraron una alta correlación (por encima de 0,8) con nuestra variable objetivo (niveles promedio de consumo de energía diario) y aquellas con correlaciones nulas. Las características de alta correlación pueden conducir a un sobreajuste, donde el modelo funciona bien con datos de entrenamiento pero mal con datos invisibles. Las características con correlación nula, por otro lado, no aportan ningún valor ya que carecen de una relación definible con el objetivo.
Al excluir estas características, nuestro objetivo es mejorar la generalización del modelo y garantizar que nuestras predicciones se basen en un conjunto equilibrado y significativo de entradas de datos.
# Filter out features that are highly correlated with our target variable
column_of_interest = "PJME_MW__mean"
train_corr_matrix = train_combined_df.corr()
train_corr_with_interest = train_corr_matrix(column_of_interest)
null_corrs = pd.Series(train_corr_with_interest.isnull())
false_features = null_corrs(null_corrs).index.tolist()columns_to_exclude = list(set(train_corr_with_interest(abs(train_corr_with_interest) > 0.8).index.tolist() + false_features))
columns_to_exclude.remove(column_of_interest)
# Filtered DataFrame excluding columns with high correlation to the column of interest
X_train_transformed = train_combined_df.drop(columns=columns_to_exclude)
X_test_transformed = test_combined_df.drop(columns=columns_to_exclude)
Si ahora miramos las primeras filas de los datos de entrenamiento, esta es una instantánea de cómo se ve. Ahora tenemos 73 funciones que se agregaron desde las bibliotecas de características de series temporales que utilizamos. La etiqueta que vamos a predecir en base a estas características es el nivel de consumo energético del día siguiente.
Es importante tener en cuenta que utilizamos una práctica recomendada de aplicar el proceso de caracterización por separado para los datos de entrenamiento y de prueba para evitar la fuga de datos (y los datos de prueba retenidos son nuestras observaciones más recientes).
Además, calculamos nuestro valor de cuartil discreto (usando los cuartiles que definimos originalmente) usando el siguiente código para obtener nuestras etiquetas de energía de tren/prueba, que es lo que son nuestras y_labels.
# Define a function to classify each value into a quartile
def classify_into_quartile(value):
if value < quartiles(0):
return 1
elif value < quartiles(1):
return 2
elif value < quartiles(2):
return 3
else:
return 4 y_train = X_train_transformed("PJME_MW__mean").rename("daily_energy_level")
X_train_transformed.drop("PJME_MW__mean", inplace=True, axis=1)
y_test = X_test_transformed("PJME_MW__mean").rename("daily_energy_level")
X_test_transformed.drop("PJME_MW__mean", inplace=True, axis=1)
energy_levels_train = y_train.apply(classify_into_quartile)
energy_levels_test = y_test.apply(classify_into_quartile)
Utilizando nuestro conjunto de datos tabulares destacados, podemos aplicar cualquier modelo de ML supervisado para predecir niveles futuros de consumo de energía. Aquí usaremos un modelo de Clasificador de aumento de gradiente (GBC), el arma elegida por la mayoría de los científicos de datos que operan con datos tabulares.
Nuestro modelo GBC está instanciado a partir del sklearn.ensemble
módulo y configurado con hiperparámetros específicos para optimizar su rendimiento y evitar el sobreajuste.
from sklearn.ensemble import GradientBoostingClassifiergbc = GradientBoostingClassifier(
n_estimators=150,
learning_rate=0.1,
max_depth=4,
min_samples_leaf=20,
max_features='sqrt',
subsample=0.8,
random_state=42
)
gbc.fit(X_train_transformed, energy_levels_train)
y_pred_gbc = gbc.predict(X_test_transformed)
gbc_accuracy = accuracy_score(energy_levels_test, y_pred_gbc)
print(f'Accuracy: {gbc_accuracy:.4f}')
>>> 0.8075
La precisión fuera de muestra del 81% es considerablemente mejor que los resultados de nuestro modelo Prophet anterior.
Ahora que hemos visto cómo caracterizar el problema de las series temporales y los beneficios de aplicar potentes modelos de ML como Gradient Boosting, surge una pregunta natural: ¿Qué modelo de ML supervisado deberíamos aplicar? Por supuesto, podríamos experimentar con muchos modelos, ajustar sus hiperparámetros y ensamblarlos. Una solución más sencilla es dejar que AutoML se encargue de todo esto por nosotros.
Aquí usaremos una solución AutoML simple proporcionada en ai/” rel=”noopener ugc nofollow” target=”_blank”>Estudio Cleanlab, que implica configuración cero. Simplemente proporcionamos nuestro conjunto de datos tabulares y la plataforma entrena automáticamente muchos tipos de modelos de aprendizaje automático supervisados (incluido el aumento de gradiente, entre otros), ajusta sus hiperparámetros y determina qué modelos son mejores para combinar en un único predictor. Aquí está todo el código necesario para entrenar e implementar un clasificador supervisado de AutoML:
from cleanlab_studio import Studiostudio = Studio()
studio.create_project(
dataset_id=energy_forecasting_dataset,
project_name="ENERGY-LEVEL-FORECASTING",
modality="tabular",
task_type="multi-class",
model_type="regular",
label_column="daily_energy_level",
)
model = studio.get_model(energy_forecasting_model)
y_pred_automl = model.predict(test_data, return_pred_proba=True)
A continuación, podemos ver estimaciones de evaluación de modelos en la plataforma AutoML, que muestran todos los diferentes tipos de modelos de ML que se ajustaron y evaluaron automáticamente (incluidos múltiples modelos de aumento de gradiente), así como un predictor de conjunto construido combinando de manera óptima sus predicciones.
Después de realizar inferencias en nuestros datos de prueba para obtener las predicciones del nivel de consumo de energía del día siguiente, vemos que la precisión de la prueba es del 89 %, una mejora bruta del 8 % en puntos porcentuales en comparación con nuestro enfoque anterior de aumento de gradiente.
Para nuestros datos de consumo diario de energía de PJM, descubrimos que transformar los datos a un formato tabular y caracterizarlos logró un Reducción del 67% en el error de predicción (aumento del 38 % en puntos porcentuales brutos en la precisión fuera de la muestra) en comparación con nuestra precisión de referencia establecida con nuestro modelo de pronóstico Prophet.
También probamos un enfoque sencillo de AutoML para la clasificación multiclase, que resultó en una reducción del 42% en el error de predicción (aumento del 8% en puntos porcentuales brutos en precisión fuera de muestra) en comparación con nuestro modelo de aumento de gradiente y resultó en una reducción del 81% en el error de predicción (aumento del 46 % en puntos porcentuales brutos en la precisión fuera de la muestra) en comparación con nuestro modelo de pronóstico Prophet.
Al adoptar enfoques como los ilustrados anteriormente para modelar un conjunto de datos de series temporales más allá del enfoque restringido de considerar únicamente métodos de pronóstico, podemos aplicar técnicas de ML supervisado más generales y lograr mejores resultados para ciertos tipos de problemas de pronóstico.
A menos que se indique lo contrario, todas las imágenes son del autor.