引言

预测不同市场的需求高峰非常有用。在电力市场中,在需求高峰时段消耗电力会因较高的关税而受到惩罚。当个人或公司在电力需求最高时消耗电力时,监管机构称之为巧合高峰 (CP)。

在德克萨斯州电力市场 (ERCOT) 中,高峰是指 ERCOT 电网容量达到最高点时的每月 15 分钟间隔。高峰是由所有消费者对电网的总需求造成的。巧合高峰需求是 ERCOT 用来确定最终电力消费账单的重要因素。ERCOT 记录每个客户在 6 月至 9 月之间的 4 个月内的 CP 需求,并以此调整电价。因此,客户可以通过减少巧合高峰需求来节省电费。

在此示例中,我们将使用历史负荷数据训练 LightGBM 模型,以预测 2022 年 9 月的日内高峰。多重季节性通常存在于低采样电力数据中。需求表现出每日和每周的季节性,在一天的特定时间(例如下午 6:00 对凌晨 3:00)或特定日期(例如周日对周五)存在明显的模式。

首先,我们将加载 ERCOT 历史需求数据,然后使用 MLForecast.cross_validation 方法拟合 LightGBM 模型并预测 9 月份的每日负荷。最后,我们将展示如何使用预测结果来检测巧合高峰。

大纲

  1. 安装库
  2. 加载并探索数据
  3. 拟合 LightGBM 模型并进行预测
  4. 高峰检测

提示

您可以使用 Colab 交互式地运行此 Notebook

我们假设您已经安装了 MLForecast。请查看此指南了解 如何安装 MLForecast 的说明。

使用 pip install mlforecast 安装必要的包。

我们还需要使用 pip install lightgbm 安装 LightGBM

加载数据

MLForecast 的输入始终是采用 长格式 的数据帧,包含三列:unique_iddsy

  • unique_id(字符串、整数或类别)表示序列的标识符。

  • ds(日期时间戳或整数)列应为索引时间的整数或日期时间戳,理想格式为 YYYY-MM-DD(日期)或 YYYY-MM-DD HH:MM:SS(时间戳)。

  • y(数值)表示我们希望预测的度量。我们将重命名

首先,读取 ERCOT 市场 2022 年的历史总需求数据。我们对原始数据(可在此处获取)进行了处理,包括添加因夏令时而缺失的小时、将日期解析为日期时间格式以及筛选出感兴趣的列。

import numpy as np
import pandas as pd
from utilsforecast.plotting import plot_series
# Load data
Y_df = pd.read_csv('https://datasets-nixtla.s3.amazonaws.com/ERCOT-clean.csv', parse_dates=['ds'])
Y_df = Y_df.query("ds >= '2022-01-01' & ds <= '2022-10-01'")
fig = plot_series(Y_df)

我们观察到时间序列表现出季节性模式。此外,时间序列包含 6,552 个观测值,因此有必要使用计算高效的方法在生产环境中部署它们。

拟合 LightGBM 模型并进行预测

导入 MLForecast 类和您需要的模型。

import lightgbm as lgb

from mlforecast import MLForecast
from mlforecast.target_transforms import Differences

首先,实例化模型并定义参数。

提示

在此示例中,我们使用 lgb.LGBMRegressor 模型的默认参数,但您可以更改它们以提高预测性能。

models = [
    lgb.LGBMRegressor(verbosity=-1) # you can include more models here
]

我们通过实例化一个带有以下必需参数的 MLForecast 对象来拟合模型

  • models:一个 sklearn-like(拟合和预测)模型的列表。

  • freq:一个字符串,指示数据的频率。(参见 pandas 可用的频率别名。)

  • target_transforms:在计算特征之前应用于目标的变换。这些变换在预测步骤中会恢复。

  • lags:用作特征的目标滞后值。

# Instantiate MLForecast class as mlf
mlf = MLForecast(
    models=models,
    freq='H', 
    target_transforms=[Differences([24])],
    lags=range(1, 25)
)

提示

在此示例中,我们仅使用差分和滞后值来生成特征。请参阅完整文档以查看所有可用特征。

cross_validation 方法允许用户模拟多个历史预测,通过将 for 循环替换为 fitpredict 方法,极大地简化了流水线。此方法会重新训练模型并预测每个窗口。请参阅此教程,其中包含窗口如何定义的动画演示。

使用 cross_validation 方法生成 9 月份的所有每日预测。要生成每日预测,将预测范围 window_size 设置为 24。在此示例中,我们模拟在 9 月份部署流水线,因此将窗口数设置为 30(每天一个)。最后,窗口之间的步长为 24(等于 window_size)。这确保每天只生成一个预测。

此外,

  • id_col:标识每个时间序列。
  • time_col:标识时间序列的时间列。
  • target_col:标识要建模的列。
crossvalidation_df = mlf.cross_validation(
    df=Y_df,
    h=24,
    n_windows=30,
)
crossvalidation_df.head()
unique_iddscutoffyLGBMRegressor
0ERCOT2022-09-01 00:00:002022-08-31 23:00:0045482.47175745685.265537
1ERCOT2022-09-01 01:00:002022-08-31 23:00:0043602.65804343779.819515
2ERCOT2022-09-01 02:00:002022-08-31 23:00:0042284.81734242672.470923
3ERCOT2022-09-01 03:00:002022-08-31 23:00:0041663.15677142091.768192
4ERCOT2022-09-01 04:00:002022-08-31 23:00:0041710.62190442481.403168

重要提示

使用 cross_validation 时,请确保在所需的时间戳生成预测。检查 cutoff 列,该列指定预测窗口之前的最后一个时间戳。

高峰检测

最后,我们使用 crossvaldation_df 中的预测结果来检测每日小时需求高峰。对于每一天,我们将检测到的高峰设置为最高的预测值。在这种情况下,我们希望预测一个高峰 (npeaks);根据您的设置和目标,此参数可能会改变。例如,高峰数量可以对应电池为降低需求可放电的小时数。

npeaks = 1 # Number of peaks

对于 ERCOT 4CP 检测任务,我们关注的是正确预测最高的月度负荷。接下来,我们筛选出 9 月份小时需求最高的一天并预测该高峰。

crossvalidation_df = crossvalidation_df.reset_index()[['ds','y','LGBMRegressor']]
max_day = crossvalidation_df.iloc[crossvalidation_df['y'].argmax()].ds.day # Day with maximum load
cv_df_day = crossvalidation_df.query('ds.dt.day == @max_day')
max_hour = cv_df_day['y'].argmax()
peaks = cv_df_day['LGBMRegressor'].argsort().iloc[-npeaks:].values # Predicted peaks

在下图中,我们可以看到 LightGBM 模型如何成功检测到 2022 年 9 月的巧合高峰。

import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(10, 5))
ax.axvline(cv_df_day.iloc[max_hour]['ds'], color='black', label='True Peak')
ax.scatter(cv_df_day.iloc[peaks]['ds'], cv_df_day.iloc[peaks]['LGBMRegressor'], color='green', label=f'Predicted Top-{npeaks}')
ax.plot(cv_df_day['ds'], cv_df_day['y'], label='y', color='blue')
ax.plot(cv_df_day['ds'], cv_df_day['LGBMRegressor'], label='Forecast', color='red')
ax.set(xlabel='Time', ylabel='Load (MW)')
ax.grid()
ax.legend()
fig.savefig('../../figs/electricity_peak_forecasting__predicted_peak.png', bbox_inches='tight')
plt.close()

重要提示

在此示例中,我们仅包含 9 月份的数据。然而,MLForecast 和 LightGBM 可以正确预测 2022 年这 4 个月的高峰。您可以通过增加 cross_validationn_windows 参数或过滤 Y_df 数据集来尝试此操作。

下一步

特别是 MLForecast 和 LightGBM 是用于高峰检测的良好基准模型。但是,进一步探索更新的预测算法或进行超参数优化可能会很有用。