import numpy as np
import pandas as pd检测需求高峰
在这个示例中,我们将展示如何在 ERCOT(德克萨斯州)市场上进行电力负荷预测,以检测每日高峰。
介绍
预测不同市场中的峰值是有用的。在电力市场中,在峰值需求时消费电力会受到更高费率的惩罚。当个人或公司在电力需求最高时消费电力时,监管机构将其称为同时峰值(CP)。
在德克萨斯州电力市场(ERCOT)中,峰值是每月15分钟的时间段,在此期间ERCOT电网处于最高容量状态。峰值是由所有消费者对电网的总需求引起的。同时峰值需求是ERCOT用于确定最终电力消费账单的重要因素。ERCOT记录每个客户在6月至9月期间的CP需求,为期4个月,并利用这些数据来调整电价。因此,通过减少同时峰值需求,客户可以节省电费。
在这个示例中,我们将使用历史负载数据训练一个NHITS模型,以预测2022年9月的次日峰值。低采样电力数据中通常存在多重季节性。需求表现出每日和每周的季节性,在特定的时间段例如下午6点与凌晨3点,或者特定的日期例如星期日与星期五之间有明显的模式。
首先,我们将加载ERCOT历史需求数据,然后使用Neuralforecast.cross_validation方法来拟合模型并预测9月份的每日负载。最后,我们展示如何使用预测结果来检测同时峰值。
大纲
- 安装库
- 加载和探索数据
- 拟合NHITS模型并进行预测
- 峰值检测
库
我们假设您已经安装了NeuralForecast。请查看本指南以获取有关如何安装NeuralForecast的说明。
使用pip install neuralforecast安装必要的包。
加载数据
神经预测模型的输入始终是一个长格式的数据框,包含三列:unique_id、ds 和 y:
unique_id(字符串、整数或类别)表示序列的标识符。ds(日期戳或整数)列应该是一个整数索引时间,或者理想上是 YYYY-MM-DD 格式的日期或 YYYY-MM-DD HH:MM:SS 格式的时间戳。y(数值型)表示我们希望预测的测量值。 我们将重命名
首先,下载并读取 ERCOT 市场 2022 年的历史总需求,数据可在这里获取。数据处理包括因夏令时而添加缺失的小时、将日期解析为日期时间格式,以及过滤感兴趣的列。
# 加载数据
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'")Y_df.plot(x='ds', y='y', figsize=(20, 7))
使用NHITS进行拟合和预测
导入 NeuralForecast 类和你需要的模型。
from neuralforecast.core import NeuralForecast
from neuralforecast.auto import AutoNHITS/Users/cchallu/opt/anaconda3/envs/neuralforecast/lib/python3.10/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
首先,实例化模型并定义参数。要实例化AutoNHITS,您需要定义:
h:预测视野loss:训练损失。使用DistributionLoss生成概率预测。默认值:MAE。config:超参数搜索空间。如果为None,则AutoNHITS类将使用预定义的建议超参数空间。num_samples:探索的配置数量。
models = [AutoNHITS(h=24,
config=None, # 使用默认配置
num_samples=10
)
]我们通过实例化一个 NeuralForecast 对象来拟合模型,所需的参数如下:
models:模型列表。从 models 中选择你想要的模型并导入。freq:一个字符串,表示数据的频率。(请参见 pandas 可用的频率。)
# 实例化 StatsForecast 类为 sf
nf = NeuralForecast(
models=models,
freq='H',
)cross_validation 方法允许用户模拟多个历史预测,通过用 fit 和 predict 方法替换 for 循环,从而大大简化管道。此方法重新训练模型并预测每个窗口。请参阅 这个教程 以获取窗口定义的动画演示。
使用 cross_validation 方法生成所有九月份的每日预测。要生成每日预测,请将预测范围 h 设置为 24。在此示例中,我们模拟在九月份部署管道,因此将窗口数量设置为 30(每一天一个窗口)。最后,将窗口之间的步长设置为 24,以便每天仅生成一个预测。
%%capture
crossvalidation_df = nf.cross_validation(
df=Y_df,
step_size=24,
n_windows=30
)crossvalidation_df.head()| unique_id | ds | cutoff | AutoNHITS | y | |
|---|---|---|---|---|---|
| 0 | ERCOT | 2022-09-01 00:00:00 | 2022-08-31 23:00:00 | 46184.621094 | 45482.471757 |
| 1 | ERCOT | 2022-09-01 01:00:00 | 2022-08-31 23:00:00 | 44108.359375 | 43602.658043 |
| 2 | ERCOT | 2022-09-01 02:00:00 | 2022-08-31 23:00:00 | 42990.058594 | 42284.817342 |
| 3 | ERCOT | 2022-09-01 03:00:00 | 2022-08-31 23:00:00 | 42040.902344 | 41663.156771 |
| 4 | ERCOT | 2022-09-01 04:00:00 | 2022-08-31 23:00:00 | 42007.972656 | 41710.621904 |
使用 cross_validation 时,请确保预测是在所需的时间戳上生成的。检查 cutoff 列,该列指定了预测窗口之前的最后时间戳。
峰值检测
最后,我们使用crossvaldation_df中的预测来检测每日的小时需求峰值。对于每一天,我们将检测到的峰值设置为最高预测。在这种情况下,我们想预测一个峰值(npeaks);根据您的设置和目标,该参数可能会有所变化。例如,峰值的数量可以对应于电池可放电以减少需求的小时数。
npeaks = 1 # 峰值数量对于ERCOT 4CP检测任务,我们有兴趣正确预测每月最高负载。接下来,我们筛选出九月份小时需求最高的那一天,并预测峰值。
crossvalidation_df = crossvalidation_df.reset_index()[['ds','y','AutoNHITS']]
max_day = crossvalidation_df.iloc[crossvalidation_df['y'].argmax()].ds.day # 最大负荷日
cv_df_day = crossvalidation_df.query('ds.dt.day == @max_day')
max_hour = cv_df_day['y'].argmax()
peaks = cv_df_day['AutoNHITS'].argsort().iloc[-npeaks:].values # 预测峰值在下面的图中,我们可以看到模型如何正确地检测到2022年9月的重合峰值。
import matplotlib.pyplot as pltplt.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]['AutoNHITS'], 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['AutoNHITS'], label='Forecast', color='red')
plt.xlabel('Time')
plt.ylabel('Load (MW)')
plt.grid()
plt.legend()
在这个例子中,我们只包含了九月份。然而,NHITS能够正确预测2022年四个月的峰值。您可以通过增加cross_validation的nwindows参数或过滤Y_df数据集来尝试这个功能。所有月份的完整运行只需10分钟。
参考文献
Give us a ⭐ on Github