Возобновляемая Энергия: Прогнозирование Солнечной Энергии

Обучение будет проводиться на 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")
metrics.tail(1)
MAE_val
RMSE_val
Loss_val
RegLoss_val
epoch
MAE
RMSE
Loss
RegLoss

108

131.362961

146.889999

0.013868

0.0

108

92.142319

118.028023

0.006694

0.0

forecast = m.predict(sf_pv_df)
m.set_plotting_backend("plotly-static")
m.plot(forecast)
m.plot_parameters()
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")
metrics.tail(1)
MAE_val
RMSE_val
Loss_val
RegLoss_val
epoch
MAE
RMSE
Loss
RegLoss

108

18.209431

30.536762

0.000599

0.0

108

30.15587

52.70145

0.001442

0.0

forecast = m.predict(sf_pv_df)
m.set_plotting_backend("plotly-static")
m.plot(forecast)
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")
metrics.tail(1)
MAE_val
RMSE_val
Loss_val
RegLoss_val
epoch
MAE
RMSE
Loss
RegLoss

108

14.277524

27.617516

0.00049

0.0

108

21.769081

41.479614

0.000905

0.0

m.set_plotting_backend("plotly-static")
m.plot_parameters()
m = m.highlight_nth_step_ahead_of_each_forecast(1)
forecast = m.predict(df_test)
m.plot(forecast)
m.plot_components(forecast)
m.plot(forecast[-48:])

Last updated