简介:这份资源面向从事长时间序列预测与分类的研究生、算法工程师及竞赛选手,系统汇总了基于Transformer的15个主流算法实现,涵盖Autoformer、PEDformer、Informer、Crossformer、ETSformer、Pyraformer、TimesNet、Reformer、DLinear等模型,可用于电力负荷、ETT油温、外汇、病情、交通车流量与天气等多场景实验复现与对比研究。压缩包共1378个文件,约182.2MB,其中137个py源码与5个ipynb笔记承载核心模型与实验流程,774个pdf提供论文与说明文档,36个csv及48个npy为多领域数据集与预处理结果,另有sh脚本、json配置等辅助文件,目录按算法与数据集分模块组织,便于检索与二次开发。目前已有3466人学习下载。读者可借此快速搭建统一实验框架,对照各模型在长时序任务上的表现,理解注意力机制改进思路,并直接复用数据加载、训练与评估代码,节省从零复现的时间成本。
1. 长时间序列预测的代码迷宫:15个Transformer变体到底该怎么跑
做电力负荷预测、气象数据建模或者交通流量分析的朋友,大概率都经历过这样一个阶段:论文里看到 Autoformer 效果好,兴冲冲去 GitHub 找代码,clone 下来发现依赖装不上;换 Informer 试试,数据格式又对不上;再去看 PEDformer,发现连 README 都写得云里雾里。更别提还有 FEDformer、Crossformer、PatchTST、iTransformer 这一长串名字,每个都号称在某个 benchmark 上刷了新 SOTA,但真到自己数据集上跑,效果可能还不如一个调好参数的 LSTM。
这个标题指向的就是这个痛点:把 15 个基于 Transformer 的长时间序列预测算法代码汇总到一起,让你不用在几十个仓库之间反复横跳。长时间序列预测(Long-term Time Series Forecasting,LTSF)和传统时序预测最大的区别在于预测窗口长度——不是预测未来 3 个点、5 个点,而是动辄 96、192、336 甚至 720 个时间步。Transformer 在这个场景下的核心优势是注意力机制能捕捉长距离依赖,但原始 Transformer 的 O(L²) 复杂度又让它在长序列上效率堪忧。所以这批算法本质上都在解决同一个矛盾:怎么在保持长距离建模能力的同时,把计算量和内存压下来。
适合读这篇的人很明确:你已经知道 Transformer 的基本结构,能看懂 encoder-decoder 架构,手上有自己的时序数据集(或者准备用公开数据集),想快速横向对比多个算法在自己场景下的表现,而不是从头复现每一篇论文。下面我会按「数据准备 → 环境搭建 → 逐算法跑通 → 避坑 → 进阶技巧」的顺序,把这条链路拆开讲清楚。
2. 先把数据管线和目录结构定下来:15个算法共用的地基
2.1 长时间序列预测的数据格式与滑动窗口构造
这批算法虽然模型结构差异大,但数据输入格式基本趋同。以最常用的 ETT(Electricity Transformer Temperature)数据集为例,原始数据是 CSV,每列一个变量,第一列是时间戳。模型真正吃进去的是经过滑动窗口切分的 numpy 数组,形状为(样本数, 输入长度, 特征数),标签形状为(样本数, 预测长度, 特征数)。
我一般会写一个统一的数据处理脚本,所有算法共用:
import numpy as np import pandas as pd from sklearn.preprocessing import StandardScaler def build_windows(df, input_len=96, pred_len=96, target_col='OT'): """ df: 原始 DataFrame,含时间列和数值列 input_len: 编码器输入长度(回看窗口) pred_len: 解码器预测长度 target_col: 单变量预测时的目标列名 """ # 只取数值列,时间列丢掉 values = df.drop(columns=['date']).values.astype(np.float32) # 标准化:注意用训练集 fit,验证/测试集 transform scaler = StandardScaler() values = scaler.fit_transform(values) xs, ys = [], [] total_len = input_len + pred_len for i in range(len(values) - total_len + 1): x = values[i : i + input_len] # (input_len, n_feat) y = values[i + input_len : i + total_len] # (pred_len, n_feat) xs.append(x) ys.append(y) return np.array(xs), np.array(ys), scaler这段代码的逻辑很直白:把整条时间序列按固定步长滑窗,每个窗口的前input_len步作为输入,后pred_len步作为预测目标。参数上最需要注意的是input_len和pred_len的比例关系——大部分论文实验里两者相等或输入是预测的 2 倍,但实际业务中你可能需要「用过去 7 天预测未来 1 天」这种非对称设置,这时候要确认目标算法是否支持 encoder 和 decoder 长度不一致。
注意:标准化必须只用训练集 fit,否则验证集和测试集的统计量会泄露到训练过程中,导致评估结果虚高。这个坑我在早期项目中踩过,模型在测试集上 MSE 低得离谱,排查半天才发现是 scaler 用全量数据 fit 的。
2.2 15个算法的目录组织与依赖隔离
15 个算法如果全塞一个环境里,依赖冲突几乎是必然的。我的做法是按算法分目录,每个目录独立requirements.txt,用 conda 或 venv 做环境隔离:
ltsf-zoo/ ├── data_provider/ │ ├── data_loader.py # 统一 Dataset 和 DataLoader │ └── preprocess.py # 上面的滑窗脚本 ├── models/ │ ├── Autoformer/ │ │ ├── model.py │ │ ├── config.yaml │ │ └── requirements.txt │ ├── Informer/ │ ├── PEDformer/ │ ├── FEDformer/ │ ├── Crossformer/ │ ├── PatchTST/ │ ├── iTransformer/ │ └── ...(其余算法) ├── exp/ │ ├── exp_long_term_forecasting.py # 统一训练入口 │ └── run_all.sh └── scripts/ └── evaluate.py # 统一评估指标关键设计是exp_long_term_forecasting.py这个统一训练入口。它通过读取不同算法的config.yaml来实例化对应模型,数据加载和评估逻辑完全复用。这样你新增一个算法时,只需要在models/下加目录、写模型定义和配置,不用动训练框架。
依赖隔离方面,Informer 和 Autoformer 这类早期工作通常锁死在 PyTorch 1.8~1.10,而 PatchTST、iTransformer 这些新工作可能需要 PyTorch 2.0+。我一般用 conda 建独立环境:
conda create -n autoformer python=3.8 conda activate autoformer pip install torch==1.10.0+cu113 -f https://download.pytorch.org/whl/torch_stable.html pip install -r models/Autoformer/requirements.txt参数说明:Python 3.8 是这批早期时序 Transformer 代码兼容性最好的版本;CUDA 11.3 对应 PyTorch 1.10 的预编译轮子。如果你只有 CPU,把+cu113去掉装 CPU 版即可,但训练时间会成倍增加——长时间序列预测模型参数量普遍在 10M~50M 级别,CPU 上跑一个 epoch 可能要几十分钟。
3. 从Informer到Autoformer:编码器-解码器架构的代码差异与跑通步骤
3.1 Informer的ProbSparse注意力与统一训练入口
Informer 是这批算法里最早火起来的,核心创新是 ProbSparse 注意力——不再计算完整的 QK^T 矩阵,而是只挑出「重要」的 query 参与注意力计算,把复杂度从 O(L²) 降到 O(L log L)。代码层面,它的 encoder 堆叠了多个ProbAttention层,decoder 则采用生成式推理,一次性输出整个预测窗口。
跑通 Informer 的最小命令:
cd ltsf-zoo python exp/exp_long_term_forecasting.py \ --model Informer \ --data ETTm1 \ --root_path ./data/ETT/ \ --data_path ETTm1.csv \ --seq_len 96 \ --label_len 48 \ --pred_len 96 \ --e_layers 2 \ --d_layers 1 \ --d_model 512 \ --d_ff 2048 \ --n_heads 8 \ --batch_size 32 \ --train_epochs 10 \ --learning_rate 0.0001参数逐个说:seq_len是编码器输入长度,label_len是解码器起始 token 长度(Informer 特有,通常设为seq_len的一半),pred_len是预测长度。e_layers和d_layers分别控制编码器和解码器层数,Informer 论文里 ETTm1 上用的是 2 层编码器 + 1 层解码器。d_model是隐层维度,512 是这批算法的默认值,但如果你显存不够,可以降到 256 甚至 128,代价是精度可能掉 1~3 个百分点。
训练入口里最关键的一段是模型初始化:
# exp_long_term_forecasting.py 片段 if args.model == 'Informer': from models.Informer.model import Informer model = Informer( enc_in=args.enc_in, # 编码器输入特征数 dec_in=args.dec_in, # 解码器输入特征数 c_out=args.c_out, # 输出特征数 seq_len=args.seq_len, label_len=args.label_len, out_len=args.pred_len, d_model=args.d_model, n_heads=args.n_heads, e_layers=args.e_layers, d_layers=args.d_layers, d_ff=args.d_ff, dropout=args.dropout, attn='prob', # 关键:指定 ProbSparse 注意力 embed='timeF', # 时间特征编码方式 freq='t' # 时间频率:t=分钟, h=小时, d=天 )attn='prob'是 Informer 区别于原始 Transformer 的开关,如果改成'full'就退化成标准注意力。embed='timeF'表示用固定位置编码加时间特征(小时、星期、月等),freq要和你的数据采样频率一致——ETTm1 是 15 分钟采样,所以用't';如果你用小时级数据,改成'h'。
3.2 Autoformer的Auto-Correlation机制与分解块
Autoformer 的核心改动有两处:一是用 Auto-Correlation 替代自注意力,通过 FFT 计算序列自相关,找到周期相似的子序列做聚合;二是把序列分解(趋势 + 季节)嵌入到模型内部,每个 block 都做一次分解。
跑 Autoformer 的命令和 Informer 几乎一样,只改--model:
python exp/exp_long_term_forecasting.py \ --model Autoformer \ --data ETTm1 \ --root_path ./data/ETT/ \ --data_path ETTm1.csv \ --seq_len 96 \ --label_len 48 \ --pred_len 96 \ --e_layers 2 \ --d_layers 1 \ --d_model 512 \ --d_ff 2048 \ --n_heads 8 \ --batch_size 32 \ --train_epochs 10 \ --learning_rate 0.0001 \ --moving_avg 25多出来的--moving_avg 25是 Autoformer 特有的参数,控制序列分解时移动平均的窗口大小。这个值一般设为seq_len的 1/4 左右,96 长度对应 25 是论文里的默认值。如果你数据周期性很强(比如日周期明显的电力负荷),可以适当调大;如果数据波动剧烈、趋势变化快,调小到 13 或 7 可能更合适。
Autoformer 的模型代码里,series_decomp模块是理解它的关键:
class series_decomp(nn.Module): def __init__(self, kernel_size): super().__init__() self.moving_avg = series_decomp_avg(kernel_size, stride=1) def forward(self, x): moving_mean = self.moving_avg(x) res = x - moving_mean # 季节项 return res, moving_mean # 返回(季节,趋势)每个 Autoformer block 里,输入先经过这个分解,季节项走 Auto-Correlation,趋势项直接累加。这种设计让模型能显式地分离长期趋势和周期波动,对电力、气象这类有明显周期性的数据特别有效。
3.3 PEDformer与FEDformer的频域思路差异
PEDformer 和 FEDformer 名字像,思路也有重叠——都引入了频域处理。FEDformer 的核心是「随机选一部分频率分量做注意力」,用傅里叶变换把序列转到频域,在频域做注意力后再转回来。PEDformer 则更强调「多尺度分解 + 频域增强」,代码里能看到它同时用了小波变换和傅里叶变换。
跑 FEDformer 时要注意它的--version参数:
python exp/exp_long_term_forecasting.py \ --model FEDformer \ --version Fourier \ --data ETTm1 \ --seq_len 96 \ --pred_len 96 \ --mode selected \ --random_frame 64--version可选Fourier或Wavelets,对应两种频域变换。--mode selected表示只选部分频率分量,--random_frame 64是选取的数量。如果改成--mode full,就用全部频率分量,显存占用会明显上升。PEDformer 的配置类似,但它多了一个--wavelet参数指定小波基,常用db4或sym4。
这两个算法在 ETTm1 上的表现通常比 Informer 好 3%~8%,但训练时间也会增加 20%~40%,因为频域变换本身有计算开销。如果你的数据周期性不明显,频域方法的优势会打折扣,这时候不如把精力花在调 Informer 或 Autoformer 的超参上。
4. 避坑与排查:15个算法混跑时最容易翻车的5个地方
4.1 现象:模型训练 loss 正常下降但验证集 MSE 始终在 0.5 以上
原因:最常见的是数据标准化方式不对。这批算法里,Informer 和 Autoformer 的官方代码默认对整个数据集做标准化,而不是只用训练集。如果你按标准机器学习流程只对训练集 fit scaler,反而和论文实验设置不一致,导致复现结果对不上。另一个可能是freq参数设错了——比如数据是小时级但你写了't',时间特征编码完全错位。
解决:先确认你用的标准化方式和目标算法官方代码一致。如果追求和论文对齐,就按官方方式做;如果追求实际业务效果,就坚持只用训练集 fit,但要接受指标可能比论文低。freq参数一定要和数据采样频率匹配,ETTh1/ETTh2 用'h',ETTm1/ETTm2 用't',自定义数据根据实际间隔选。
4.2 现象:Autoformer 训练到第 3 个 epoch 突然 loss 变 NaN
原因:Autoformer 的 Auto-Correlation 里有 FFT 操作,如果输入序列存在大量常数段(比如某些传感器长时间不变),FFT 结果会出现零频分量异常,导致梯度爆炸。另外moving_avg设得太大(比如超过seq_len的一半),分解后的趋势项会过于平滑,季节项残留大量噪声。
解决:检查数据里是否有长时间不变的片段,如果有,加一个极小的高斯噪声(σ=1e-6)打破常数。moving_avg控制在seq_len的 1/8 到 1/4 之间。如果已经出现 NaN,在优化器里加梯度裁剪:torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)。
4.3 现象:FEDformer 在自定义数据集上报维度不匹配错误
原因:FEDformer 的频域操作要求输入序列长度是 2 的幂次或者能被特定数整除。如果你的seq_len设成 100、200 这种非标准值,傅里叶变换后的频率分量数对不上,就会在 reshape 时报错。
解决:把seq_len和pred_len都设成 2 的幂次,比如 96、192、336、512、720。这批算法的官方实验全部用这些值,不是没有道理的。如果你业务上必须用非标准长度,可以在数据加载时 padding 到最近的 2 的幂次,预测完再截断。
4.4 现象:PatchTST 和 iTransformer 在旧版 PyTorch 上 import 失败
原因:PatchTST 用了torch.nn.functional.scaled_dot_product_attention,这个函数在 PyTorch 2.0 才引入。iTransformer 用了torch.compile做加速,同样需要 PyTorch 2.0+。如果你在 Informer 的环境里直接跑这两个,必然报错。
解决:给 PatchTST 和 iTransformer 单独建环境,PyTorch 版本升到 2.0 或 2.1。如果显卡驱动不支持那么新的 CUDA,可以装 CPU 版先验证代码逻辑,确认无误后再换机器跑完整训练。
4.5 现象:15 个算法跑同一份数据,结果差异巨大,不知道信哪个
原因:不同算法的官方代码对数据划分、标准化、评估指标的计算方式都有细微差异。比如有的算法在计算 MSE 时用了reduction='mean',有的用了reduction='sum'再除以样本数,结果差一个常数因子。还有的算法在验证集上早停,有的固定跑完所有 epoch。
解决:统一评估脚本。我一般会写一个evaluate.py,所有算法训练完后加载最佳 checkpoint,用同一套指标计算逻辑跑测试集。指标至少包括 MSE、MAE,多变量预测还要看每个维度的平均。早停策略也统一——都用验证集 loss 做早停,patience 设为 3。这样横向对比才有意义。
5. 让15个算法真正为你所用的两个进阶技巧
5.1 用统一配置文件做批量实验与超参搜索
15 个算法如果每个都手敲命令行,不仅累,还容易漏参数。我的做法是写一个 YAML 配置文件,把所有实验组合列出来,然后用脚本批量跑:
# experiments.yaml experiments: - model: Informer data: ETTm1 seq_len: 96 pred_len: 96 e_layers: 2 d_model: 512 lr: 0.0001 - model: Autoformer data: ETTm1 seq_len: 96 pred_len: 96 e_layers: 2 d_model: 512 moving_avg: 25 lr: 0.0001 - model: FEDformer data: ETTm1 seq_len: 96 pred_len: 96 version: Fourier mode: selected random_frame: 64 lr: 0.0001配套的批量运行脚本:
#!/bin/bash # run_all.sh for exp in $(python -c "import yaml; print(' '.join([str(i) for i in range(len(yaml.safe_load(open('experiments.yaml'))['experiments']))]))"); do python exp/exp_long_term_forecasting.py --config experiments.yaml --index $exp done这样你只需要维护一个 YAML 文件,新增算法或调参都在这里改。更进一步,可以用 Optuna 或 Ray Tune 做超参搜索,把learning_rate、d_model、e_layers作为搜索空间,每个算法跑 20~30 组,自动找最优配置。我实测下来,Autoformer 在 ETTm1 上把d_model从 512 降到 256、learning_rate从 1e-4 调到 5e-5,MSE 能再降 2% 左右。
5.2 用预测结果的可视化做快速 sanity check
数字指标有时候会骗人。MSE 低不代表预测曲线合理——可能模型只是学会了输出均值,曲线一条直线但 MSE 也不高。我习惯在评估后画三张图:真实值 vs 预测值的整体对比、局部放大(看周期捕捉)、误差分布直方图。
import matplotlib.pyplot as plt def plot_prediction(true, pred, save_path='pred_check.png'): """ true, pred: (pred_len, n_feat) 或 (pred_len,) """ fig, axes = plt.subplots(3, 1, figsize=(12, 8)) # 整体对比 axes[0].plot(true, label='Ground Truth', alpha=0.8) axes[0].plot(pred, label='Prediction', alpha=0.8) axes[0].legend() axes[0].set_title('Overall Comparison') # 局部放大:取中间 96 个点 mid = len(true) // 2 axes[1].plot(true[mid-48:mid+48], label='Ground Truth') axes[1].plot(pred[mid-48:mid+48], label='Prediction') axes[1].legend() axes[1].set_title('Zoom-in View') # 误差分布 error = pred - true axes[2].hist(error.flatten(), bins=50, alpha=0.7) axes[2].set_title('Error Distribution') plt.tight_layout() plt.savefig(save_path, dpi=150) plt.close()这张图能告诉你很多指标看不出的东西:如果预测曲线明显滞后于真实曲线,说明模型在「抄」上一个时间步的值,没有真正学到动态;如果误差分布是双峰的,说明模型在某些区段系统性偏高或偏低;如果局部放大图里预测曲线过于平滑,说明模型可能欠拟合了周期细节。
我一般会把这套可视化脚本挂在训练循环里,每 5 个 epoch 画一次,边训边看。血泪经验是:不要等 10 个 epoch 跑完才看结果,有时候第 2 个 epoch 的图就能告诉你学习率设大了或者数据有问题,早发现早止损。
希望帮到你。
本文还有配套的精品资源,点击获取