NHiTS 两年前发表——自那时以来在预测社区中获得了显著的关注。
首先,它是一个多功能的模型——接受过去观测值、未来已知输入和静态外生变量。它可以应用于各种预测领域,包括能源需求、零售和金融市场。
它轻量级,但性能高。与典型的依赖“粘贴”隐藏层的 DL 模型不同,该模型利用信号理论概念以最小参数提升性能。
最后,其 多速率信号采样 策略使模型能够捕捉复杂的频率模式——这对于金融预测等领域至关重要。该模型也可用于概率预测。
在本文中,我们将详细介绍 NHiTS,分析其架构,并通过实际案例突出其优势和内部工作原理。
让我们开始吧。
✅ 在我的通讯录 AI 项目文件夹(项目 2)中找到 NHITS 的动手项目,以及其他有趣的项目!别忘了订阅!
新内容: 我还发布了一篇 配套文章 介绍 NHITS 教程!
NHiTS - 前言
NHITS(Neural Hierarchical Interpolation for Time Series Forecasting)是一种将深度学习与信号处理理论相结合的预测模型
NHiTS[1] 基于 NBEATS[2],因此让我们简要回顾 NBEATS(图 1):**
图 1:NBEATS 的顶级架构 (来源)
与 NBEATS 类似,NHiTS 是模块化的,具有 3 个关键组件:
-
块(蓝色)——基本处理单元。
-
堆栈(橙色)——一系列块的集合。
-
最终模型(黄色)——一系列堆栈的集合。
在深入研究 NHiTS 之前,让我们回顾一下使其脱颖而出的特点:
-
多速率数据采样(NHiTS 独有)
-
神经网络基扩展分析(也见于 NBEATS)
-
双重残差堆叠(也见于 NBEATS)
-
分层插值(NHiTS 独有)
让我们一步步回顾:
多速率数据采样
MLPs 在预测中已得到广泛应用,训练后以时间序列作为输入并预测其延续——即预测。
MLP 变体如 TSMixer 和 TTM 已证明非常成功。NHiTS 也使用了 MLPs——但增加了一个额外的调整,以增强性能:
在NBEATS中,每个块按顺序以相同的长度处理输入信号以生成最终预测。然而,NHiTS在每个块中应用不同的采样率,称为多速率采样。
这是通过一个MaxPooling层实现的,每个块具有不同的核大小。因此,每个块都专注于时间序列的不同组成部分。较大的核大小平滑信号并过滤掉高频,使块能够专注于较大尺度的模式。
为了更好地理解这一点,让我们通过一个简单的PyTorch示例来演示,该示例改编自neuralforecast的NHiTS实现:
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(40)
# 1\. Create a 1D input tensor
simulated_data = np.random.randn(100)
input_tensor = torch.tensor(simulated_data).unsqueeze(0)
print(f"Input Tensor shape: {input_tensor.shape}")
# 2\. Apply MaxPool1D with padding, then convert tensors to numpy arrays for plotting
output_tensor_k2 = nn.functional.max_pool1d(input_tensor, kernel_size=2, stride=2, ceil_mode=True)
output_tensor_k4 = nn.functional.max_pool1d(input_tensor, kernel_size=8, stride=8, ceil_mode=True)
input_tensor, output_tensor_k2, output_tensor_k4 = input_tensor.squeeze(0).squeeze(0).numpy(), output_tensor_k2.squeeze(0).squeeze(0).numpy(), output_tensor_k4.squeeze(0).squeeze(0).numpy()
print(f"Output Tensor k=2 shape: {output_tensor_k2.shape}")
print(f"Output Tensor k=4 shape: {output_tensor_k4.shape}")
tensors = [(input_tensor, '#1f77b4', 'Input Data'),
(output_tensor_k2, '#ff7f0e', 'Maxpooling with k=2'),
(output_tensor_k4, '#2ca02c', 'Maxpooling with k=4')]
plt.figure(figsize=(9, 6))
for i, (tensor, color, label) in enumerate(tensors, 1):
plt.subplot(3, 1, i)
plt.plot(tensor, color=color, label=label)
plt.title(label)
plt.xlabel('Index')
plt.ylabel('Value')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
图 2:应用不同 k 核大小的 MaxPooling 到输入信号的效果(图片由作者提供)
-
因此,具有更激进池化的块专注于较高频率,专门从事长期预测。相比之下,具有较小核大小的块学习短期循环模式。默认情况下,NHiTS对第一个块使用 k=2,对最后一个块使用 k=1——尽管这可以根据您的需要进行调整。
-
另一个优点是资源更少。在图 2(底部图形)中,块通过将序列投影到 12 个数据点(从 100 个)来捕捉一般模式——减少了MLPs中的可训练参数。
神经基扩展
这个概念在NBEATS中被使用,并且在这里也得到了应用。
简而言之,NHiTS可以学习多项式函数来模拟非线性行为。
多项式函数可以通过添加更多项到多项式(称为多项式基扩展)来近似任何非线性曲线(在有限区间内)。
例如,在图 3中,一阶多项式 y=ax 无法拟合正弦数据,但九阶多项式却取得了成功:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
x_data = np.linspace(0, 2.5, 50) # x-values from 0 to 2.5
y_data = np.sin(x_data) + np.random.normal(0, 0.1, size=x_data.shape) # sin(x) with random noise
def P9(x):
return x - (x**3)/6 + (x**5)/120 - (x**7)/5040 + (x**9)/362880
plt.figure(figsize=(8, 5), dpi=100)
colors = {
"data": "#1ECBE1",
"linear": "#E11ECB",
"polynomial": "#9370DB"
}
plt.scatter(x_data, y_data, label="Data (sin(x) with noise)", color=colors['data'], s=30, alpha=0.7, )
# Plot the linear function y = 0.7x
x_lin = np.linspace(0, 2.5, 500)
y_lin = 0.7 * x_lin
plt.plot(x_lin, y_lin, label="y = 0.7x", color=colors['linear'], linestyle='--', linewidth=2)
# Plot the 9th degree polynomial approximation of sin(x)
y_P9 = P9(x_lin)
P9_equation = r"$P_9(x) = x - frac{x³}{6} + frac{x⁵}{120} - frac{x⁷}{5040} + frac{x⁹}{362880}$"
plt.plot(x_lin, y_P9, label=P9_equation, color=colors['polynomial'], linestyle='-', linewidth=2)
plt.title("Neural Basis Expansion Demonstration", fontsize=14)
plt.xlabel("x", fontsize=12)
plt.ylabel("y", fontsize=12)
plt.xlim(0, 2.5)
plt.grid(True, which='both', linestyle='--', linewidth=0.5, alpha=0.7)
plt.legend(fontsize=10, shadow=True)
plt.tight_layout()
plt.show()
图 3:使用九阶多项式近似 sin(x)函数(图片由作者提供)
在现实中,多项式的前九阶是通过使用泰勒级数展开来计算的,该展开式近似了[-2.5,2.5]区间内的正弦函数。
关键思想是NHiTS可以使用神经网络多项式基学习非线性周期函数。这些系数通过块内部的MLPs通过反向传播进行学习——因此得名“神经网络”。
⚠️ 注意: 神经基扩展的概念源于Stone-Weierstrass 定理
双重残差堆叠
NHiTS的基本处理单元是块——类似于NBEATS:
图 4:NHiTS 中的基本块架构。MaxPool 层实现了与上一节讨论的多速率采样(来源,作者注释)。
用 H 表示预测范围,L 表示回溯窗口。
每个块接收一个大小为 L 的时间序列,并通过一个 MLP 堆栈(一系列全连接层)传递它。
这些计算的输出是 theta 参数(θ^b 和 θ^f),也称为 扩展系数(前面已讨论)。然后通过 层次插值(稍后解释)进行转换,以产生 回溯 和 预测 信号:
回溯 信号是最佳近似的向量,可以最优地预测 预测 信号
为了提高 神经扩展过程 的有效性,多个块堆叠在一起——形成一个 堆栈(图 5):
图 5:计算流程从右到左 - 基本块(右),块堆栈(中),堆栈堆栈(左)(来源)
只有第一个块接收原始序列输入。下游块接收来自前一个块的回溯信号 x_l+1 ****(其中 l 是块索引,即 l_1 是堆栈中的第一个块):
图 6:块内的操作(作者图片)
在每个堆栈中,回溯和预测信号被组织成 2 个分支。这种拓扑结构称为 双重残差堆栈,可以用以下方程描述:
在每个块中,模型从输入 x_l 中移除了已经很好地近似的那部分回溯信号 x̂_l。换句话说:
每个块中的模型学习最优地近似输入信号的一部分,并将剩余部分发送给下游块进行近似。
由于每个块仅对输入的一部分进行建模,因此最终预测是所有块的所有 预测 ŷ 信号的求和。
最后,堆栈被堆叠(图 5,中间),增加了模型的深度和其学习复杂时间序列的能力。
最后一步是 theta 参数 θ_b 和 θ_f 如何生成回溯和预测信号。θ_b 保持为回溯信号,而 θ_f 通过 层次插值 转换为预测信号。
层次插值
也许 NHiTS 最具创新性的特性是层次插值——这是一种最初用于时间序列预测的技术。
之前,我们讨论了在每个块中对输入进行采样。这里,我们将同样的想法应用于预测。
通常,一个模型的基数与预测长度相匹配。例如,如果一个神经网络预测 7 个数据点(多步),其最终层有 7 个隐藏单元。
图 7:*分层插值。每个堆栈具有不同的表达能力比率(1/r),其中 r > 0。给定预测范围 H,每个堆栈预测(1/r)×H 个数据点。顶层堆栈(堆栈 1)具有较低的比率,专注于低频和重插值。随着堆栈级别的增加,比率增长,将焦点转移到高频(来源)](https://arxiv.org/pdf/2201.12886)
但如果模型预测的数据点少于 7 个呢?作者提出了以下建议:
-
最终估计预测信号的MLP将比预测长度具有更少的参数。
-
用
Θ表示模型的基数。通常,Θ=H(预测范围)。作者提出通过将 H 乘以 1/r 的比率来减少预测的维度性。 -
这被称为表达能力比率——允许模型使用[1/r * H]个参数来输出预测(其中 r>0)
-
但是,我们仍然需要 H 预测。为了恢复到原始预测长度并预测所有 H 个预测点的范围,我们使用线性插值。
-
与多速率采样类似,每个堆栈中的块以不同的频率进行预测。随着信号通过每个堆栈,表达能力比率分层增加——因此术语分层插值(图 7)。
-
最终预测是所有堆栈的分层预测的总和。
✅ 插值是一种估计介于现有已知数据点之间的未知数据点值的技术。
让我们进一步探索 NHiTS 在简单数据集(AirPassengers)上训练的情况。我们将从 3 个堆栈中提取 theta 系数(预测)。
图 8:NHiTS 在 AirPassengers 测试集上的预测(图片由作者提供)。
在这里,NHiTS使用 48 个数据点作为输入来预测下一个 24 个数据点。假设 3 个堆栈具有以下表达能力比率1/r = [1/12, 1/4, 1]
因此,在每个堆栈中,回溯 theta 大小(输入)为 48,而预测大小为 24。然而,总 theta 系数在堆栈之间有所不同。注意以下预测:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/935fb6386b40e187719a228050aacc55.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f3105d09229e8fb7d41b1b221092c9a1.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/077492f33c371c652465e16f1ecaedd2.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4781fbe4e1afd3e16ee23dd72179b7ba.png
图 9: 假设我们有 3 个堆栈 – 每个堆栈有 1 个块,我们分析它们在测试集上的预测。堆栈图表现出与作者在论文中展示的类似的行为(图 7)(作者图片)
每个堆栈都会发生以下情况:
-
堆栈 1: 预测 2 个数据点(1/12×24=2),这些数据点被插值到 24。模型只计算 2 个预测/参数,在反向传播中节省资源,因为它只计算 48+2=50 个参数,而不是像 NBEATS 那样计算 48+24=72 个参数。
-
堆栈 2: 产生 6 个预测(1/4×24=6),插值到 24。
-
堆栈 3: 使用表达性比率为 1,因此预测的数量等于插值预测的数量。
⚠️ 注意: 所有堆栈预测的总和并不完全等于最终的预测(图 9,底部)。NHiTS 将堆栈预测添加到朴素基线(样本训练批次中的最后一个值)。在我们的案例中,它是 337+stack_forecast_lvl_1+stack_forecast_lvl_2+stack_forecast_lvl_3,这与图 8相匹配。
但是,分层插值有什么优势呢?
-
轻量级计算: NHiTS 每个堆栈计算 (1/r)×H 个预测参数,而不是 H。作为最佳实践,只有最后一个堆栈计算完整的预测时间跨度(r=1)。
-
更干净的信号: 每个堆栈专注于不同的频率,使 NHiTS 能够捕捉到短期和长期依赖关系,从而提高性能。
为了验证这一说法,作者在性能和速度方面将 NHiTS 与 NBEATS(不包含上述升级)进行了比较:
图 10: (左) NHITS 与 NBEATS 在大小和速度方面的比较。(右) NHITS 与 NBEATS 在 MAE 和预测时间跨度方面的比较。(来源)
我们注意到以下几点:
-
左侧图示: 随着预测时间跨度的增加,与 NHiTS 相比,NBEATS 需要显著更多的参数和训练时间。
-
右侧图示: 在 NBEATS 中增加预测时间跨度会显著增加 MAE,而 NHiTS 的表现要好得多。
将所有这些放在一起
图 11 展示了 NHiTS 的顶级架构:
图 11: NHITS 的顶级架构 (来源)
NHiTS 与 NBEATS (见图 1) 具有相似的结构,但通过以下 2 个关键特性进行了改进:
-
多速率采样:通过每个块中的 MaxPool 层(蓝色框,图 11)实现。多速率采样也应用于其他类型(例如,如果模型有过去协变量、未来已知输入等)
-
分层插值:每个栈都有一个不同的表达性比率 r,专注于独特的频率。图 11(左)中的栈预测与图 9 中的相似
因此,我们得出结论:
分层插值和多速率采样使 NHITS 能够在每个级别关注不同的频率,减少不必要的参数。最终的预测是所有分层预测的总和——考虑到在傅里叶变换中一个函数由多个频率组成。
假设我们初始化NHiTS,包含 3 个栈 - 每个栈有 1 个块。一个常见的超参数调整策略如下:
图 12:NHITS 的超参数调整策略(来源)
注意池化核大小k(涉及多速率采样)和栈的系数1/r1(分层插值的表达性比率)
通常,这些值在第一个栈中较高,并在后续栈中逐渐降低,最终达到 1。具体来说:
-
第 1 个栈中的块具有大的k和高1/r比率,通过积极的插值产生低频信号。这些块主要学习长期依赖关系
-
相比之下,最终栈中的块具有较小的k和1/r值(通常是 1),生成高频数据点。
根据你的数据集和预测目标,你可以根据需要调整这些参数:
图 13:使用NHiTS进行概率能量需求预测(图片由作者提供)
图 14:使用 Tensorboard 监控 NHITs 的超参数调整(图片由作者提供)
结语
NHiTS是一个前沿的、经过验证的模型,在时间序列预测方面表现出色。
我喜欢NHiTS的地方是,通过在其前辈NBEATS上做几个简单的升级,它就实现了令人印象深刻的成果——同时更加轻量。
时间序列预测中表现优异的深度学习模型的关键不仅仅是堆叠隐藏层。相反,它们以一种尊重时间序列数据独特属性的方式整合统计概念。
如果你对深度学习模型如何整合这些统计原理以增强性能感兴趣,请查看这篇关于深度学习预测模型的全面论文:
感谢阅读!
参考文献
[1] Boris O. 等人. N-BEATS:用于可解释时间序列预测的神经基础扩展分析, ICLR (2020)
[2] Challu 等人. **** _N-HiTS: 用于时间序列预测的神经层次插值 _
438

被折叠的 条评论
为什么被折叠?



