引言

预测不同市场的峰值非常有用。在电力市场中,在高峰需求时消耗电力会面临更高的费率惩罚。当个人或公司在需求量最大时消耗电力,监管机构称之为同时发生峰值 (CP)。

在德州电力市场 (ERCOT),峰值是指 ERCOT 电网达到最高容量时的每月 15 分钟间隔。该峰值是由所有消费者对电网的总需求引起的。同时发生峰值需求是 ERCOT 用来确定最终电费账单的重要因素。ERCOT 记录每个客户在 6 月至 9 月期间的 4 个月的 CP 需求,并以此调整电价。因此,客户可以通过降低同时发生峰值需求来节省电费。

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

首先,我们将加载 ERCOT 历史需求数据,然后使用 StatsForecast.cross_validation 方法拟合 MSTL 模型并预测 9 月份的每日负荷。最后,我们展示如何使用预测来检测同时发生峰值。

大纲

  1. 安装库
  2. 加载和探索数据
  3. 拟合 MSTL 模型并预测
  4. 峰值检测

提示

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

我们假设您已安装 StatsForecast。请查看此指南了解 如何安装 StatsForecast

使用 pip install statsforecast 安装必要的软件包

加载数据

StatsForecast 的输入始终是 长格式 的数据框,包含三列:unique_iddsy

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

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

  • y(数值)表示我们要预测的测量值。

import numpy as np
import pandas as pd
Y_df = pd.read_csv('https://datasets-nixtla.s3.amazonaws.com/ERCOT-clean.csv', parse_dates=['ds'])

使用 StatsForecast 类中的 plot 方法绘制序列。此方法会打印数据集中最多 8 个随机序列,有助于进行基本 EDA。

注意

StatsForecast.plot 方法默认使用 Plotly 作为引擎。您可以通过设置 engine="matplotlib" 更改为 MatPlotLib。

from statsforecast import StatsForecast
StatsForecast.plot(Y_df)

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

拟合和预测 MSTL 模型

MSTL(基于 LOESS 的多重季节趋势分解)模型使用局部多项式回归 (LOESS) 将时间序列分解为多个季节性。然后,它使用自定义非季节模型预测趋势,并使用 SeasonalNaive 模型预测每个季节性。

提示

在此处查看我们对 MSTL 的详细解释和教程 此处

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

from sklearn.linear_model import LinearRegression
from utilsforecast.feature_engineering import trend

from statsforecast import StatsForecast
from statsforecast.models import MSTL, SklearnModel

首先,实例化模型并定义参数。电力负荷每 24 小时(每小时)和每 24 * 7 小时(每日)呈现季节性。因此,我们将使用 [24, 24 * 7] 作为季节性。请参阅 此链接,了解如何设置季节长度的详细说明。在此示例中,我们将 SklearnModelLinearRegression 模型一起用于趋势分量,但是,可以使用任何 StatsForecast 模型。完整的模型列表可在 此处 找到。

train, _ = trend(Y_df, freq='H')
train.head()
unique_iddsytrend
0ERCOT2021-01-01 00:00:0043719.8496161.0
1ERCOT2021-01-01 01:00:0043321.0503472.0
2ERCOT2021-01-01 02:00:0043063.0670633.0
3ERCOT2021-01-01 03:00:0043090.0592034.0
4ERCOT2021-01-01 04:00:0043486.5900735.0
models = [
    MSTL(
        season_length=[24, 24 * 7], # seasonalities of the time series 
        trend_forecaster=SklearnModel(LinearRegression()) # model used to forecast trend
    )
]

我们通过实例化具有以下必需参数的 StatsForecast 对象来拟合模型

  • models:模型列表。从 模型 中选择您想要的模型并导入它们。

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

# Instantiate StatsForecast class as sf
sf = StatsForecast(
    models=models,
    freq='H', 
)

提示

StatsForecast 还支持此可选参数。

  • n_jobs: n_jobs: int,并行处理中使用的作业数,使用 -1 表示所有核心。(默认值:1)

  • fallback_model:如果模型失败时使用的模型。(默认值:无)

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

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

cv_df = sf.cross_validation(
    df=train,
    h=24,
    step_size=24,
    n_windows=30
  )
cv_df.head()
unique_iddscutoffyMSTL
0ERCOT2022-09-01 00:00:002022-08-31 23:00:0045482.47175747413.944185
1ERCOT2022-09-01 01:00:002022-08-31 23:00:0043602.65804345237.153285
2ERCOT2022-09-01 02:00:002022-08-31 23:00:0042284.81734243816.390019
3ERCOT2022-09-01 03:00:002022-08-31 23:00:0041663.15677142972.956286
4ERCOT2022-09-01 04:00:002022-08-31 23:00:0041710.62190442909.899438

重要

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

峰值检测

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

npeaks = 1 # Number of peaks

对于 ERCOT 4CP 检测任务,我们关注的是正确预测最高的月度负荷。接下来,我们过滤出 9 月份每小时需求最高的日期并预测该峰值。

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

在下图中,我们可以看到 MSTL 模型如何能够正确检测 2022 年 9 月的同时发生峰值。

import matplotlib.pyplot as plt
plt.figure(figsize=(10, 5))
plt.axvline(cv_df_day.iloc[max_hour]['ds'], color='black', label='True Peak')
plt.scatter(cv_df_day.iloc[peaks]['ds'], cv_df_day.iloc[peaks]['MSTL'], color='green', label=f'Predicted Top-{npeaks}')
plt.plot(cv_df_day['ds'], cv_df_day['y'], label='y', color='blue')
plt.plot(cv_df_day['ds'], cv_df_day['MSTL'], label='Forecast', color='red')
plt.xlabel('Time')
plt.ylabel('Load (MW)')
plt.grid()
plt.legend()

重要

在此示例中,我们只包含 9 月份。然而,MSTL 可以正确预测 2022 年所有 4 个月的峰值。您可以通过增加 cross_validationnwindows 参数或过滤 Y_df 数据集来尝试。运行所有月份的总时间仅需 10 分钟。

下一步

StatsForecast,特别是 MSTL,是很好的峰值检测基准模型。然而,探索更深入、更新的预测算法可能会很有用。我们发现 Nixtla 的 NeuralForecast 库中的深度学习模型 N-HiTS 取得了特别好的结果。

在此教程中,了解如何使用我们的深度学习 N-HiTS 模型和 NeuralForecast 库预测 ERCOT 需求峰值 此教程

参考文献