Возобновляемая Энергия: Прогнозирование Солнечной Энергии
Обучение будет проводиться на 90% данных, оставляя последние 10% для оценки.
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
import numpy as np
from neuralprophet import NeuralProphet, set_log_level
set_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")
forecast = m.predict(df_test)
m = m.highlight_nth_step_ahead_of_each_forecast(1)
m.plot(forecast)
m.plot(forecast[-48:])
Прогноз на 1 шаг вперед с авторегрессией
Во втором разделе мы будем обучать прогнозиста на один шаг опережать данные о солнечном излучении (которые могут служить показателем производства солнечной фотоэлектрической энергии). Мы можем обучить этого прогнозиста, учитывая предыдущие 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")
forecast = m.predict(df_test)
m = m.highlight_nth_step_ahead_of_each_forecast(1)
m.plot(forecast)
m.plot_components(forecast)
m.plot_parameters()
m.plot(forecast[-48:])
Разрежение коэффициентов AR
Установив 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")