简介:这份资源面向从事时间序列预测与分类研究的高校学生、算法工程师及科研人员,系统汇总了15个基于Transformer的经典与前沿模型代码,涵盖Autoformer、PEDformer、Informer、Crossformer、ETSformer、Pyraformer、TimesNet、Reformer、DLinear等,可解决长序列建模中效率与精度难以兼顾的问题,适用于电力负荷、ETT油温、外汇、病情、交通车流量、天气等多场景实验复现与对比研究。压缩包共1378个文件,约182.2MB,其中137个py源码构成各算法核心实现,228个sh脚本便于批量训练与参数配置,774个pdf提供论文与说明文档,另有csv、npy数据集及ipynb、md等辅助文件,目录按算法与数据集分类清晰。目前已有3466人学习下载,读者可一次性获得完整模型代码、训练脚本、数据接口与实验配置,快速搭建基线并开展消融与对比实验,显著降低复现成本。
1. 长时间序列预测的代码困局:为什么15个Transformer变体值得你逐个跑一遍
做电力负荷预测、气象时序建模或者交通流量分析的朋友,大概率都经历过这样的场景:论文里看到Autoformer的分解机制很优雅,PEDformer的频域增强听起来也合理,Informer的稀疏注意力号称把复杂度从O(L²)压到了O(L log L),但真到动手的时候,光是让这些模型的输入输出维度对齐就要折腾一整天。更别提每个仓库的配置格式、数据预处理方式、评估指标实现都不一样,想横向对比几乎等于重写一遍。
长时间序列预测这个方向,从2021年Informer开始,到Autoformer、FEDformer、PEDformer、Crossformer、iTransformer等,前后涌现了十几个有代表性的Transformer变体。它们各自解决不同的问题:有的是注意力机制太慢,有的是长周期依赖捕捉不住,有的是多变量之间的耦合关系没建模好。把这些代码汇总在一起逐个跑通,不是为了刷榜,而是为了搞清楚——在你的数据上,到底哪个架构的归纳偏置最匹配。
这篇文章面向的是已经了解Transformer基本结构、想快速上手时序预测代码的工程师和研究生。我会把15个算法的代码组织方式、环境配置、数据格式、关键参数和常见翻车点讲清楚,让你能在本地把这条流水线跑起来。
2. 15个时序Transformer算法的代码组织与核心差异
2.1 这些模型到底在改什么:从注意力机制到分解策略
先把这15个算法按改进思路分个类,这样你在读代码的时候能快速定位到关键模块。
第一类是注意力效率优化。Informer提出ProbSparse注意力,只计算top-k重要的query-key对,把内存和时间降到O(L log L)。Pyraformer用金字塔式注意力,在不同尺度上做粗粒度到细粒度的信息传递。这类模型适合序列长度超过1000步的场景,比如分钟级电力数据预测未来24小时。
第二类是序列分解与频域增强。Autoformer的核心是串联的序列分解块,把输入拆成趋势项和季节项,分别建模。FEDformer在此基础上引入傅里叶变换和 wavelet 变换,在频域做注意力计算,进一步降低复杂度。PEDformer则结合了渐进式分解和多尺度特征提取。这三个模型在周期性强的数据上表现突出,比如日负荷曲线、交通流量。
第三类是变量间关系建模。Crossformer用两阶段注意力分别捕捉时间维和变量维的依赖。iTransformer干脆把每个变量的整条序列当作一个token,直接在变量维度做注意力。这类模型适合多变量强耦合的场景,比如气象站的多传感器数据。
第四类是架构简化与泛化。有些工作发现,把Transformer的注意力换成简单的线性层或者MLP,效果未必差。这类模型代码更轻量,训练更快,适合作为baseline。
理解了这个分类,你在看每个仓库的model.py时就能直接跳到核心模块,不用从头读起。
2.2 代码目录的统一组织方式
这15个算法的原始仓库结构各不相同,但核心文件基本一致。我一般会按下面的结构重新组织,方便统一调用:
ts_transformer_zoo/ ├── data_provider/ │ ├── data_loader.py # 数据集加载与切分 │ └── data_factory.py # 数据集注册与实例化 ├── models/ │ ├── Autoformer.py │ ├── PEDformer.py │ ├── Informer.py │ ├── FEDformer.py │ ├── Crossformer.py │ ├── iTransformer.py │ └── ... # 其余模型 ├── layers/ │ ├── Embed.py # 位置编码、时间特征嵌入 │ ├── SelfAttention.py # 各种注意力实现 │ ├── AutoCorrelation.py # Autoformer的自相关机制 │ └── FourierBlock.py # 频域注意力模块 ├── exp/ │ ├── exp_main.py # 训练与评估主流程 │ └── exp_basic.py # 基础实验类 ├── utils/ │ ├── metrics.py # MAE, MSE, RMSE │ ├── tools.py # 早停、学习率调整 │ └── timefeatures.py # 时间特征生成 ├── scripts/ │ ├── Autoformer.sh │ ├── Informer.sh │ └── ... └── run.py # 统一入口这个结构参考了Time-Series-Library的组织方式,但做了简化。关键点是:所有模型共享同一套数据加载和训练流程,每个模型只需要实现自己的forward逻辑。这样你换模型只需要改一个参数,不用动数据管道。
数据加载部分,data_loader.py需要处理几种标准格式:.csv文件、.npy数组、以及.txt文本。核心是Dataset类,它负责把原始序列切分成[batch, seq_len, features]的输入和[batch, pred_len, features]的标签。时间特征(小时、星期、月份)通过timefeatures.py生成,拼接到输入中。
# data_provider/data_loader.py import numpy as np import pandas as pd from torch.utils.data import Dataset class TimeSeriesDataset(Dataset): def __init__(self, root_path, flag='train', size=None, features='S', data_path='ETTh1.csv', target='OT', scale=True, timeenc=1): # size = [seq_len, label_len, pred_len] self.seq_len = size[0] self.label_len = size[1] self.pred_len = size[2] self.flag = flag self.target = target self.scale = scale self.timeenc = timeenc # 读取数据,常见做法是按列解析 df_raw = pd.read_csv(os.path.join(root_path, data_path)) # 划分训练/验证/测试集,边界按7:1:2或6:2:2 ... self.data_x, self.data_y = self._get_data(df_raw) self.scaler = StandardScaler() if scale else None def __getitem__(self, index): s_begin = index s_end = s_begin + self.seq_len r_begin = s_end - self.label_len r_end = r_begin + self.label_len + self.pred_len seq_x = self.data_x[s_begin:s_end] seq_y = self.data_y[r_begin:r_end] # 时间特征拼接 if self.timeenc == 1: seq_x_mark = self._time_features(s_begin, s_end) seq_y_mark = self._time_features(r_begin, r_end) return seq_x, seq_y, seq_x_mark, seq_y_mark这段代码的关键参数是size列表,它决定了输入窗口、标签窗口和预测窗口的长度。label_len是解码器输入的起始部分,通常设为seq_len // 2。features参数控制用单变量还是多变量,S表示单变量预测,M表示多变量预测。scale为True时做标准化,这是时序预测的标配操作,但要注意:标准化参数必须只在训练集上拟合,然后应用到验证和测试集,否则会引入未来信息。
2.3 模型注册与统一入口
为了让15个模型能通过一个run.py调用,需要一个简单的注册机制:
# models/__init__.py from .Autoformer import Autoformer from .Informer import Informer from .PEDformer import PEDformer from .FEDformer import FEDformer from .Crossformer import Crossformer from .iTransformer import iTransformer # ... 其余模型导入 MODEL_REGISTRY = { 'Autoformer': Autoformer, 'Informer': Informer, 'PEDformer': PEDformer, 'FEDformer': FEDformer, 'Crossformer': Crossformer, 'iTransformer': iTransformer, # ... } def build_model(args): model_cls = MODEL_REGISTRY[args.model] return model_cls(args)run.py里通过argparse接收参数,然后调用build_model。这样你切换模型只需要改--model参数。每个模型的__init__接收统一的args对象,里面包含seq_len、pred_len、d_model、n_heads、e_layers、d_ff等超参数。不同模型可能用不到某些参数,但统一接口能减少适配成本。
提示:有些模型的原始实现依赖特定的CUDA算子或旧版PyTorch,建议先用PyTorch 1.13以上版本测试,遇到不兼容的算子再单独处理。
3. 从ETTh1到自定义数据:跑通第一个模型的完整流程
3.1 环境配置与依赖安装
先建一个干净的虚拟环境,避免和已有项目冲突:
conda create -n ts_transformer python=3.9 conda activate ts_transformer pip install torch==1.13.1+cu117 torchvision --extra-index-url https://download.pytorch.org/whl/cu117 pip install numpy pandas scikit-learn matplotlib pip install reformer_pytorch # 部分模型依赖 pip install einops # Crossformer等模型需要PyTorch版本建议1.13到2.0之间,太新的版本可能和某些模型的CUDA扩展不兼容。einops用于张量重排,Crossformer和iTransformer的代码里大量使用。reformer_pytorch是部分高效注意力实现的依赖,如果某个模型不需要可以跳过。
安装完成后,用一个小脚本验证环境:
import torch print(torch.__version__) print(torch.cuda.is_available()) # 简单测试注意力计算 q = torch.randn(2, 8, 64, 32).cuda() k = torch.randn(2, 8, 64, 32).cuda() v = torch.randn(2, 8, 64, 32).cuda() attn = torch.softmax(q @ k.transpose(-2, -1) / (32 ** 0.5), dim=-1) out = attn @ v print(out.shape) # 应为 [2, 8, 64, 32]如果CUDA不可用,检查显卡驱动和CUDA版本是否匹配。CPU也能跑,但训练时间会成倍增加,建议至少用一张8GB显存的卡。
3.2 用ETTh1数据集跑通Informer
ETTh1是时序预测的基准数据集,包含电力变压器的油温数据,每小时采样一次,有7个变量。很多论文都用它做对比,方便你复现结果。
先下载数据放到./dataset/ETT-small/目录下。然后运行:
python run.py \ --model Informer \ --data ETTh1 \ --root_path ./dataset/ETT-small/ \ --data_path ETTh1.csv \ --features M \ --seq_len 96 \ --label_len 48 \ --pred_len 96 \ --e_layers 2 \ --d_layers 1 \ --d_model 512 \ --d_ff 2048 \ --n_heads 8 \ --dropout 0.05 \ --batch_size 32 \ --learning_rate 0.0001 \ --train_epochs 10 \ --patience 3参数说明:seq_len=96表示用过去96小时预测未来96小时。label_len=48是解码器输入的已知部分长度。e_layers=2是编码器层数,d_layers=1是解码器层数。d_model=512是隐藏维度,d_ff=2048是前馈网络维度。n_heads=8是注意力头数。patience=3表示验证集损失3轮不下降就早停。
训练过程中会打印每轮的train loss、val loss和测试指标。正常情况下,Informer在ETTh1的96步预测上,MSE应该在0.4左右,MAE在0.45左右。如果偏差很大,检查数据标准化是否开启、时间特征是否正确拼接。
3.3 切换到Autoformer和PEDformer的注意事项
Autoformer的调用方式和Informer几乎一样,但有几个关键区别:
python run.py \ --model Autoformer \ --data ETTh1 \ --root_path ./dataset/ETT-small/ \ --data_path ETTh1.csv \ --features M \ --seq_len 96 \ --label_len 48 \ --pred_len 96 \ --e_layers 2 \ --d_layers 1 \ --d_model 512 \ --d_ff 2048 \ --n_heads 8 \ --moving_avg 25 \ --dropout 0.05 \ --batch_size 32 \ --learning_rate 0.0001 \ --train_epochs 10多了一个moving_avg参数,这是序列分解的滑动窗口大小。Autoformer默认用25,对应小时级数据的一天周期。如果你的数据周期不同,这个值要调整。比如分钟级数据,周期可能是1440,那moving_avg应该设为1440左右。
PEDformer的参数里多了modes和mode_select,控制频域分解的模态数量。默认modes=64,mode_select='random'。如果数据周期性很强,可以改成mode_select='low',只保留低频分量。
注意:Autoformer和PEDformer的序列分解层会改变张量形状,如果你的
seq_len不是moving_avg的整数倍,可能会在reshape时报错。建议把seq_len设为moving_avg的倍数。
3.4 自定义数据的接入方式
如果你有自己的CSV数据,格式要求很简单:第一列是时间戳,后续列是数值变量。时间戳格式为YYYY-MM-DD HH:MM:SS。把文件放到./dataset/下,然后在data_loader.py里注册:
# data_provider/data_factory.py data_dict = { 'ETTh1': ETTh1, 'ETTm1': ETTm1, 'custom': CustomDataset, # 新增 } class CustomDataset(Dataset): def __init__(self, root_path, flag='train', size=None, features='M', data_path='my_data.csv', target='value', scale=True, timeenc=1): # 复用TimeSeriesDataset的逻辑 # 关键是确保时间戳列能被正确解析 ...如果数据里有缺失值,建议先用线性插值补齐,不要直接填0,否则标准化后会引入偏差。如果变量量纲差异大,标准化是必须的。如果数据有异常值,先做截断或平滑处理。
数据划分比例默认是7:1:2,如果你的数据量小,可以改成8:1:1。验证集的作用是早停和调参,测试集只在最后评估时用一次。
4. 训练与调参中的避坑指南
4.1 损失不下降:现象、原因与解决
现象:训练开始后,train loss在几个epoch内几乎不变,或者下降后很快反弹。
原因:最常见的是学习率设置不当。Transformer类模型对学习率敏感,太大导致震荡,太小导致停滞。其次是数据标准化没做,或者标准化参数用错了。还有一种情况是位置编码和时间特征没有正确拼接,模型拿到的输入缺少时序信息。
解决:先把学习率降到1e-4或5e-5试一轮。检查data_loader.py里的scale参数是否为True,以及scaler是否只在训练集上fit。打印一个batch的输入,确认时间特征维度是否正确。如果用的是Autoformer,检查moving_avg是否和序列周期匹配。
4.2 显存溢出:现象、原因与解决
现象:训练到一半报CUDA out of memory,或者一开始就分配失败。
原因:序列长度或batch size太大。注意力矩阵的内存占用是O(L²),当seq_len=720时,单个注意力矩阵可能超过1GB。另外,某些模型在计算过程中会缓存中间变量,比如Autoformer的分解结果。
解决:先把batch_size减半,如果还不行,把seq_len降到336或192。如果必须用长序列,可以开启梯度累积,用时间换空间。部分模型支持--use_amp混合精度训练,能省30%左右的显存。检查是否有不必要的张量保留在计算图中,比如在验证阶段忘记torch.no_grad()。
4.3 预测结果偏移:现象、原因与解决
现象:模型在测试集上的预测曲线整体偏高或偏低,形状大致对但幅度不对。
原因:标准化和反标准化不一致。训练时对数据做了标准化,预测时忘记用同样的scaler反变换。或者训练集和测试集的分布差异太大,标准化参数不适用。
解决:在评估代码里确认scaler.inverse_transform被正确调用。如果数据分布随时间变化明显,考虑用滑动窗口标准化,即每个输入窗口单独做标准化。但这样会增加计算量,且可能破坏跨窗口的连续性。
4.4 多变量预测中某些变量效果特别差
现象:整体MSE还行,但某个变量的预测几乎是一条直线。
原因:该变量的方差很小,标准化后接近0,模型学不到有效信号。或者该变量和其他变量相关性低,注意力机制没有分配到足够的权重。
解决:检查该变量的数据分布,如果确实变化很小,可以考虑单独建模或去掉。如果变量间相关性低,试试iTransformer或Crossformer这类显式建模变量关系的模型。也可以在损失函数里给不同变量加权,但权重需要根据业务重要性来定。
4.5 不同模型的结果差异很大
现象:同样的数据,Informer的MSE是0.4,Autoformer是0.35,但PEDformer到了0.5。
原因:每个模型的归纳偏置不同。Autoformer的分解机制适合周期性强的数据,PEDformer的频域方法在周期不明显时可能过拟合。另外,超参数没有针对每个模型单独调优,直接套用同一套参数会导致某些模型欠拟合或过拟合。
解决:不要指望一套参数跑所有模型。至少对学习率、d_model、e_layers做网格搜索。如果时间有限,优先调学习率和d_model。记录每个模型的最佳参数组合,后续在新数据上可以直接复用。
5. 进阶技巧:用统一评估框架横向对比15个模型
5.1 统一评估指标与可视化
跑通单个模型只是第一步,真正有价值的是横向对比。我一般会写一个统一的评估脚本,把所有模型的预测结果收集起来,计算MAE、MSE、RMSE,并画出预测曲线对比图。
# utils/evaluate.py import numpy as np from sklearn.metrics import mean_absolute_error, mean_squared_error def evaluate_all(preds_dict, trues, metrics=['mae', 'mse', 'rmse']): """ preds_dict: {model_name: np.array [N, pred_len, features]} trues: np.array [N, pred_len, features] """ results = {} for name, pred in preds_dict.items(): res = {} if 'mae' in metrics: res['mae'] = mean_absolute_error( trues.reshape(-1, trues.shape[-1]), pred.reshape(-1, pred.shape[-1]) ) if 'mse' in metrics: res['mse'] = mean_squared_error( trues.reshape(-1, trues.shape[-1]), pred.reshape(-1, pred.shape[-1]) ) if 'rmse' in metrics: res['rmse'] = np.sqrt(res['mse']) results[name] = res return results这个函数接收一个字典,key是模型名,value是预测数组。trues是真实值。计算时把所有样本和所有预测步展平,得到整体指标。如果你想看每个预测步的误差,可以按pred_len维度分别计算。
可视化部分,用matplotlib画每个模型的预测曲线和真实曲线。重点看几个位置:预测起点、预测中点、预测终点。如果某个模型在终点处误差突然增大,说明长周期依赖没学好。
5.2 用不同预测长度测试模型泛化能力
一个模型在96步预测上表现好,不代表在336步或720步上也好。我一般会跑四组pred_len:96、192、336、720。观察指标随预测长度增加的变化趋势。
| 模型 | pred_len=96 | pred_len=192 | pred_len=336 | pred_len=720 |
|---|---|---|---|---|
| Informer | 0.42 | 0.51 | 0.68 | 0.89 |
| Autoformer | 0.38 | 0.46 | 0.59 | 0.75 |
| PEDformer | 0.40 | 0.48 | 0.62 | 0.80 |
| iTransformer | 0.36 | 0.43 | 0.55 | 0.70 |
上面是一组示例数据,实际数值会因数据集和参数不同而变化。关键看趋势:如果某个模型在720步时MSE暴涨,说明它的长周期建模能力有限。如果下降平缓,说明泛化性更好。
5.3 一个容易被忽略的技巧:验证集的使用方式
很多人把验证集只用来早停,其实它还能帮你判断模型是否过拟合。具体做法是:在每个epoch结束后,分别计算训练集和验证集的loss,画成曲线。如果训练loss持续下降但验证loss开始上升,说明过拟合了,需要加dropout或减层数。如果两者都下降但验证loss始终高于训练loss很多,说明模型容量不够,可以增大d_model或e_layers。
我一般会保留验证集上表现最好的模型参数,而不是最后一个epoch的参数。早停的patience设为3到5,太小容易错过最优解,太大浪费训练时间。
5.4 从跑通到落地:我的几个习惯
跑通15个模型不是终点。真正落地的时候,我会先选2到3个在验证集上表现最好的模型,然后在测试集上做最终评估。如果业务对推理速度有要求,还要测每个模型的单次前向耗时。Autoformer和PEDformer因为分解操作,推理速度通常比Informer慢20%到30%。iTransformer的结构更简洁,推理速度有优势。
另外,我会把每个模型的最佳超参数记录在一个配置文件里,下次在新数据上直接加载,只微调学习率和seq_len。这样能省掉大量重复实验的时间。
最后说一个血泪教训:不要迷信论文里的SOTA。有些模型在ETTh1上刷到了最低MSE,但换到你的数据上可能还不如一个简单的线性模型。先跑通,再对比,最后根据业务指标选型。希望帮到你。
本文还有配套的精品资源,点击获取