Глобальное локальное моделирование
При использовании одной модели прогнозирования с общими весами на наборе данных, состоящем из множества временных рядов, можно достичь создания так называемой глобальной модели. Она особенно полезна в случаях, когда один временной ряд может не отражать всю динамику временных рядов. Кроме того, глобальные модели обеспечивают лучшую обобщенность и экономию размера модели.
Однако в случаях, когда многие временные ряды имеют только некоторые общие черты поведения, более подходящей может быть модель глобально-локального типа. В такой модели используется одна модель с общими весами для захвата общих поведений по всем временным рядам, в то время как некоторые компоненты моделируются отдельно для каждого временного ряда.
В этом руководстве мы продемонстрируем пример глобального локального моделирования, отдельно моделируя компоненты тренда и сезонности для каждого временного ряда в наборе данных почасовых нагрузок региона ERCOT.
Сначала загружаем данные:
if "google.colab" in str(get_ipython()):
# Удаление предустановленных пакетов из Colab для избежания конфликтов
!pip uninstall -y torch notebook notebook_shim tensorflow tensorflow-datasets prophet torchaudio torchdata torchtext torchvision
!pip install git+https://github.com/ourownstory/neural_prophet.git # может занять некоторое время
#!pip install neuralprophet # намного быстрее, но может не иметь последних обновлений/исправлений ошибок
import pandas as pd
from neuralprophet import NeuralProphet, set_log_level
from neuralprophet import set_random_seed
import numpy as np
set_random_seed(10)
set_log_level("ERROR", "INFO")
data_location = "https://raw.githubusercontent.com/ourownstory/neuralprophet-data/main/datasets/"
df_ercot = pd.read_csv(data_location + "multivariate/load_ercot_regions.csv")
df_ercot.head()
0
2004-01-01 01:00:00
7225.09
877.79
1044.89
745.79
7124.21
1660.45
3639.12
654.61
1
2004-01-01 02:00:00
6994.25
850.75
1032.04
721.34
6854.58
1603.52
3495.16
639.88
2
2004-01-01 03:00:00
6717.42
831.63
1021.10
699.70
6639.48
1527.99
3322.70
623.42
3
2004-01-01 04:00:00
6554.27
823.56
1015.41
691.84
6492.39
1473.89
3201.72
613.49
4
2004-01-01 05:00:00
6511.19
823.38
1009.74
686.76
6452.26
1462.76
3163.74
613.32
Извлекаем названия регионов, которые позже будут использованы при создании модели.
regions = list(df_ercot)[1:]
Глобальные модели можно активировать, когда входные данные df
функции имеют дополнительную колонку «ID», которая идентифицирует различные временные ряды (помимо типичной колонки «ds», содержащей временные метки, и колонки «y», содержащей наблюдаемые значения временного ряда). В нашем примере мы выбираем данные за трехлетний интервал (с 2004 по 2007 год).
df_global = pd.DataFrame()
for col in regions:
aux = df_ercot[["ds", col]].copy(deep=True) # выберите столбец, связанный с регионом
aux = aux.iloc[:26301, :].copy(deep=True) # выберите данные до строки 26301 (временные метки с 2004 по 2007 год)
aux = aux.rename(columns={col: "y"}) # переименуйте столбец данных в 'y', что совместимо с Neural Prophet
aux["ID"] = col
df_global = pd.concat((df_global, aux))
Мы изменим тенденцию для СЕВЕРА и сезонность для ПОБЕРЕЖЬЯ.
df_global["y"] = (
np.where(df_global["ID"] == "COAST", -df_global["y"], df_global["y"]) # если регион COAST, инвертируем значения столбца "y"
+ 2 * df_global.loc[df_global["ID"] == "COAST", "y"].mean() # добавляем удвоенное среднее значение столбца "y" для COAST
)
df_global["y"] = np.where(df_global["ID"] == "NORTH", df_global["y"] + 0.1 * df_global.index, df_global["y"]) # если регион NORTH, добавляем 0.1 * индекс строки к значениям столбца "y"
df_global.loc[df_global["ID"] == "NORTH"].plot() # визуализируем данные для региона NORTH
df_global.loc[df_global["ID"] == "COAST"].plot() # визуализируем данные для региона COAST


Глобальное моделирование
m = NeuralProphet(
trend_global_local="global", # используем глобальную модель для тренда
season_global_local="global", # используем глобальную модель для сезонности
changepoints_range=0.8, # доля данных для поиска точек изменений
epochs=20, # количество эпох обучения
trend_reg=5, # коэффициент регуляризации для тренда
)
m.set_plotting_backend("plotly-static") # устанавливаем бэкенд для визуализации графиков
Когда входными данными для функции split_df
является pd.DataFrame со столбцом ID
, тренировочные и валидационные данные предоставляются в аналогичном формате. Для глобальных моделей входные данные обычно разделяются в соответствии с долей времени, охватывающей все временные ряды (по умолчанию, когда есть более одного ID
и когда local_split=False
). Если пользователь хочет разделить каждый временной ряд локально, параметр local_split
должен быть установлен в значение True. В этом примере мы разделим наши данные на тренировочные и тестовые (с 33% долей тестовой выборки - 2 года на обучение и 1 год на тестирование).
df_train, df_test = m.split_df(df_global, valid_p=0.33, local_split=True) # разделяем данные на тренировочный и тестовый наборы
print(df_train.shape, df_test.shape) # выводим размеры тренировочного и тестового наборов
После создания объекта NeuralProphet
, модель может быть создана путем вызова функции fit
metrics = m.fit(df_train, freq="H") # обучаем модель на тренировочных данных с частотой "H" (час)
Убедитесь, что вы предоставляете данные, идентифицированные с ключами, связанными с соответствующими временными рядами поездов. Таким образом, подходящие параметры нормализации данных используются в процедурах после подгонки (т.е.,predict
, test
).
future = m.make_future_dataframe(df_test, n_historic_predictions=True) # создаем будущие даты на основе тестовых данных
forecast = m.predict(future) # делаем прогноз на будущее
Мы сейчас построим прогнозируемые временные ряды и параметры для:
NORTH: С корректировкой тренда
COAST: С корректировкой сезонности
EAST: Без изменений к оригиналу
North
m.plot(forecast[forecast["ID"] == "NORTH"]) # визуализация прогноза для региона NORTH
m.plot_parameters(df_name="NORTH") # визуализация параметров модели для региона NORTH
South
m.plot(forecast[forecast["ID"] == "COAST"]) # визуализация прогноза для региона COAST
m.plot_parameters(df_name="COAST") # визуализация параметров модели для региона COAST
East
m.plot(forecast[forecast["ID"] == "EAST"]) # визуализация прогноза для региона EAST
m.plot_parameters(df_name="EAST") # визуализация параметров модели для региона EAST
Metrics
test_metrics_global = m.test(df_test) # оценка модели на тестовых данных
test_metrics_global
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Runningstage.testing metric DataLoader 0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Loss_test 0.12341304123401642
MAE_val 0.23543809354305267
RMSE_val 0.26708388328552246
RegLoss_test 0.0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0
0.235438
0.267084
0.123413
0.0
Локальное моделирование тренда и сезонности
Мы повторим вышеописанный процесс, но для локального моделирования тренда и сезонности.
m = NeuralProphet(
trend_global_local="local", # локальный тренд
season_global_local="local", # локальная сезонность
changepoints_range=0.8, # доля периода, в котором могут находиться точки изменения
epochs=20, # количество эпох обучения
trend_reg=5, # параметр регуляризации для тренда
)
m.set_plotting_backend("plotly-static") # выбор бэкэнда для построения графиков
metrics = m.fit(df_train, freq="H") # обучение модели на обучающем наборе данных с частотой "H" (часы)
future = m.make_future_dataframe(df_test, n_historic_predictions=True) # создание фрейма данных для будущих предсказаний на основе тестового набора данных с учетом исторических предсказаний
forecast = m.predict(future) # предсказание на основе будущего фрейма данных
North
m.plot(forecast[forecast["ID"] == "NORTH"]) # построение графика прогноза для региона "NORTH"
m.plot_parameters(df_name="NORTH") # визуализация параметров модели для региона "NORTH"
Coast
m.plot(forecast[forecast["ID"] == "COAST"]) # визуализация прогноза для региона "COAST"
m.plot_parameters(df_name="COAST") # визуализация параметров модели для региона "COAST"
East
m.plot(forecast[forecast["ID"] == "EAST"]) # визуализация прогноза для региона "EAST"
m.plot_parameters(df_name="EAST") # визуализация параметров модели для региона "EAST"
Metric
test_metrics_local = m.test(df_test) # вычисление метрик качества модели на тестовом наборе данных
test_metrics_local # вывод результатов
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Runningstage.testing metric DataLoader 0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Loss_test 0.08480319380760193
MAE_val 0.18777026236057281
RMSE_val 0.220332533121109
RegLoss_test 0.0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0
0.18777
0.220333
0.084803
0.0
Заключение
Сравнивая локально-глобальную модель и глобальную модель, мы достигли более низкой ошибки с локально-глобальной моделью.
Last updated