Utilizando datos climáticos para modelos de aprendizaje automático

Usando datos climáticos para modelos de aprendizaje automático

Introducción

El clima es un factor determinante en muchas cosas que suceden en el mundo real. De hecho, es tan importante que suele beneficiar cualquier modelo de pronóstico que lo incorpore utilizando modelos de aprendizaje automático.

Piensa en los siguientes escenarios:

  • Una agencia de transporte público intenta pronosticar retrasos y congestiones en el sistema
  • Un proveedor de energía desea estimar la cantidad de generación de electricidad solar para mañana con el fin de negociar energía
  • Los organizadores de eventos necesitan anticipar la cantidad de asistentes para garantizar que se cumplan los estándares de seguridad
  • Una granja necesita programar las operaciones de cosecha para la próxima semana

Es justo decir que cualquier modelo en los escenarios anteriores que no incluya el clima como factor es inútil o no tan bueno como podría serlo.

Sorprendentemente, aunque hay muchos recursos en línea que se centran en cómo pronosticar el clima en sí, prácticamente no hay nada que muestre cómo obtener y utilizar los datos meteorológicos de manera efectiva como característica, es decir, como entrada para predecir algo más. De eso trata esta publicación.

Resumen

En primer lugar, destacaremos los desafíos asociados con el uso de datos meteorológicos para el modelado, los modelos comúnmente utilizados y los proveedores disponibles. Luego realizaremos un estudio de caso y utilizaremos datos de uno de los proveedores para construir un modelo de aprendizaje automático que pronostique los viajes en taxi en Nueva York.

Al final de esta publicación, habrás aprendido sobre:

  • Desafíos en el uso de datos meteorológicos para el modelado
  • Qué modelos y proveedores meteorológicos existen
  • Los pasos típicos de ETL (extracción, transformación y carga) y creación de características para datos de series temporales
  • Evaluación de la importancia de las características mediante valores SHAP

Este artículo se publicó como parte del Data Science Blogathon.

Desafíos

Clima medido vs. Pronóstico

Para un modelo de ML en producción, necesitamos tanto (1) datos en vivo para producir predicciones en tiempo real como (2) una gran cantidad de datos históricos para entrenar un modelo capaz de hacer eso.

por Hadija en Unsplash

Obviamente, al hacer predicciones en tiempo real, utilizaremos el pronóstico del clima actual como entrada, ya que es la estimación más actualizada de lo que va a suceder en el futuro. Por ejemplo, al predecir cuánta energía solar se generará mañana, la entrada que necesitamos para el modelo es lo que los pronósticos dicen sobre el clima de mañana.

¿Qué pasa con el entrenamiento del modelo?

Si queremos que el modelo funcione bien en el mundo real, los datos de entrenamiento deben reflejar los datos en vivo. Para el entrenamiento del modelo, hay que elegir entre utilizar mediciones históricas o pronósticos históricos. Las mediciones históricas reflejan solo el resultado, es decir, lo que las estaciones meteorológicas registraron. Sin embargo, el modelo en vivo va a utilizar pronósticos, no mediciones, ya que las mediciones aún no están disponibles en el momento en que el modelo hace su predicción.

Si existe la posibilidad de obtener pronósticos históricos, siempre se deben preferir, ya que esto entrena el modelo en las mismas condiciones exactas que están disponibles en el momento de las predicciones en vivo.

por American Public Power Association en Unsplash

Considera este ejemplo: siempre que haya muchas nubes, una granja de energía solar producirá poca electricidad. Un modelo entrenado con mediciones históricas aprenderá que cuando la característica de cobertura de nubes muestra un valor alto, hay un 100% de probabilidad de que no haya mucha electricidad. Por otro lado, un modelo entrenado con pronósticos históricos aprenderá que hay otra dimensión en esto: la distancia de pronóstico. Al hacer predicciones varios días antes, un valor alto de cobertura de nubes es solo una estimación y no significa que el día en cuestión será nublado con certeza. En estos casos, el modelo solo podrá confiar en esta característica hasta cierto punto y considerar otras características también al predecir la generación solar.

Formato

Los datos meteorológicos =/= los datos meteorológicos. Hay muchos factores que descartan un conjunto específico de datos meteorológicos como incluso remotamente útiles. Entre los principales factores se encuentran:

  • Granularidad: ¿hay registros para cada hora, cada 3 horas, diariamente?
  • Variables: ¿incluye la(s) característica(s) que necesito?
  • Resolución espacial: ¿a cuántos km² se refiere un registro?
  • Horizonte: ¿hasta qué punto llega el pronóstico?
  • Actualizaciones del pronóstico: ¿con qué frecuencia se crea un nuevo pronóstico?

Además, la forma o el formato de los datos puede ser complicado de trabajar. Cualquier paso adicional de ETL que necesite crear puede introducir errores y la naturaleza dependiente del tiempo de los datos puede hacer que este trabajo sea bastante frustrante.

Datos en vivo vs. Datos antiguos

Los datos que tienen más de un día, o una semana, a menudo vienen en forma de archivos CSV, servidores FTP, o en el mejor de los casos en un punto de conexión de API separado, pero nuevamente a menudo con campos diferentes que el punto de conexión de pronóstico en vivo. Esto crea el riesgo de datos incompatibles y puede aumentar la complejidad en su ETL.

Costos

Los costos pueden variar extremadamente dependiendo del proveedor y los tipos de datos meteorológicos que se requieran. Por ejemplo, los proveedores pueden cobrar por cada coordenada individual, lo que puede ser un problema cuando se requieren muchas ubicaciones. Obtener pronósticos meteorológicos históricos suele ser bastante difícil y costoso.

Modelos meteorológicos

Los modelos de predicción numérica del tiempo, como se les llama con frecuencia, simulan el comportamiento físico de todos los diferentes aspectos del clima. Hay muchos de ellos, que varían en su formato (ver arriba), las partes del mundo que cubren y su precisión.

Aquí hay una lista rápida de los modelos meteorológicos más utilizados:

  • GFS: modelo estándar más conocido, ampliamente utilizado, global
  • CFS: menos preciso que GFS, para pronósticos climáticos a largo plazo, global
  • ECMWF: modelo más preciso pero costoso, global
  • UM: modelo más preciso para el Reino Unido, disponible globalmente también
  • WRF: código de código abierto para producir pronósticos meteorológicos regionales personalizados
por Brian McGowan en Unsplash

Proveedores

Los proveedores están ahí para llevar los datos de los modelos meteorológicos al usuario final. A menudo, también tienen sus propios modelos de pronóstico patentados además de los modelos meteorológicos estándar. Aquí hay algunos de los conocidos:

  • AccuWeather
  • MetOffice
  • OpenWeatherMap
  • AerisWeather
  • DWD (Alemania)
  • Meteogroup (Reino Unido)

API BlueSky

Para el caso de uso del aprendizaje automático, los proveedores mencionados anteriormente resultan no ofrecer pronósticos históricos o el proceso para obtener y combinar los datos es tanto complicado como costoso. En contraste, blueskyapi.io ofrece una API sencilla que se puede llamar para obtener tanto pronósticos en vivo como históricos en el mismo formato, lo que hace que la canalización de datos sea muy sencilla. Los datos originales provienen de GFS, el modelo meteorológico más utilizado.

Estudio de caso: Viajes en taxi en Nueva York

Imagina que tienes un negocio de taxis en Nueva York y quieres pronosticar la cantidad de viajes en taxi para optimizar la planificación de tu personal y flota. Como tienes acceso a los datos históricos combinados de los taxis de Nueva York, decides utilizarlos y crear un modelo de aprendizaje automático.

por Heather Shevlin en Unsplash

Utilizaremos datos que se pueden descargar del sitio web de Nueva York aquí.

Primero, algunas importaciones:

import pandas as pd
import numpy as np
import holidays
import datetime
import pytz
from dateutil.relativedelta import relativedelta
from matplotlib import pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
import shap
import pyarrow

Preprocesamiento de datos de taxis

timezone = pytz.timezone("US/Eastern")
dates = pd.date_range("2022-04", "2023-03", freq="MS", tz=timezone)

Para obtener nuestro conjunto de datos de taxis, necesitamos recorrer los archivos y crear un dataframe agregado con conteos por hora. Esto llevará aproximadamente 20 segundos en completarse.

aggregated_dfs = []
for date in dates:
    print(date)
    df = pd.read_parquet(
      f"./data/yellow_tripdata_{date.strftime('%Y-%m')}.parquet", 
      engine='pyarrow'
    )
    df["timestamp"] = pd.DatetimeIndex(
      df["tpep_pickup_datetime"], tz=timezone, ambiguous='NaT'
    ).floor("H")
    
    # limpieza de datos, a veces incluye marcas de tiempo incorrectas
    df = df[
        (df.timestamp >= date) & 
        (df.timestamp < date + relativedelta(months=1))
    ]
    aggregated_dfs.append(
      df.groupby(["timestamp"]).agg({"trip_distance": "count"}
    ).reset_index())
df = pd.concat(aggregated_dfs).reset_index(drop=True)
df.columns = ["timestamp", "count"]

Echemos un vistazo a los datos. Los primeros 2 días:

df.head(48).plot("timestamp", "count")

Todo:

fig, ax = plt.subplots()
fig.set_size_inches(20, 8)
ax.plot(df.timestamp, df["count"])
ax.xaxis.set_major_locator(plt.MaxNLocator(10))

Curiosamente, podemos ver que durante algunos momentos festivos la cantidad de viajes en taxi es bastante reducida. Desde una perspectiva de series de tiempo, no hay una tendencia u heteroscedasticidad evidente en los datos.

Ingeniería de características en los datos de taxis

A continuación, agregaremos algunas características típicas utilizadas en la predicción de series de tiempo.

Codificar partes de la marca de tiempo

df["hour"] = df["timestamp"].dt.hour
df["day_of_week"] = df["timestamp"].dt.day_of_week

Codificar días festivos

us_holidays = holidays.UnitedStates()
df["date"] = df["timestamp"].dt.date
df["holiday_today"] = [ind in us_holidays for ind in df.date]
df["holiday_tomorrow"] = [ind + datetime.timedelta(days=1) in us_holidays for ind in df.date]
df["holiday_yesterday"] = [ind - datetime.timedelta(days=1) in us_holidays for ind in df.date]

Datos meteorológicos BlueSky

Ahora llegamos a la parte interesante: los datos meteorológicos. A continuación se muestra una guía sobre cómo utilizar la API de clima BlueSky. Para los usuarios de Python, está disponible a través de pip:

pip install blueskyapi

Sin embargo, también es posible utilizar cURL.

La API básica de BlueSky es gratuita. Se recomienda obtener una clave API a través del sitio web, ya que esto aumentará la cantidad de datos que se pueden obtener de la API.

Con su suscripción paga, puede obtener variables meteorológicas adicionales, actualizaciones de pronóstico más frecuentes, mejor granularidad, etc., pero para el estudio de caso esto no es necesario.

import blueskyapi
client = blueskyapi.Client()  # use la clave API aquí para aumentar el límite de datos

Necesitamos elegir la ubicación, las distancias de pronóstico y las variables meteorológicas de interés. Obtengamos un año completo de pronósticos meteorológicos para que coincida con los datos de los taxis.

# Nueva York
lat = 40.5
lon = 106.0

weather = client.forecast_history(
    lat=lat,
    lon=lon,
    min_forecast_moment="2022-04-01T00:00:00+00:00",
    max_forecast_moment="2023-04-01T00:00:00+00:00",
    forecast_distances=[3,6],  # horas adelante
    columns=[
        'precipitation_rate_at_surface',
        'apparent_temperature_at_2m',
        'temperature_at_2m',
        'total_cloud_cover_at_convective_cloud_layer',
        'wind_speed_gust_at_surface',
        'categorical_rain_at_surface',
        'categorical_snow_at_surface'
    ],
)
weather.iloc[0]

¡Eso es todo lo que teníamos que hacer para obtener los datos climáticos!

Unir Datos

Necesitamos asegurarnos de que los datos climáticos se mapean correctamente a los datos de los taxis. Para eso necesitamos el momento objetivo en el que se hizo el pronóstico del clima. Obtenemos esto agregando el “forecast_moment” + “forecast_distance”:

weather["target_moment"] = weather.forecast_moment + pd.to_timedelta(
    weather.forecast_distance, unit="h"
)

Un problema típico al unir datos es el tipo de datos y la conciencia de la zona horaria de las marcas de tiempo. Vamos a igualar las zonas horarias para asegurarnos de unirlos correctamente.

df["timestamp"] = [timezone.normalize(ts).astimezone(pytz.utc) for ts in df["timestamp"]]
weather["target_moment"] = weather["target_moment"].dt.tz_localize('UTC')

Como último paso, unimos, para cualquier marca de tiempo en los datos de los taxis, el pronóstico del clima más reciente disponible.

d = pd.merge_asof(df, weather, left_on="timestamp", right_on="target_moment", direction="nearest")
d.iloc[0]

¡Nuestro conjunto de datos está completo!

Modelo

Antes de modelar, generalmente tiene sentido verificar algunas cosas más, como si la variable objetivo es estacionaria y si hay alguna falta o anomalía en los datos. Sin embargo, para este artículo, vamos a mantenerlo realmente simple y simplemente ajustar un modelo de random forest sin ajustar con las características que hemos extraído y creado:

d = d[~d.isnull().any(axis=1)].reset_index(drop=True)
X = d[
    [
        "day_of_week", 
        "hour", 
        "holiday_today", 
        "holiday_tomorrow", 
        "holiday_yesterday", 
        "precipitation_rate_at_surface",
        "apparent_temperature_at_2m",
        "temperature_at_2m",
        "total_cloud_cover_at_convective_cloud_layer",
        "wind_speed_gust_at_surface",
        "categorical_rain_at_surface",
        "categorical_snow_at_surface"
    ]
]
y = d["count"]
X_train, X_test, y_train, y_test = train_test_split(
  X, y, test_size=0.33, random_state=42, shuffle=False
)
rf = RandomForestRegressor()
rf.fit(X_train, y_train)
pred_train = rf.predict(X_train)
plt.figure(figsize=(50,8))
plt.plot(y_train)
plt.plot(pred_train)
plt.show()

pred_test = rf.predict(X_test)
plt.figure(figsize=(50,8))
plt.plot(y_test.reset_index(drop=True))
plt.plot(pred_test)
plt.show()

Como era de esperar, se pierde bastante precisión en el conjunto de prueba en comparación con el conjunto de entrenamiento. Esto podría mejorarse, pero en general, las predicciones parecen razonables, aunque a menudo son conservadoras cuando se trata de valores muy altos.

print("MAPE es", round(mean_absolute_percentage_error(y_test,pred_test) * 100, 2), "%")

MAPE es 17.16 %

Modelo Sin Clima

Para confirmar que agregar datos climáticos mejoró el modelo, vamos a compararlo con un modelo de referencia que se ajusta a todo excepto a los datos climáticos:

X = d[
    [
        "day_of_week", 
        "hour", 
        "holiday_today", 
        "holiday_tomorrow", 
        "holiday_yesterday"
    ]
]
y = d["count"] 
X_train, X_test, y_train, y_test = train_test_split(
  X, y, test_size=0.33, random_state=42, shuffle=False
)
rf0 = RandomForestRegressor(random_state=42)
rf0.fit(X_train, y_train)
pred_train = rf0.predict(X_train)
pred_test = rf0.predict(X_test)
print("MAPE es", round(mean_absolute_percentage_error(y_test,pred_test) * 100, 2), "%")

MAPE es 17.76 %

Agregar datos meteorológicos mejoró el MAPE de pronóstico de viajes en taxi en un 0.6%. Si bien este porcentaje puede no parecer mucho, según las operaciones de un negocio, esta mejora podría tener un impacto significativo.

Importancia de las características

Además de las métricas, echemos un vistazo a la importancia de las características. Vamos a utilizar el paquete SHAP, que utiliza valores SHAP para explicar la contribución individual y marginal de cada característica al modelo, es decir, verifica cuánto contribuye una característica individual sobre las demás características.

explainer = shap.Explainer(rf)
shap_values = explainer(X_test)

Esto llevará algunos minutos, ya que se ejecutan numerosos escenarios de “qué pasaría si” sobre todas las características: ¿cómo afectaría la precisión general de la predicción si faltara alguna característica?

shap.plots.beeswarm(shap_values)

Podemos ver que las variables explicativas más importantes son la hora del día y el día de la semana. Esto tiene mucho sentido. El número de viajes en taxi varía mucho a lo largo del día y de la semana. Algunos de los datos meteorológicos también resultaron ser útiles. Cuando hace frío, hay más viajes en taxi. Sin embargo, en cierta medida, la temperatura también podría ser un indicador de los efectos generales de la estacionalidad anual en la demanda de taxis. Otra característica importante son las ráfagas de viento, con menos taxis utilizados cuando hay más ráfagas. Una hipótesis aquí podría ser que hay menos tráfico durante el mal tiempo.

Mejoras adicionales en el modelo

  • Considerar la creación de más características a partir de los datos existentes, como retrasar la variable objetivo del día o la semana anterior.
  • El reentrenamiento frecuente del modelo asegurará capturar siempre las tendencias. Esto tendrá un gran impacto al utilizar el modelo en el mundo real.
  • Considerar la adición de más datos externos, como datos de tráfico y congestión en Nueva York.
  • Considerar otros modelos y herramientas de series temporales, como Facebook Prophet.
por Clint Patterson en Unsplash

Conclusión

¡Eso es todo! Has creado un modelo simple que utiliza datos meteorológicos y que se puede utilizar en la práctica.

En este artículo se discutió la importancia de los datos meteorológicos en los modelos de pronóstico en diversos sectores, los desafíos asociados con su uso efectivo y los modelos y proveedores de pronóstico meteorológico numérico disponibles, destacando BlueSky API como una forma rentable y eficiente de obtener tanto pronósticos en tiempo real como históricos. A través de un estudio de caso sobre el pronóstico de viajes en taxi en Nueva York, este artículo proporcionó una demostración práctica del uso de datos meteorológicos en el aprendizaje automático, enseñándote todas las habilidades básicas que necesitas para comenzar:

  • Los pasos típicos de ETL y creación de características para datos de series temporales
  • ETL de datos meteorológicos y creación de características mediante BlueSky API
  • Ajuste y evaluación de un modelo de bosques aleatorios simple para series temporales
  • Evaluación de la importancia de las características mediante valores SHAP

Conclusiones clave

  1. Aunque los datos meteorológicos pueden ser extremadamente complejos de integrar en modelos de aprendizaje automático existentes, los servicios modernos de datos meteorológicos como BlueSky API reducen en gran medida la carga de trabajo.
  2. La integración de los datos meteorológicos de BlueSky en el modelo mejoró la precisión predictiva en el estudio de caso de los viajes en taxi en Nueva York, lo que demuestra que el clima juega un papel práctico visible en las operaciones diarias.
  3. Muchos sectores como el comercio minorista, la agricultura, la energía, el transporte, etc., se benefician de manera similar o mayor y, por lo tanto, requieren buenas integraciones de pronóstico del clima para mejorar sus propios pronósticos y mejorar su eficiencia operativa y asignación de recursos.

Preguntas frecuentes

Los medios mostrados en este artículo no son propiedad de Analytics Vidhya y se utilizan a discreción del autor.