正在加载中...

展开本页目录
算法教程NBEATS-N-BEATS

NBEATS-N-BEATS

No.156 · 在线教程

NBEATS-N-BEATS 模块在当前项目中的真实实现,是一个简化版 N-BEATS 风格序列建模器。它支持回归和分类,但并不是论文中那种标准的多步 backcast/forecast basis expansion 结构,而是先将时序窗口展平成向量,再通过若干全连接残差块逐…

NBEATS-N-BEATS

1. 方法概述

NBEATS-N-BEATS 模块在当前项目中的真实实现,是一个简化版 N-BEATS 风格序列建模器。它支持回归和分类,但并不是论文中那种标准的多步 backcast/forecast basis expansion 结构,而是先将时序窗口展平成向量,再通过若干全连接残差块逐步更新残差并累加一个标量 forecast

设按时间顺序排列的样本为

$$ \mathcal{D}=\{(x_t,y_t)\}_{t=1}^{N},\qquad x_t\in\mathbb{R}^{d},\ y_t\in\mathcal{Y} \tag{1} $$

其中 \(x_t\) 为第 \(t\) 个时间步的特征向量,\(y_t\) 为目标变量。该模块默认数据行顺序已经代表时间顺序,并不会单独读取时间列。

2. 数据预处理与序列构造

2.1 特征编码与目标处理

scale_methodstandardminmax,程序会先对特征执行 pd.get_dummies() 编码;若为 none,则只保留数值型特征,非数值特征会被直接删除。

分类任务中,目标列会统一使用 LabelEncoder 编码为整数类别:

$$ \phi:\mathcal{Y}\to \{0,1,\ldots,C-1\} \tag{2} $$

这比有些旧实现更严格,因为即便原始标签本身是数值型,也会重新映射成从 0 开始的连续类别索引,以适配 sparse_categorical_crossentropy

2.2 全量样本缩放

LSTM 模块类似,当前实现会在构造序列之前,对全量样本先拟合缩放器。若采用标准化,则

$$ x_{tj}^{\ast}=\frac{x_{tj}-\mu_j}{\sigma_j} \tag{3} $$

若采用 Min-Max 缩放,则

$$ x_{tj}^{\ast}=\frac{x_{tj}-x_j^{\min}}{x_j^{\max}-x_j^{\min}} \tag{4} $$

回归任务若勾选 scale_target=True,目标列也会做缩放:

$$ y_t^{\ast}=\frac{y_t-\mu_y}{\sigma_y} \tag{5} $$

这里同样需要注意:scale_target 始终使用 StandardScaler,而且是在全量样本上拟合,因此存在一定信息泄漏。

2.3 滑动窗口与 sequence-to-one 目标

设窗口长度为 \(L\),预测步长为 \(H\)。对起点 \(i\),程序先构造多变量输入窗口

$$ \mathbf{X}_i= \begin{bmatrix} x_i^{\ast}\\ x_{i+1}^{\ast}\\ \vdots\\ x_{i+L-1}^{\ast} \end{bmatrix} \in\mathbb{R}^{L\times d'} \tag{6} $$

对应监督目标取为

$$ z_i=y_{i+L+H-1} \tag{7} $$

因此它并不是直接预测长度为 \(H\) 的未来向量,而是一个sequence-to-one 结构,horizon 只是控制“向后偏移多少步取那个单点目标”。

可构造的序列样本数为

$$ M=N'-L-H+1 \tag{8} $$

其中 \(N'\) 为清洗后的样本量。代码要求 \(M\ge 10\)。

2.4 按时间顺序切分训练集与测试集

设测试比例为 \(r_{\mathrm{te}}\),则系统先按时间顺序切分:

$$ M_{\mathrm{train}}=\left\lfloor M(1-r_{\mathrm{te}})\right\rfloor,\qquad M_{\mathrm{test}}=M-M_{\mathrm{train}} \tag{9} $$

如果 \(M_{\mathrm{train}}<2\) 或 \(M_{\mathrm{test}}<1\),程序会直接报错。分类任务还要求训练集中每个类别至少有 2 条序列样本。

3. 简化版 N-BEATS 块结构

3.1 输入展平

虽然原始输入窗口是二维张量 \(\mathbf{X}_i\in\mathbb{R}^{L\times d'}\),但当前实现会先将其展平成长度为 \(p=Ld'\) 的向量:

$$ r^{(0)}=\mathrm{vec}(\mathbf{X}_i)\in\mathbb{R}^{p} \tag{10} $$

因此,后续网络并不是沿时间维逐步递推,而是把整个窗口当成一个普通向量输入全连接块。

3.2 残差块

对任一块 \(k\),程序先经过若干层全连接 ReLU 网络:

$$ h^{(k,\ell)}=\mathrm{ReLU}\!\left(W^{(k,\ell)}h^{(k,\ell-1)}+b^{(k,\ell)}\right) \tag{11} $$

在此基础上,块会输出:

$$ b^{(k)}=W_b^{(k)}h^{(k)}+c_b^{(k)}\in\mathbb{R}^{p} \tag{12} $$

$$ f^{(k)}=W_f^{(k)}h^{(k)}+c_f^{(k)}\in\mathbb{R} \tag{13} $$

其中 \(b^{(k)}\) 对应 backcast,\(f^{(k)}\) 对应标量 forecast。

3.3 残差更新与 forecast 累积

块输出后,残差按

$$ r^{(k)}=r^{(k-1)}-b^{(k)} \tag{14} $$

更新,而最终 forecast 为所有块预测值之和:

$$ \hat y=\sum_{k=1}^{K}f^{(k)} \tag{15} $$

其中 \(K=\text{num\_stacks}\times \text{num\_blocks}\)。

需要强调的是:当前实现没有标准 N-BEATS 论文中的趋势 basis、季节 basis、解释性头或多步 forecast basis expansion,所以更准确地说,这是一个“N-BEATS 风格的全连接残差堆叠网络”。

3.4 分类输出

分类任务中,程序先得到标量 forecast,再接任务输出层:

$$ \hat p= \begin{cases} \sigma(w\hat y+b),& C\le 2\\ \mathrm{softmax}(W\hat y+b),& C>2 \end{cases} \tag{16} $$

这说明分类分支其实是在一个单标量 bottleneck 上做类别判别,而不是常见的多维分类 head。

4. 训练目标、测试监控与后备实现

4.1 TensorFlow 主实现

若环境中安装了 tensorflow 且未强制回退,程序使用 Keras 模型训练。回归任务损失为

$$ \mathcal{L}_{\mathrm{reg}}=\frac{1}{M_{\mathrm{train}}}\sum_{i=1}^{M_{\mathrm{train}}}(z_i-\hat z_i)^2 \tag{17} $$

二分类与多分类分别使用二元交叉熵和稀疏交叉熵。

一个非常重要的实现细节是:主训练阶段把测试集直接作为

$$ \text{validation\_data}=(X_{\mathrm{test}},y_{\mathrm{test}}) \tag{18} $$

传入 model.fit()。如果开启 early_stopping=True,则 EarlyStopping 监控的也是这个测试集的 val_loss。因此,当前代码中的测试集既用于训练过程监控,又用于最终性能评价。

4.2 无 TensorFlow 时的后备路径

若环境中没有 tensorflow,或显式设置 force_fallback=True,则程序退化为:

  • 分类:LogisticRegression
  • 回归:LinearRegression

这意味着正式实验前必须确认 parameters.backendtensorflow 还是 fallback_sklearn。此外,自动导出的 repro_*.py 脚本会默认把 force_fallback 设为 True,因此其复现结果可能与主界面直接运行的 TensorFlow 结果并不一致。

4.3 回归分解表

回归任务会额外生成一个“趋势季节分解”工作表,但它并不是论文式的 N-BEATS 可解释分解,而只是对预测值做滚动均值得到

$$ \text{trend}_i=\mathrm{RollingMean}(\hat y_i) \tag{19} $$

并定义

$$ \text{seasonal}_i=\hat y_i-\text{trend}_i \tag{20} $$

因此该分解更像导出层面的辅助解释,而不是模型内部显式学习出的可解释 basis。

5. 评价指标与输出结果解释

5.1 回归指标

回归任务输出 rmsemaer2

$$ \mathrm{RMSE}=\sqrt{\frac{1}{M_{\mathrm{test}}}\sum_{i=1}^{M_{\mathrm{test}}}(y_i-\hat y_i)^2} \tag{21} $$

$$ \mathrm{MAE}=\frac{1}{M_{\mathrm{test}}}\sum_{i=1}^{M_{\mathrm{test}}}|y_i-\hat y_i| \tag{22} $$

$$ R^2=1-\frac{\sum_{i=1}^{M_{\mathrm{test}}}(y_i-\hat y_i)^2}{\sum_{i=1}^{M_{\mathrm{test}}}(y_i-\bar y)^2} \tag{23} $$

5.2 分类指标

分类任务输出 accuracyf1_macrof1_weighted。准确率定义为

$$ \mathrm{Accuracy}=\frac{1}{M_{\mathrm{test}}}\sum_{i=1}^{M_{\mathrm{test}}}\mathbf{1}(\hat y_i=y_i) \tag{24} $$

5.3 输出结果说明

当前模块导出的 Excel 工作表包括:

  • 原始数据:原始输入数据;
  • 处理后数据:编码/缩放后的逐行特征表,不是三维序列张量;
  • 模型指标:最终指标;
  • 训练历史:loss / val_loss;
  • 预测结果:测试集序列目标位置对应的真实值与预测值;
  • 混淆矩阵:仅分类任务有效;
  • 趋势季节分解:仅回归任务有效的滚动均值分解表;
  • 类别映射:分类标签映射;
  • 参数:模型与训练参数;
  • 图表索引:图表路径索引。

图表方面,回归任务主要生成:

  • loss_curve.png
  • pred_vs_true.png
  • residual_hist.png

分类任务主要生成:

  • loss_curve.png
  • confusion_matrix.png

6. 算法流程

按照当前项目实现,NBEATS-N-BEATS 的计算流程如下:

  1. 读取 Excel/CSV 数据,并由用户选择任务类型、目标列与特征列;
  2. 根据缩放方式决定是保留纯数值特征还是先做 One-Hot 编码;
  3. 在全量样本上执行特征/目标缩放;
  4. window_sizehorizon 构造 sequence-to-one 滑动窗口;
  5. 按时间顺序切分训练集与测试集;
  6. 将每个窗口展平成向量,送入简化版 N-BEATS 全连接残差块网络;
  7. 若启用 TensorFlow 主实现,则在训练时把测试集作为 validation_data,并可选早停;
  8. 若无 TensorFlow,则退化为逻辑回归或线性回归;
  9. 计算分类或回归指标,导出预测结果、分解表、图表、Excel 和复现脚本。

7. 关键参数说明

表 1 关键参数及含义

参数 含义 当前默认值
task 任务类型 regression
target_column 目标列 用户指定
feature_cols 特征列列表 用户勾选
window_size 窗口长度 24
horizon 预测步长 1
num_stacks 堆叠数 2
num_blocks 每堆块数 2
hidden_units 隐藏单元数 256
num_layers 每块隐藏层数 2
dropout Dropout 比例 0.1
learning_rate 学习率 0.001
epochs 最大训练轮数 50
batch_size 批大小 32
test_size 测试集比例 0.2
random_state 随机种子 42
scale_method 特征缩放方式 standard
scale_target 是否标准化回归目标 True
shuffle_train 训练时是否打乱样本 False
early_stopping 是否启用早停 True
patience 早停容忍轮数 10
backend 实际运行后端 tensorflowfallback_sklearn

8. 论文写作模板

8.1 方法描述模板

可在论文“方法部分”中写为:

“本文采用基于 N-BEATS 思想的全连接残差堆叠网络对时序样本进行建模。首先,将原始样本按时间顺序构造为长度为 \(L\) 的输入窗口,并将第 \(H\) 个未来时间步的目标值作为监督信号;其次,将窗口展平为一维向量后输入多个残差预测块,每个块同时输出对输入残差的回代项和对目标的预测项,模型通过逐块更新残差并累加预测值得到最终输出;随后,采用均方误差或交叉熵损失函数并结合 Adam 优化器完成模型训练;最后,在测试集上使用 RMSE、MAE、\(R^2\) 或 Accuracy、F1 等指标评价模型性能。”

8.2 结果解释模板

结果部分可写为:N-BEATS 通过残差块逐层分解历史信息并累积预测结果,若模型在趋势变化区间仍保持较低误差,则说明残差堆叠结构对复杂时间模式具有较好的表达能力。若回归分解表中不同块贡献差异明显,也可辅助解释模型预测来源。

8.3 表格标题模板

表题可写为:N-BEATS 模型预测结果与性能指标汇总表。

8.4 图表题注模板

图注可写为:N-BEATS 模型真实值与预测值对比曲线。

8.5 表格示例

建议列名:时间点、真实值、预测值、残差、RMSE、MAE、\(R^2\) 或分类评价指标。

9. 实现说明与注意事项

  • 当前实现虽然命名为 NBEATS-N-BEATS,但它并不是标准论文版的 interpretable N-BEATS;没有趋势/季节 basis expansion,也不是多步 forecast head。
  • 模型实际上是 sequence-to-onehorizon 只决定预测哪个未来单点,而不是输出长度为 horizon 的向量。
  • 输入窗口在进入模型前会被展平成普通向量,因此该实现更接近“面向时序窗口的全连接残差网络”,而不是原版 N-BEATS 的标准组织方式。
  • 特征和目标缩放都在全量样本上先完成,再做训练/测试切分,因此存在一定信息泄漏。
  • TensorFlow 主实现把测试集直接作为 validation_data 参与训练监控;这会使测试集既承担早停监控又承担最终评估,不适合非常严格的论文实验设计。
  • 若环境中没有 TensorFlow,或者运行复现脚本时默认 force_fallback=True,程序会退化为逻辑回归/线性回归后备模型,因此正式实验前必须核对实际后端。
  • 趋势季节分解 工作表只是对预测值做滚动均值后的导出辅助结果,不能等同于 N-BEATS 内部的可解释趋势/季节块分解。

10. 论文写作建议

论文中建议避免直接把该结果写成“标准 N-BEATS 实验”。更合适的写法是:采用“受 N-BEATS 思想启发的全连接残差时序预测网络”。结果部分可重点展示测试集预测误差、预测对比图和后备实现说明;若正文需要写趋势/季节解释,应明确指出那只是导出层面的滚动分解辅助,而非模型内部 basis 分解结果。

11. 单篇终审补充

11.1 图题与表题对齐建议

  • 原始数据 表可写为:表X N-BEATS 原始数据预览。
  • 处理后数据 表可写为:表X N-BEATS 处理后样本数据。
  • 模型指标 表可写为:表X N-BEATS 测试集性能指标汇总。
  • 训练历史 表可写为:表X N-BEATS 训练过程记录。
  • 预测结果 表可写为:表X N-BEATS 测试样本预测结果。
  • 混淆矩阵 表可写为:表X N-BEATS 分类混淆矩阵或占位结果表。
  • 趋势季节分解 表可写为:表X N-BEATS 导出层趋势季节辅助分解结果。
  • 参数 表可写为:表X N-BEATS 参数设置与运行后端记录。
  • 图表索引 表可写为:表X N-BEATS 图表索引与路径清单。
  • loss_curve.png 建议写为:图X N-BEATS 训练损失曲线。
  • pred_vs_true.png 建议写为:图X N-BEATS 真实值与预测值对比图。
  • residual_hist.png 建议写为:图X N-BEATS 预测残差分布图。

11.2 终审说明

  • 当前代表性结果目录中的真实主工作簿为 nbeats_baseline_run1.xlsx,复现输出为 nbeats_baseline_run1_repro.xlsx。论文若附文件名或结果清单,应把两者区分为“基线导出”和“repro 导出”。
  • 真实图文件位于 nbeats_baseline_run1_plots/ 下,主要包括 loss_curve.pngpred_vs_true.pngresidual_hist.png。当前并没有标准 N-BEATS 可解释 basis 可视化图,正文不能把这些结果写成“趋势块/季节块内部可视化”。
  • 趋势季节分解 工作表只是导出层的辅助分解结果,不等同于原版 N-BEATS 内部趋势-季节 basis 分解。论文中若需要解释该表,应明确其为“后处理辅助分解”,而不是模型内部结构直出。
  • 当前工作簿是否出现 类别映射 取决于任务类型;代表性回归结果目录中并未出现该表,因此正文中不应把 类别映射 写成该算法的固定导出项。
  • 真实 repro 脚本为 repro_NBEATS_N_BEATS_20260320_004306.py,并通过 INPUT_FILE = 'repro_inputs/nbeats_baseline_input.csv' 读取输入副本;附录中的复现实验说明应保持这一相对路径口径。

11.3 全量强化补充

本篇终审补充绑定的真实算法目录为 具体的算法3/深度学习与时序网络/NBEATS-N-BEATS,本次采用的代表性结果目录为 具体的算法3/深度学习与时序网络/NBEATS-N-BEATS/results/NBEATS-N-BEATS分析结果_20260320_004306_enhanced

当前目录中真实存在两份工作簿:

  • nbeats_baseline_run1.xlsx
  • nbeats_baseline_run1_repro.xlsx

两者实测工作表一致,均包含:

  • 原始数据
  • 处理后数据
  • 模型指标
  • 训练历史
  • 预测结果
  • 混淆矩阵
  • 趋势季节分解
  • 参数
  • 图表索引

因此这篇应明确区分主结果与 repro 结果。代表性目录当前对应的是回归口径结果,但仍保留了 混淆矩阵 工作表作为兼容/占位输出,正文不能因此误写成分类主实验。

当前目录中的真实图文件为:

  • nbeats_baseline_run1_plots/loss_curve.png
  • nbeats_baseline_run1_plots/pred_vs_true.png
  • nbeats_baseline_run1_plots/residual_hist.png
  • nbeats_baseline_run1_repro_plots/loss_curve.png
  • nbeats_baseline_run1_repro_plots/pred_vs_true.png
  • nbeats_baseline_run1_repro_plots/residual_hist.png

因此本轮真实图证据就是训练损失曲线、预测对比图和残差直方图三类,不存在原版 N-BEATS basis 可视化图。

复现实物方面,该目录实际包含:

  • 具体的算法3/深度学习与时序网络/NBEATS-N-BEATS/results/NBEATS-N-BEATS分析结果_20260320_004306_enhanced/repro_NBEATS_N_BEATS_20260320_004306.py
  • 具体的算法3/深度学习与时序网络/NBEATS-N-BEATS/results/NBEATS-N-BEATS分析结果_20260320_004306_enhanced/repro_inputs/nbeats_baseline_input.csv

脚本中明确写成 INPUT_FILE = 'repro_inputs/nbeats_baseline_input.csv'OUTPUT_FILE = 'nbeats_baseline_run1_repro.xlsx'。因此这一篇当前的真实复现口径已经是目录内相对路径输入副本。

12. 软件实现核查补充(2026-07)

  • 当前主结果目录应写作 具体的算法3/深度学习与时序网络/NBEATS-N-BEATS/results/NBEATS-N-BEATS分析结果_20260320_004306_enhanced
  • 正文应围绕 原始数据处理后数据模型指标预测结果混淆矩阵趋势季节分解参数图表索引 来写。
  • 图证应对应 loss_curve.pngpred_vs_true.pngresidual_hist.png,并把主结果与 repro 再生产物区分开。
  • 复现脚本应按 repro_NBEATS_N_BEATS_20260320_004306.py + repro_inputs/nbeats_baseline_input.csv 的口径说明。