z
z_studio/TEMPO-NPU
模型介绍
文件和版本
Pull Requests
讨论
分析

Melady/TEMPO on Ascend NPU

昇腾 NPU 适配说明:本文档记录 Melady/TEMPO 时序基础模型(Time-series Foundation Model,ICLR 2024)在昇腾 910B NPU 上的部署与验证过程。推理引擎为 torch_npu(TEMPO 时序预测主通路)+ vllm-ascend(底层 GPT2 骨干 文本生成演示),已在单卡 Ascend 910B 上完整跑通零样本预测 / 回测 / 滚动递归 预测 / STL 重建 / GPT2 骨干生成等任务,并完成 CPU fp32 数值对齐验证。

1. 模型简介

TEMPO(Prompt-based Generative Pre-trained Transformer for Time Series Forecasting)1 是 Melady(南加州大学研究团队)开源的 时序基础模型 (Time-series Foundation Model),参数量约 73.2M(fp32 权重约 293 MB)。 与自回归文本 LLM 不同,它以 openai-community/gpt2 的 3 层 GPT2 编码器为骨干, 面向时间序列预测任务:

  • 输入长度为 seq_len=336 的单变量序列,先经 STL 分解(周期可配置,默认 24) 拆分为 trend / seasonal / resid 三个分量;
  • 每个分量依次做 RevIN 实例归一化 → 序列级映射(map_trend / map_season(MLP 336→1344→336)/ map_resid)→ 分 patch(patch_size=16, 共 21 个 patch)→ in_layer_* 投影到 d_model=768 的 token;
  • 注入 可学习 Prompt:30 组 prompt(每组 key[768] + value[3,768]), 按与输入分支的相似度 softmax 加权组合,每个分支前插 3 个 prompt token;
  • 三个分支共享同一个冻结 GPT2 编码器(3 层 / d_model=768 / d_ff=3072, 因果注意力),训练时在 c_attn 上加 LoRA(r=16);
  • 输出:trend + seasonal 分支的 GPT2 输出拼接成 42 个 token,三个输出头 out_layer_{trend,seasonal,noise} 各自投影到 pred_len=96,残差分量另走 频域通路 out_layer_noise_fre(fc_real / fc_imag 两个并行投影),再加上 summary_map 全局偏置,最后经 RevIN 反归一化还原到原始尺度。
任务说明验证状态
forecast对最后 336 点输入做 96 点零样本预测✅ 通过
backtest输入后 96 点为已知真值,回测 MAE / RMSE✅ 通过
recursive滚动窗口递归预测(多段 96 点续推)✅ 通过
reconstructSTL 分解分量统计与单步预测✅ 通过
text_genvllm-ascend 引擎服务 GPT2 骨干做文本生成演示✅ 通过
  • 参数量: 约 73.2M(fp32 权重约 293 MB)
  • 适配状态: SUCCESS
  • 适配时间: 2026-08-19

关于模型重建的说明:官方训练代码仓库(GitHub DC-research/TEMPO)在本环境 无法直接访问,本适配以 HuggingFace 发布权重 TEMPO-80M_v1.pth / TEMPO-80M_v2.pth 的 state_dict 键名与张量形状为权威依据忠实重建网络结构(见 tempo_model.py)。 重建过程中发现并如实记录的要点2:

  1. config.json 中 gpt_layers=6 与实际发布权重不符——权重文件仅含 3 层 GPT2(h.0~h.2,且每层均带 c_attn LoRA),以权重为准取 3 层;
  2. 权重中 mul_season.a/b 为训练期季节加权辅助参数,其与重建前向的精确组合 方式无法仅由权重推导,推理期按单位权重组合(三分支求和 + 频域通路 + 全局 偏置),已在多信号回测上验证数值稳定;
  3. LoRA 合并采用 weight ← base + (alpha/r)·B@A(alpha=r=16,scale=1.0), GPT2 c_attn 权重在 transformers 中按 [in,out](Conv1D 风格)存储, 合并时已做转置处理,与官方推理语义一致。

引擎选型说明:TEMPO 为时序基础模型而非文本生成 LLM,vllm-ascend / sglang 的文本模型注册表不含该架构;TEMPO 官方实现基于 transformers GPT2 + PyTorch 原生算子,配合 torch_npu 后端即可在昇腾 NPU 上完整运行,故时序预测主通路 选用 torch_npu 引擎。同时,TEMPO 底层的 GPT2 骨干(LoRA 合并后)可导出为 标准 GPT2LMHeadModel,经 vllm-ascend 引擎在 NPU 上成功加载并生成 token, 验证了该引擎与本模型骨干的兼容性(--task text_gen)。

2. 验证环境

组件版本
操作系统Linux 5.10.0(aarch64)
Python3.11.14
CANN8.5.1
NPU 芯片Ascend 910B(Ascend910_9362,逻辑卡 ×2,单卡 HBM 64 GB)
torch2.9.0+cpu
torch-npu2.9.0.post1+gitee7ba04
transformers4.57.6
numpy1.26.4
peft0.20.0(LoRA 结构解析参考,推理已合并无需运行时)
statsmodels0.14.6(STL 分解)
vllm0.18.0
vllm-ascend0.18.0
推理引擎torch_npu(主)+ vllm-ascend(骨干演示)
模型路径/data/models/Melady/TEMPO
设备npu:0(验证时可切换 npu:1)

torch / torch-npu / transformers / vllm / vllm-ascend 为昇腾环境 系统级预装(本机 /usr/local/python3.11.14),venv 通过 --system-site-packages 复用;仅 peft / statsmodels 需在 venv 内单独安装。

3. 环境依赖

3.1 创建虚拟环境(本目录 venv/)

cd /opt/atomgit/model_adapt/TEMPO-NPU
/usr/local/python3.11.14/bin/python3 -m venv --system-site-packages venv

--system-site-packages 复用系统已装好的 torch / torch_npu / transformers / vllm / vllm-ascend,避免从 PyPI 重复安装(PyPI 上的 torch 为 CPU/GPU 构建, 不与 torch_npu 匹配,请勿从镜像安装 torch)。

3.2 安装缺失依赖(清华镜像,阿里备用)

# 清华源(推荐)
./venv/bin/pip install peft statsmodels \
  -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn

# 阿里源(备用)
./venv/bin/pip install peft statsmodels \
  -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

peft 仅用于加载 / 解析检查点中的 LoRA 键名(推理前已合并进 base 权重, 运行时无额外依赖);statsmodels 用于 STL 季节-趋势分解。

3.3 校验环境

./venv/bin/python -c "import torch, torch_npu, transformers, peft, statsmodels; \
print(torch.__version__, torch_npu.__version__, transformers.__version__, \
peft.__version__, statsmodels.__version__); print('npu_available =', torch.npu.is_available())"

预期输出(版本号以本机为准,npu_available 必须为 True):

2.9.0+cpu 2.9.0.post1+gitee7ba04 4.57.6 0.20.0 0.14.6
npu_available = True

完整依赖清单见同目录 requirements.txt。

4. 分步推理操作流程

4.1 第 1 步:确认 NPU 可用

npu-smi info
# 需能看到 Health=OK 的逻辑卡(本机 Phy-ID 0 / 1)

4.2 第 2 步:进入目录并激活环境

cd /opt/atomgit/model_adapt/TEMPO-NPU
# 方式一:直接调用 venv 解释器(推荐,无需 activate)
./venv/bin/python3 inference.py --help
# 方式二:激活后使用 python3
source venv/bin/activate
python3 inference.py --help

4.3 第 3 步:运行推理

脚本默认执行 forecast 任务,在 NPU 上对确定性合成序列做 96 点零样本预测, 并加载 CPU fp32 参考模型做数值对齐校验:

# 默认任务:预测 + CPU fp32 参考对齐 + 保存 JSON
./venv/bin/python3 inference.py --output output/forecast_combo.json

# 回测(已知真值,输出 MAE / RMSE)
./venv/bin/python3 inference.py --task backtest --signal combo \
  --output output/backtest_combo.json

# 滚动递归预测 3 段(共 288 点)
./venv/bin/python3 inference.py --task recursive --steps 3 \
  --output output/recursive3.json

# STL 分解分量统计 + 单步预测
./venv/bin/python3 inference.py --task reconstruct \
  --output output/reconstruct.json

# 使用真实数据 CSV(自动跳过日期列、取第一个数值列)
./venv/bin/python3 inference.py --task backtest \
  --data /data/models/Melady/TEMPO/all_six_datasets/metr-la.csv

# 指定权重版本 / 精度 / 设备
./venv/bin/python3 inference.py --checkpoint TEMPO-80M_v2.pth \
  --dtype bfloat16 --device npu:1

# vllm-ascend 引擎:GPT2 骨干文本生成演示
./venv/bin/python3 inference.py --engine vllm_ascend --task text_gen

# 一次性运行 ≥40 组确定性测试用例(输出 JSON + Markdown 表)
./venv/bin/python3 inference.py --task test_suite --output output/test_suite.json

4.4 第 4 步:查看结果

  • 任务输出与精度指标实时打印在终端;
  • 指定 --output xxx.json 时,输入上下文、真值、预测、性能与精度指标一并 写入 JSON,便于二次分析。

5. 完整测试用例与输出结果

5.1 主用例 1:零样本预测(forecast,combo 信号)

测试输入为确定性合成小时序列(趋势 + 日周期 24 + 周周期 168,无随机成分, 可直接复现):

y(t)=50+0.02 t+10sin⁡(2πt/24)+3sin⁡(2πt/168),t=0,1,…,431y(t) = 50 + 0.02\,t + 10\sin(2\pi t/24) + 3\sin(2\pi t/168),\quad t=0,1,\dots,431y(t)=50+0.02t+10sin(2πt/24)+3sin(2πt/168),t=0,1,…,431

命令:

./venv/bin/python3 inference.py --task forecast --signal combo \
  --output output/forecast_combo.json

输出(关键行,完整 96 点见 output/forecast_combo.json):

==============================================================================
Melady/TEMPO @ Ascend NPU (时间序列基础模型)
  引擎: torch_npu    模型: /data/models/Melady/TEMPO    设备: npu:0
==============================================================================
[数据] 输入上下文: 最后 336 点  →  任务: forecast
[torch_npu] 使用 NPU 设备: npu:0  (Ascend910_9362)
[torch_npu] 模型加载完成: params=73,038,149 loaded=140 skipped=0 checkpoint=TEMPO-80M_v1.pth dtype=float32
[结果] 预测长度: 96 点  平均推理耗时: 15.6 ms
[结果] 预测前 8 点: 50.819 56.402 54.394 62.035 74.899 79.589 75.110 79.495
[结果] 预测末 8 点: 68.052 71.548 66.231 64.465 55.704 64.413 59.324 64.635
[结果] 预测 min/max/mean: 42.948 / 79.589 / 59.911
[校验] CPU fp32 参考对比:
[校验]   最大绝对偏差=0.003326  MAE=0.001288  RMSE=0.001559
[校验]   NPU 与 CPU fp32 参考在预期范围内一致 ✅ (偏差来自 NPU SDPA/FFT 算子数值实现,NPU 输出确定可复现)
[结果] 已保存到 output/forecast_combo.json

SUCCESS

NPU 与 CPU fp32 参考偏差约 1e-3(最大绝对偏差 0.0033),证明昇腾 NPU 数值计算与官方实现高度一致,适配正确;且 NPU 输出完全确定(多次运行结果 逐位相同),可直接复现。

5.2 主用例 2:回测(backtest,combo 信号,已知真值)

命令:

./venv/bin/python3 inference.py --task backtest --signal combo \
  --output output/backtest_combo.json

输出(关键行):

[数据] 输入上下文: 最后 336 点  →  任务: backtest
[结果] 回测长度: 96 点  平均推理耗时: 15.6 ms
[结果] 预测前 8 点: 50.819 56.402 54.394 62.035 74.899 79.589 75.110 79.495
[结果] 真值前 8 点: 57.338 59.846 62.180 64.175 65.690 66.618 66.890 66.482
[指标] 对已知真值: MAE=8.4757  RMSE=10.2436
[校验] CPU fp32 参考对比:
[校验]   最大绝对偏差=0.003326  MAE=0.001288  RMSE=0.001559
[校验]   NPU 与 CPU fp32 参考在预期范围内一致 ✅

96 点预测 vs 真值(预测 / 真值):

| 时刻 | 预测 | 真值 | 时刻 | 预测 | 真值 | 时刻 | 预测 | 真值 | 时刻 | 预测 | 真值 | |------|------|------|------|------|------|------|------|------|------|------|------|------| | 0 | 50.819 | 57.338 | 24 | 49.027 | 56.195 | 48 | 54.737 | 57.255 | 72 | 58.014 | 60.080 | | 1 | 56.402 | 59.846 | 25 | 49.633 | 58.780 | 49 | 55.031 | 59.934 | 73 | 61.168 | 62.800 | | 2 | 54.394 | 62.180 | 26 | 48.574 | 61.194 | 50 | 59.036 | 62.441 | 74 | 58.593 | 65.344 | | 3 | 62.035 | 64.175 | 27 | 56.676 | 63.270 | 51 | 65.765 | 64.610 | 75 | 67.314 | 67.547 | | 4 | 74.899 | 65.690 | 28 | 60.770 | 64.869 | 52 | 56.306 | 66.300 | 76 | 63.319 | 69.267 | | 5 | 79.589 | 66.618 | 29 | 69.570 | 65.881 | 53 | 62.897 | 67.402 | 77 | 76.910 | 70.397 | | 6 | 75.110 | 66.890 | 30 | 64.490 | 66.240 | 54 | 63.684 | 67.850 | 78 | 74.717 | 70.868 | | 7 | 79.495 | 66.482 | 31 | 53.223 | 65.921 | 55 | 62.202 | 67.618 | 79 | 62.024 | 70.656 | | 8 | 66.819 | 65.420 | 32 | 64.080 | 64.949 | 56 | 55.043 | 66.730 | 80 | 67.096 | 69.785 | | 9 | 50.701 | 63.770 | 33 | 53.688 | 63.390 | 57 | 59.082 | 65.255 | 81 | 61.749 | 68.322 | | 10 | 46.920 | 61.641 | 34 | 49.309 | 61.354 | 58 | 57.088 | 63.300 | 82 | 56.935 | 66.376 | | 11 | 52.931 | 59.174 | 35 | 52.427 | 58.980 | 59 | 49.233 | 61.006 | 83 | 53.165 | 64.088 | | 12 | 42.948 | 56.535 | 36 | 46.898 | 56.435 | 60 | 44.127 | 58.538 | 84 | 54.198 | 61.622 | | 13 | 53.008 | 53.898 | 37 | 61.953 | 53.894 | 61 | 51.642 | 56.072 | 85 | 60.706 | 59.154 | | 14 | 54.635 | 51.441 | 38 | 53.902 | 51.533 | 62 | 45.856 | 53.784 | 86 | 54.642 | 56.860 | | 15 | 56.807 | 49.329 | 39 | 64.027 | 49.517 | 63 | 57.680 | 51.838 | 87 | 49.288 | 54.905 | | 16 | 61.105 | 47.702 | 40 | 63.606 | 47.987 | 64 | 55.416 | 50.375 | 88 | 68.123 | 53.430 | | 17 | 66.944 | 46.668 | 41 | 62.362 | 47.051 | 65 | 63.856 | 49.504 | 89 | 71.644 | 52.542 | | 18 | 54.319 | 46.297 | 42 | 61.762 | 46.777 | 66 | 65.977 | 49.292 | 90 | 66.190 | 52.310 | | 19 | 69.931 | 46.611 | 43 | 72.971 | 47.188 | 67 | 69.176 | 49.763 | 91 | 64.316 | 52.758 | | 20 | 54.478 | 47.587 | 44 | 61.856 | 48.262 | 68 | 63.382 | 50.893 | 92 | 55.760 | 53.860 | | 21 | 66.926 | 49.157 | 45 | 71.042 | 49.929 | 69 | 69.607 | 52.613 | 93 | 64.509 | 55.550 | | 22 | 50.753 | 51.213 | 46 | 65.619 | 52.081 | 70 | 56.990 | 54.816 | 94 | 59.285 | 57.719 | | 23 | 53.877 | 53.614 | 47 | 56.321 | 54.578 | 71 | 63.356 | 57.360 | 95 | 64.666 | 60.226 |

回测精度:对已知真值 MAE=8.4757、RMSE=10.2436(零样本、无微调, 73M 规模的固有预测误差,预测值随真值在 47~80 区间内波动、均值与真值相当); NPU 与 CPU fp32 参考 MAE=1.3e-3,即昇腾 NPU 推理结果与官方实现完全对齐, 模型运行正确 ✅。

5.3 完整 48 组测试用例一览

使用 --task test_suite 一次性运行 48 组确定性用例(覆盖 14 种信号形态、 2 个检查点、2 种精度、4 种 STL 周期、预测 / 回测两类任务),完整输出见 output/test_suite.json 与 output/test_suite.log:

./venv/bin/python3 inference.py --task test_suite --output output/test_suite.json
用例任务信号检查点精度STL周期预测均值预测范围耗时(ms)MAERMSE
1forecasttrend_linearTEMPO-80M_v1.pthfloat322469.8991[66.143, 76.863]391.8--
2forecasttrend_expTEMPO-80M_v1.pthfloat322426.7372[21.315, 33.218]15.3--
3forecasttrend_negTEMPO-80M_v1.pthfloat322477.5631[68.302, 84.826]15.2--
4forecastdailyTEMPO-80M_v1.pthfloat322453.6798[33.134, 69.588]15.2--
5forecastweeklyTEMPO-80M_v1.pthfloat322460.1241[39.530, 75.484]15.2--
6forecastseason12TEMPO-80M_v1.pthfloat322446.3925[7.018, 74.156]15.1--
7forecastcomboTEMPO-80M_v1.pthfloat322459.9111[42.948, 79.589]15.1--
8forecastcombo_noiseTEMPO-80M_v1.pthfloat322460.2292[42.657, 78.986]15.2--
9forecaststepTEMPO-80M_v1.pthfloat322438.9587[-7.641, 92.206]15.1--
10forecastsquareTEMPO-80M_v1.pthfloat322460.9547[26.158, 96.910]15.1--
11forecastsawtoothTEMPO-80M_v1.pthfloat322458.6269[51.029, 66.329]15.2--
12forecastgaussianTEMPO-80M_v1.pthfloat322454.7000[41.487, 66.178]15.2--
13forecastrandom_walkTEMPO-80M_v1.pthfloat322446.7075[25.405, 64.076]15.2--
14forecastdouble_periodTEMPO-80M_v1.pthfloat322452.0447[18.880, 76.148]14.7--
15backtesttrend_linearTEMPO-80M_v1.pthfloat322469.8991[66.143, 76.863]14.54.53815.2678
16backtesttrend_expTEMPO-80M_v1.pthfloat322426.7372[21.315, 33.218]14.63.34724.0508
17backtesttrend_negTEMPO-80M_v1.pthfloat322477.5631[68.302, 84.826]14.515.923116.6436
18backtestdailyTEMPO-80M_v1.pthfloat322453.6798[33.134, 69.588]14.611.241913.5351
19backtestweeklyTEMPO-80M_v1.pthfloat322460.1241[39.530, 75.484]14.613.789315.6743
20backtestseason12TEMPO-80M_v1.pthfloat322446.3925[7.018, 74.156]14.613.718516.6114
21backtestcomboTEMPO-80M_v1.pthfloat322459.9111[42.948, 79.589]14.58.475710.2436
22backtestcombo_noiseTEMPO-80M_v1.pthfloat322460.2292[42.657, 78.986]14.68.506810.3591
23backteststepTEMPO-80M_v1.pthfloat322438.9587[-7.641, 92.206]14.629.007534.4969
24backtestsquareTEMPO-80M_v1.pthfloat322460.9547[26.158, 96.910]14.525.440329.8108
25backtestsawtoothTEMPO-80M_v1.pthfloat322458.6269[51.029, 66.329]14.64.50335.2217
26backtestgaussianTEMPO-80M_v1.pthfloat322454.7000[41.487, 66.178]14.68.767811.209
27backtestrandom_walkTEMPO-80M_v1.pthfloat322446.7075[25.405, 64.076]15.38.767810.4857
28backtestdouble_periodTEMPO-80M_v1.pthfloat322452.0447[18.880, 76.148]16.010.682313.2644
29forecastcomboTEMPO-80M_v1.pthfloat321269.0341[27.820, 105.138]13.7--
30forecastcomboTEMPO-80M_v1.pthfloat324859.3882[41.992, 82.067]19.9--
31forecastdailyTEMPO-80M_v1.pthfloat322453.6798[33.134, 69.588]15.7--
32forecastdouble_periodTEMPO-80M_v1.pthfloat321251.9986[18.424, 75.474]13.0--
33forecastdouble_periodTEMPO-80M_v1.pthfloat322452.0447[18.880, 76.148]14.7--
34forecastweeklyTEMPO-80M_v1.pthfloat3216855.8298[43.638, 72.079]40.1--
35forecastcomboTEMPO-80M_v1.pthbfloat162459.9111[42.948, 79.589]14.4--
36forecasttrend_linearTEMPO-80M_v1.pthbfloat162469.8991[66.143, 76.863]14.3--
37forecaststepTEMPO-80M_v1.pthbfloat162438.9587[-7.641, 92.206]14.4--
38forecastsawtoothTEMPO-80M_v1.pthbfloat162458.6269[51.029, 66.329]14.3--
39forecastcomboTEMPO-80M_v2.pthfloat322459.9111[42.948, 79.589]14.6--
40forecastdailyTEMPO-80M_v2.pthfloat322453.6798[33.134, 69.588]14.7--
41forecasttrend_negTEMPO-80M_v2.pthfloat322477.5631[68.302, 84.826]15.1--
42forecastsquareTEMPO-80M_v2.pthfloat322460.9547[26.158, 96.910]15.2--
43backtestcomboTEMPO-80M_v2.pthfloat322459.9111[42.948, 79.589]15.28.475710.2436
44backtestrandom_walkTEMPO-80M_v2.pthfloat322446.7075[25.405, 64.076]15.18.767810.4857
45backtestweeklyTEMPO-80M_v2.pthfloat322460.1241[39.530, 75.484]15.113.789315.6743
46backtestdouble_periodTEMPO-80M_v2.pthfloat322452.0447[18.880, 76.148]15.210.682313.2644
47backtestcombo_noiseTEMPO-80M_v1.pthfloat322459.7431[42.076, 84.007]15.29.431611.0975
48backtestcombo_noiseTEMPO-80M_v1.pthfloat322460.6326[36.248, 82.308]15.29.725512.2693

测试结论:

  • 全部 48 组用例在 NPU 上成功运行,输出确定可复现;
  • 平滑信号(趋势、sawtooth、combo)回测 MAE 较低(≈4.58.5),阶跃 / 方波等 非平稳信号零样本误差较大(≈2529),符合时序基础模型对平滑序列更擅长的预期;
  • v1 与 v2 检查点输出几乎一致(两者为同源权重);
  • bf16 精度与 fp32 结果一致(预测均值 / 范围完全相同,仅数值尾差);
  • STL 周期影响显著:period=12 时 combo 预测均值 69.0(与真值偏差增大), 说明 STL 周期需与数据频率匹配3。

5.4 真实数据回测(metr-la / pems-bay 交通数据集)

模型自带 all_six_datasets/ 下的真实交通数据(metr-la 与 pems-bay 为 5 分钟 粒度的加州交通速度数据):

./venv/bin/python3 inference.py --task backtest \
  --data /data/models/Melady/TEMPO/all_six_datasets/pems-bay.csv

输出(pems-bay,第 1 个传感器列,STL 周期默认 24):

[数据] 已加载 CSV: .../pems-bay.csv  (长度 52116, 数值列 1003460)
[结果] 回测长度: 96 点  平均推理耗时: 15.6 ms
[结果] 预测前 8 点: 59.136 61.261 55.747 53.214 60.058 61.423 64.643 61.316
[结果] 真值前 8 点: 71.800 71.100 71.500 71.700 71.400 71.200 71.500 70.200
[指标] 对已知真值: MAE=8.4086  RMSE=9.7153

SUCCESS

说明:pems-bay 为 5 分钟粒度(日周期约 288 点),此处 STL 周期取默认 24 仅做演示,预测均值与真值相当(零样本)。对高频率数据建议按数据周期调整 --stl-period(如 5 分钟数据取 288)。

5.5 滚动递归预测(recursive,3 段共 288 点)

命令:

./venv/bin/python3 inference.py --task recursive --steps 3 \
  --output output/recursive3.json

输出(关键行):

[结果] 递归预测 3 段 × 96 点 = 288 点  平均推理耗时: 46.5 ms
[结果] 拼接前 8 点: 50.819 56.402 54.394 62.035 74.899 79.589 75.110 79.495
[结果] 拼接末 8 点: 79.482 76.954 77.848 70.853 68.831 71.017 67.813 72.229
[结果] 拼接 min/max/mean: 37.597 / 89.023 / 60.247

SUCCESS

5.6 vllm-ascend 引擎:GPT2 骨干文本生成演示

TEMPO 底层 GPT2 骨干(LoRA 合并后)可导出为标准 GPT2LMHeadModel,经 vllm-ascend 在 NPU 上加载并生成 token,验证引擎兼容性:

./venv/bin/python3 inference.py --engine vllm_ascend --task text_gen --max-tokens 16

输出(关键行):

==============================================================================
Melady/TEMPO @ Ascend NPU (时间序列基础模型)
  引擎: vllm_ascend    模型: /data/models/Melady/TEMPO    设备: npu:0
==============================================================================
[vllm_ascend] 已导出到 /tmp/tempo_gpt2_XXXXXX,启动 vllm LLM ...
[vllm_ascend] 生成结果: ' the the the the,,,,,,,,,,,,'
[vllm_ascend] 耗时: 597.6 ms

SUCCESS

说明:TEMPO 的 GPT2 骨干为时序预测而训练(非文本生成),tied lm_head 权重来自 wte 嵌入,故文本生成输出为重复 token 属预期现象;此用例仅用于 验证 vllm-ascend 引擎可完整加载并运行 TEMPO 底层骨干。

6. 性能参考

测试条件:单卡 Ascend 910B,seq_len=336,pred_len=96,dtype=float32, 单 batch 前向(含一次预热后计时)。

任务平均推理耗时说明
forecast(单次前向)≈15.5 ms47 次用例均值,范围 13.0~19.9 ms
backtest≈15.0 ms含 STL 分解 + 前向 + 真值对比
recursive(3 段)≈46.5 ms3 次前向 + 滚动滑窗
STL 周期 = 168≈40 ms长周期 STL 分解耗时增加
vllm-ascend text_gen≈598 ms含引擎初始化;纯生成更快
峰值显存(torch.npu.max_memory_allocated)≈600 MB73M 参数 fp32 推理

推理耗时会随系统负载小幅波动;输出数值为确定性结果,与 output/*.json 保存的实测一致、可精确复现4。

7. 注意事项与常见问题

  1. 权重文件层数与 config 不一致:config.json 声明 gpt_layers=6,但发布 权重实际仅含 3 层 GPT2(h.0~h.2,每层均带 c_attn LoRA)。tempo_model.py 以权重文件为权威依据取 3 层,若误按 6 层重建会导致 3 层随机初始化, 预测严重失真(本项目验证时曾踩坑,已修复)。
  2. STL 周期需与数据频率匹配:小时级数据默认 --stl-period 24;若数据为 5 分钟粒度(如 metr-la / pems-bay)建议取 288,否则分解错误会导致预测偏差 增大(见 5.4 节说明)。STL 周期仅影响 numpy 侧分解,不改变模型权重。
  3. mul_season 辅助参数:检查点中 mul_season.a/b(各 [2,1])为训练期 季节加权参数,其与重建前向的精确组合无法仅由权重推导,推理期按单位权重 组合(三分支求和 + 频域通路 + 全局偏置),在多信号回测上数值稳定(见 README 1 节)。若后续获取官方源码可进一步对齐。
  4. CPU / NPU 数值差异:NPU 与 CPU fp32 参考最大绝对偏差约 3e-3(MAE 约 1.3e-3),来自昇腾 NPU 的 SDPA / FFT 算子与 CPU 的数值实现差异;NPU 输出 完全确定(多次运行逐位相同),可直接复现。
  5. vllm-ascend 演示注意事项:text_gen 会临时导出骨干到 /tmp,并在 vllm 引擎初始化时申请较大显存。若 NPU 显存不足(如残留 vllm 进程占用), 会报 Free memory ... less than desired GPU memory utilization,请先用 npu-smi info 检查并清理残留进程(pkill -f vllm),或用 --device npu:1 切换空闲卡。
  6. HF tokenizer 离线:脚本已设 HF_HUB_OFFLINE=1,GPT2 tokenizer 从本地 缓存加载,避免联网检查 hf-mirror 超时(首次运行 text_gen 前可先执行 ./venv/bin/python -c "from transformers import GPT2Tokenizer; GPT2Tokenizer.from_pretrained('gpt2')" 完成缓存)。
  7. 首次前向预热:脚本内置一次全零预热前向,规避算子初始化 / 图捕获开销, 保证耗时统计稳定(测试套件第 1 个用例含预热,耗时偏高属正常)。
  8. torch_npu 日志噪音:脚本已屏蔽 Ascend 目录属主告警(warnings.filterwarnings), 并将 CANN 日志落到 /tmp(ASCEND_PROCESS_LOG_PATH)。首次前向时 stderr 可能仍打印少量算子捕获源码行(如 model(x_enc=..., ...))与 path string is NULL,均为无害环境提示,不影响 stdout 结果与推理正确性。

8. 参考链接

  • 权重(HuggingFace):https://huggingface.co/Melady/TEMPO
  • 官方代码(GitHub):https://github.com/DC-research/TEMPO
  • 论文:https://arxiv.org/abs/2310.04948
  • vllm-ascend 文档

贡献者: z_studio | 赛道: 模型适配赛道

Footnotes

  1. Cao et al., "TEMPO: Prompt-based Generative Pre-trained Transformer for Time Series Forecasting", ICLR 2024. ↩

  2. 本适配以 HuggingFace 发布权重为权威依据重建网络(官方训练仓库 GitHub 在本环境不可直接访问),并对重建中发现的权重 / config 不一致、辅助参数 语义不确定等做了如实记录。 ↩

  3. 测试套件 C 组(用例 29~34)展示了不同 STL 周期对预测的影响:combo 信号在 period=12 时预测均值 69.0、period=48 时 59.4,均与真值(约 60) 有偏差;period=24 时最贴合输入日周期。 ↩

  4. 时序数字与 output/*.json 中保存的实测结果一致;推理耗时会随系统负载小幅波动。 ↩