长周期预测具有挑战性,因为预测结果具有波动性计算复杂。为了解决这个问题,我们创建了用于时间序列的神经层级插值(NHITS)。NHITS 基于 NBEATS 构建,并通过层级插值和多速率输入处理将其部分输出专注于时间序列的不同频率。在长周期预测任务中,NHITS 在获得 AAAI 最佳论文奖的 Informer 模型基础上将准确率提高了 25%,同时速度快了 50 倍。

该模型由多个带有 ReLU 非线性的 MLP 组成。块通过双残差堆叠原理连接,使用第 l 个块的后向预测 y~tL:t,l\mathbf{\tilde{y}}_{t-L:t,l} 和前向预测 y^t+1:t+H,l\mathbf{\hat{y}}_{t+1:t+H,l} 输出。多速率输入池化、层级插值和后向残差连接共同促使加法预测在不同信号频段中实现专门化,从而减少内存占用和计算时间,进而提高了架构的简洁性和准确性。

参考文献
-Boris N. Oreshkin, Dmitri Carpov, Nicolas Chapados, Yoshua Bengio (2019). “N-BEATS:用于可解释时间序列预测的神经基扩展分析”。
-Cristian Challu, Kin G. Olivares, Boris N. Oreshkin, Federico Garza, Max Mergenthaler-Canseco, Artur Dubrawski (2023). “NHITS:用于时间序列预测的神经层级插值”。已被第三十七届 AAAI 人工智能大会接受。
-Zhou, H.; Zhang, S.; Peng, J.; Zhang, S.; Li, J.; Xiong, H.; and Zhang, W. (2020). “Informer:超越高效 Transformer 的长序列时间序列预测”。2021 年人工智能促进协会大会 (AAAI 2021)。


来源

NHITS

 NHITS (h, input_size, futr_exog_list=None, hist_exog_list=None,
        stat_exog_list=None, exclude_insample_y=False,
        stack_types:list=['identity', 'identity', 'identity'],
        n_blocks:list=[1, 1, 1], mlp_units:list=[[512, 512], [512, 512],
        [512, 512]], n_pool_kernel_size:list=[2, 2, 1],
        n_freq_downsample:list=[4, 2, 1], pooling_mode:str='MaxPool1d',
        interpolation_mode:str='linear', dropout_prob_theta=0.0,
        activation='ReLU', loss=MAE(), valid_loss=None,
        max_steps:int=1000, learning_rate:float=0.001,
        num_lr_decays:int=3, early_stop_patience_steps:int=-1,
        val_check_steps:int=100, batch_size:int=32,
        valid_batch_size:Optional[int]=None, windows_batch_size:int=1024,
        inference_windows_batch_size:int=-1, start_padding_enabled=False,
        step_size:int=1, scaler_type:str='identity', random_seed:int=1,
        drop_last_loader=False, alias:Optional[str]=None, optimizer=None,
        optimizer_kwargs=None, lr_scheduler=None,
        lr_scheduler_kwargs=None, dataloader_kwargs=None,
        **trainer_kwargs)

*NHITS

时间序列神经层级插值 (NHITS) 是一种基于 MLP 的深度神经网络架构,具有前向和后向残差连接。NHITS 通过层级插值和池化将其序列预测局部专门化到信号频率,从而解决了波动性和内存复杂性挑战。

参数
h: int,预测范围。
input_size: int,自回归输入大小,y=[1,2,3,4] input_size=2 -> y_[t-2:t]=[1,2]。
futr_exog_list: str list,未来外部变量列。
hist_exog_list: str list,历史外部变量列。
stat_exog_list: str list,静态外部变量列。
exclude_insample_y: bool=False,如果为 True,模型会跳过自回归特征 y[t-input_size:t]。
stack_types: List[str],堆栈列表形式为 N * ['identity'],将弃用并改用 n_stacks。请注意 len(stack_types)=len(n_freq_downsample)=len(n_pool_kernel_size)。
n_blocks: List[int],每个堆栈的块数。请注意 len(n_blocks) = len(stack_types)。
mlp_units: List[List[int]],每种堆栈类型的隐藏层结构。每个内部列表应包含每个隐藏层的单元数。请注意 len(n_hidden) = len(stack_types)。
n_pool_kernel_size: List[int],用于计算最大值/平均值的窗口大小列表。请注意 len(stack_types)=len(n_freq_downsample)=len(n_pool_kernel_size)。
n_freq_downsample: List[int],包含堆栈系数(逆表达比率)的列表。请注意 len(stack_types)=len(n_freq_downsample)=len(n_pool_kernel_size)。
pooling_mode: str,输入池化模块,可选 ['MaxPool1d', 'AvgPool1d']。
interpolation_mode: str='linear',插值基,可选 ['linear', 'nearest', 'cubic']。
dropout_prob_theta: float,介于 (0, 1) 之间的浮点数。用于 NHITS 基的 Dropout。
activation: str,激活函数,可选 ['ReLU', 'Softplus', 'Tanh', 'SELU', 'LeakyReLU', 'PReLU', 'Sigmoid']。
loss: PyTorch 模块,从损失函数集合中实例化的训练损失类。
valid_loss: PyTorch 模块=loss,从损失函数集合中实例化的验证损失类。
max_steps: int=1000,最大训练步数。
learning_rate: float=1e-3,介于 (0, 1) 之间的学习率。
num_lr_decays: int=-1,学习率衰减次数,均匀分布在 max_steps 中。
early_stop_patience_steps: int=-1,早停前等待的验证迭代次数。
val_check_steps: int=100,两次验证损失检查之间的训练步数。
batch_size: int=32,每个批次中不同时间序列的数量。
valid_batch_size: int=None,每个验证和测试批次中不同时间序列的数量,如果为 None,则使用 batch_size。
windows_batch_size: int=1024,每个训练批次中采样的窗口数量,默认为全部。
inference_windows_batch_size: int=-1,每个推理批次中采样的窗口数量,-1 表示全部。
start_padding_enabled: bool=False,如果为 True,模型将在时间序列开头填充零,填充数量等于输入大小。
step_size: int=1,每个时间数据窗口之间的步长。
scaler_type: str='identity',用于时间输入归一化的缩放器类型,参见时间缩放器
random_seed: int,用于 pytorch 初始化器和 numpy 生成器的随机种子。
drop_last_loader: bool=False,如果为 True,TimeSeriesDataLoader 会丢弃最后一个非完整批次。
alias: str,可选,模型的自定义名称。
optimizer: ‘torch.optim.Optimizer’ 的子类,可选,用户指定的优化器代替默认选择 (Adam)。
optimizer_kwargs: dict,可选,用户指定的 optimizer 使用的参数列表。
lr_scheduler: ‘torch.optim.lr_scheduler.LRScheduler’ 的子类,可选,用户指定的 lr_scheduler 代替默认选择 (StepLR)。
lr_scheduler_kwargs: dict,可选,用户指定的 lr_scheduler 使用的参数列表。

dataloader_kwargs: dict,可选,由 TimeSeriesDataLoader 传递给 PyTorch Lightning dataloader 的参数列表。
**trainer_kwargs: int,继承自PyTorch Lightning 的 trainer 的关键字 trainer 参数。

参考文献
-Cristian Challu, Kin G. Olivares, Boris N. Oreshkin, Federico Garza, Max Mergenthaler-Canseco, Artur Dubrawski (2023). “NHITS:用于时间序列预测的神经层级插值”。已被第三十七届 AAAI 人工智能大会接受。*


NHITS.fit

 NHITS.fit (dataset, val_size=0, test_size=0, random_seed=None,
            distributed_config=None)

*拟合。

fit 方法使用初始化参数(learning_ratewindows_batch_size 等)和初始化期间定义的 loss 函数来优化神经网络的权重。在 fit 方法内部,我们使用一个继承了初始化时的 self.trainer_kwargs 的 PyTorch Lightning Trainer 来定制其输入,参见PL 的 trainer 参数

该方法设计为与 SKLearn-like 类兼容,特别是与 StatsForecast 库兼容。

默认情况下,model 不保存训练检查点以保护磁盘内存,要保存检查点,请在 __init__ 中将 enable_checkpointing 设置为 True

参数
dataset: NeuralForecast 的 TimeSeriesDataset,参见文档
val_size: int,时间交叉验证的验证集大小。
random_seed: int=None,用于 pytorch 初始化器和 numpy 生成器的随机种子,覆盖 model.__init__ 中的设置。
test_size: int,时间交叉验证的测试集大小。
*


NHITS.predict

 NHITS.predict (dataset, test_size=None, step_size=1, random_seed=None,
                quantiles=None, **data_module_kwargs)

*预测。

使用 PL 的 Trainer 执行 predict_step 进行神经网络预测。

参数
dataset: NeuralForecast 的 TimeSeriesDataset,参见文档
test_size: int=None,时间交叉验证的测试集大小。
step_size: int=1,每个窗口之间的步长。
random_seed: int=None,用于 pytorch 初始化器和 numpy 生成器的随机种子,覆盖 model.__init__ 中的设置。
quantiles: list of floats,可选(默认 None),要预测的目标分位数。
**data_module_kwargs: PL 的 TimeSeriesDataModule 参数,参见文档。*

使用示例

import pandas as pd
import matplotlib.pyplot as plt

from neuralforecast import NeuralForecast
from neuralforecast.models import NHITS
from neuralforecast.losses.pytorch import DistributionLoss
from neuralforecast.utils import AirPassengersPanel, AirPassengersStatic

Y_train_df = AirPassengersPanel[AirPassengersPanel.ds<AirPassengersPanel['ds'].values[-12]].reset_index(drop=True) # 132 train
Y_test_df = AirPassengersPanel[AirPassengersPanel.ds>=AirPassengersPanel['ds'].values[-12]].reset_index(drop=True) # 12 test

model = NHITS(h=12,
              input_size=24,
              loss=DistributionLoss(distribution='StudentT', level=[80, 90], return_params=True),
              stat_exog_list=['airline1'],
              futr_exog_list=['trend'],
              n_freq_downsample=[2, 1, 1],
              scaler_type='robust',
              max_steps=200,
              early_stop_patience_steps=2,
              inference_windows_batch_size=1,
              val_check_steps=10,
              learning_rate=1e-3)

fcst = NeuralForecast(models=[model], freq='ME')
fcst.fit(df=Y_train_df, static_df=AirPassengersStatic, val_size=12)
forecasts = fcst.predict(futr_df=Y_test_df)

# Plot quantile predictions
Y_hat_df = forecasts.reset_index(drop=False).drop(columns=['unique_id','ds'])
plot_df = pd.concat([Y_test_df, Y_hat_df], axis=1)
plot_df = pd.concat([Y_train_df, plot_df])

plot_df = plot_df[plot_df.unique_id=='Airline1'].drop('unique_id', axis=1)
plt.plot(plot_df['ds'], plot_df['y'], c='black', label='True')
plt.plot(plot_df['ds'], plot_df['NHITS-median'], c='blue', label='median')
plt.fill_between(x=plot_df['ds'][-12:], 
                 y1=plot_df['NHITS-lo-90'][-12:].values, 
                 y2=plot_df['NHITS-hi-90'][-12:].values,
                 alpha=0.4, label='level 90')
plt.legend()
plt.grid()
plt.plot()