Возобновляемая Энергия: Прогнозирование Солнечной Энергии
Обучение будет проводиться на 90% данных, оставляя последние 10% для оценки.
if"google.colab"instr(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 pdimport numpy as npfrom neuralprophet import NeuralProphet, set_log_levelset_log_level("ERROR")
data_location ="https://raw.githubusercontent.com/ourownstory/neuralprophet-data/main/datasets/"# Загрузка данных о солнечной энергии в Сан-Францискоsf_pv_df = pd.read_csv(data_location +"energy/SF_PV.csv")m =NeuralProphet( yearly_seasonality=3, # Учитывать сезонность с периодом в 3 года weekly_seasonality=False, # Игнорировать недельную сезонность daily_seasonality=8, # Учитывать суточную сезонность с периодом в 8 единиц (часов?) growth="off", # Отключить учет тренда (роста/падения) learning_rate=0.1, # Скорость обучения модели (0.1 - типичное значение))# Разделение данных на обучающую и тестовую выборкиdf_train, df_test = m.split_df(sf_pv_df, freq="H", valid_p=0.10)# Обучение модели с использованием обучающей выборки и валидации на тестовойmetrics = m.fit(df_train, freq="H", validation_df=df_test, progress="bar")
Общий прогноз: только функции, основанные на времени.
В этом первом разделе мы будем обучать модель только с функциями времени, как если бы мы делали это с Facebook Prophet.
С самого начала мы знаем, что интенсивность солнечного света зависит от времени суток и сезона в течение года. Кроме того, известно, что максимальная дневная интенсивность пропорциональна сезону. На данный момент ни Prophet, ни NeuralProphet не могут умножать две сезонности, поэтому пик будет слишком низким летом и может стать отрицательным зимой. Не идеально, но нормально для первой попытки.
m =NeuralProphet( yearly_seasonality=3, # Учитывать сезонность с периодом в 3 года weekly_seasonality=False, # Игнорировать недельную сезонность daily_seasonality=8, # Учитывать суточную сезонность с периодом в 8 единиц (часов?) growth="off", # Отключить учет тренда (роста/падения) learning_rate=0.1, # Скорость обучения модели (0.1 - типичное значение))# Разделение данных на обучающую и тестовую выборкиdf_train, df_test = m.split_df(sf_pv_df, freq="H", valid_p=0.10)# Обучение модели с использованием обучающей выборки и валидации на тестовойmetrics = m.fit(df_train, freq="H", validation_df=df_test, progress="bar")
Во втором разделе мы будем обучать прогнозиста на один шаг опережать данные о солнечном излучении (которые могут служить показателем производства солнечной фотоэлектрической энергии). Мы можем обучить этого прогнозиста, учитывая предыдущие 24 шага и отключив тренд и сезонность.
Параметры, которые мы можем изменить, - это количество лагов и разреженность AR.
m =NeuralProphet( growth="off", # Отключить учет тренда (роста/падения) yearly_seasonality=False, # Игнорировать годовую сезонность weekly_seasonality=False, # Игнорировать недельную сезонность daily_seasonality=False, # Игнорировать суточную сезонность n_lags=3*24, # Количество прошлых наблюдений для прогноза (72 часа) learning_rate=0.01, # Скорость обучения модели (меньше по сравнению с предыдущим примером))# Разделение данных на обучающую и тестовую выборкиdf_train, df_test = m.split_df(sf_pv_df, freq="H", valid_p=0.10)# Обучение модели с использованием обучающей выборки и валидации на тестовойmetrics = m.fit(df_train, freq="H", validation_df=df_test, progress="bar")
Установив ar_reg > 0, мы можем уменьшить количество ненулевых коэффициентов авторегрессии (AR).
m =NeuralProphet( growth="off", # Отключить учет тренда (роста/падения) yearly_seasonality=False, # Игнорировать годовую сезонность weekly_seasonality=False, # Игнорировать недельную сезонность daily_seasonality=False, # Игнорировать суточную сезонность n_lags=3*24, # Количество прошлых наблюдений для прогноза (72 часа) ar_reg=1, # Добавить авторегрессивный компонент (порядка 1) learning_rate=0.01, # Скорость обучения модели (меньше по сравнению с предыдущим примером))# Разделение данных на обучающую и тестовую выборкиdf_train, df_test = m.split_df(sf_pv_df, freq="H", valid_p=0.10)# Обучение модели с использованием обучающей выборки и валидации на тестовойmetrics = m.fit(df_train, freq="H", validation_df=df_test, progress="bar")
metrics.tail(1)
MAE_val
RMSE_val
Loss_val
RegLoss_val
epoch
MAE
RMSE
Loss
RegLoss
108
17.369593
31.082371
0.00119
0.000569
108
30.580618
53.85133
0.002069
0.000569
m = m.highlight_nth_step_ahead_of_each_forecast(1)# Выделить прогнозы на 1 шаг впередm.set_plotting_backend("plotly-static")# Установить библиотеку визуализацииm.plot_parameters()# Построить график параметров модели
Прогноз на 1 шаг вперед с авторегрессией, включая интеграцию
Далее мы добавим разности ряда как лаговую ковариату. Это позволяет расширить модель с AR до ARI, где I обозначает "интегрированный" временной ряд.
df = sf_pv_df.copy(deep=True)# Создать глубокую копию исходных данныхdf["I"]= np.append(0, sf_pv_df["y"].values[1:] - sf_pv_df["y"].values[:-1])# Добавить столбец с разницей между соседними значениямиprint(df.tail(3))# Вывести последние 3 строки измененного dataframe
ds
y
I
8757
2015-12-31 22:00:00
0
0
8758
2015-12-31 23:00:00
0
0
8759
2016-01-01 00:00:00
0
0
m =NeuralProphet( growth="off", # Отключить учет тренда (роста/падения) yearly_seasonality=False, # Игнорировать годовую сезонность weekly_seasonality=False, # Игнорировать недельную сезонность daily_seasonality=False, # Игнорировать суточную сезонность n_lags=3*24, # Количество прошлых наблюдений для прогноза (72 часа) learning_rate=0.01, # Скорость обучения модели (меньше по сравнению с предыдущим примером))# Добавить столбец "I" в качестве запаздывающего регрессораm = m.add_lagged_regressor("I", normalize="standardize")# Разделение данных на обучающую и тестовую выборкиdf_train, df_test = m.split_df(df, freq="H", valid_p=0.10)# Обучение модели с использованием обучающей выборки и валидации на тестовойmetrics = m.fit(df_train, freq="H", validation_df=df_test, progress="bar")
metrics.tail(1)
MAE_val
RMSE_val
Loss_val
RegLoss_val
epoch
MAE
RMSE
Loss
RegLoss
108
17.883141
30.405554
0.000594
0.0
108
29.873787
52.650181
0.001445
0.0
m.set_plotting_backend("plotly-static")# Установить библиотеку визуализацииm = m.highlight_nth_step_ahead_of_each_forecast(1)# Выделить прогнозы на 1 шаг впередm.plot_parameters()# Построить график параметров модели
Прогноз на 1 шаг вперед с AR-Net: использование нейронной сети
Важно учесть следующее: если рассматривать нейронную сеть хотя бы с одним скрытым слоем, скорость обучения играет значительную роль при тренировке нейронной сети.
При достаточно высокой скорости обучения (вероятно, > 0.1) градиент, кажется, исчезает и заставляет выходные данные сети AR стремиться к нулю. Простой способ избежать этой проблемы - установить скорость обучения на достаточно низком уровне, вероятно, около 0.01 до 0.001.
m =NeuralProphet( growth="off", # Отключить учет тренда (роста/падения) yearly_seasonality=False, # Игнорировать годовую сезонность weekly_seasonality=False, # Игнорировать недельную сезонность daily_seasonality=False, # Игнорировать суточную сезонность n_lags=3*24, # Количество прошлых наблюдений для прогноза (72 часа) ar_layers=[32, 32, 32, 32], # Добавить 4 AR слоя с шириной 32 learning_rate=0.003, # Скорость обучения модели (меньше по сравнению с предыдущим примером))# Создать глубокую копию исходных данных и добавить столбец с разницей между соседними значениямиdf = sf_pv_df.copy(deep=True)df["I"]= np.append(0, sf_pv_df["y"].values[1:] - sf_pv_df["y"].values[:-1])# Разделить данные на обучающую и тестовую выборкиdf_train, df_test = m.split_df(df, freq="H", valid_p=0.10)# Добавить столбец "I" в качестве запаздывающего регрессораm = m.add_lagged_regressor("I", normalize="standardize")# Обучить модель с использованием обучающей выборки и валидации на тестовойmetrics = m.fit(df_train, freq="H", validation_df=df_test, progress="bar")