简介:基于Transformer的长时间序列预测与分类算法代码合集,涵盖Autoformer、Informer、PEDformer、Crossformer、TimesNet、DLinear等十五个主流时间序列模型,并配套电力负荷、ETT油温、外汇汇率、病情变化、交通车流量、天气观测等真实数据集。面向需要复现或对比不同Transformer变体性能的研究者、算法工程师与竞赛选手,可减少从零搭建与调参成本,快速完成多模型实验。压缩包共一千三百七十八个文件,约一百八十二点二MB,以PDF论文说明、Shell训练脚本、Python核心代码、npy与CSV数据文件为主,另有少量可视化图片和Notebook示例。目录按算法模块组织,已有三千四百六十七人浏览学习。包内除了各模型训练推理脚本,还包含数据预处理流程、超参数配置、环境依赖说明与实验日志,适合直接修改数据路径后运行测试,也可以对照PDF内容理解各算法的设计动机与适用差异,显著缩短基线对比和环境配置时间。
1. 长时间序列预测的“长”是把双刃剑:15个Transformer变体到底在解决什么
Transformer在长序列预测上有个反直觉的短板:序列越长,自注意力越记不住远期信息,因为每个位置要和所有位置算相似度,长度一上来,注意力权重就被均摊。长时间序列预测(LTSF)恰恰要求模型记住几百步之前的周期与趋势,这就是 Autoformer、PEDformer、Informer 这些变体扎堆的理由——它们不是推翻Transformer,而是改注意力的计算方式。这份15个算法代码汇总的价值在于把训练、评估、预测统一成一套命令行入口,你不用为每个模型重写数据处理和评估脚本。适合做电力负荷、交通流量、气象预报、金融日频预测的从业者拿来当基线对比和调参起点。
2. 拿到代码包先做三件事:环境、数据格式、跑通最小demo
2.1 为什么是这15个模型:按注意力机制给算法分组
标题里提到的“15个算法”,落到代码包里通常就是models/目录下每个子目录一个模型类。先别急着跑,把这十几个模型按注意力怎么改分成四组,后面调参才有方向。
| 分组 | 模型 | 核心改动 |
|---|---|---|
| 稀疏注意力 | Informer、Pyraformer | 减少参与注意力计算的query/key数量,Informer用ProbSparse采样,Pyraformer用金字塔多尺度图 |
| 分解与自相关 | Autoformer、ETSformer | 把原始序列先拆成趋势项和季节项,Autoformer用自相关替代attention做周期匹配 |
| 频域 | PEDformer、FiLM | 变换到傅里叶频域后只保留部分频率分量做注意力,长周期信号在频域更稀疏 |
| 分块 | PatchTST、Crossformer、LightTS | 把输入序列切成patch再编码,支持更长输出 |
| 分布修正 | Nonstationary Transformer | 先反平稳化再平稳化,缓解训练和测试分布漂移 |
| 基线 | DLinear、SCINet、TimesNet、Triformer、Vanilla Transformer | 线性或非Transformer结构,用来验证Transformer是否真的有增益 |
这六组的调参入口完全不同:稀疏注意力组先看采样比例,频域组看频率阶数,分块组看patch长度。如果把PEDformer当Informer调,大概率改半天找不到头绪。
2.2 环境与仓库结构:从requirements到运行入口
这类汇总代码包的环境不复杂,Python 3.8或3.9、PyTorch 1.13左右就够,再加 numpy、pandas、scipy、sklearn、matplotlib。装的时候别一把梭,常见做法是先建一个干净的虚拟环境,再按requirements装。
# 建立虚拟环境并激活,隔离依赖 python -m venv venv && source venv/bin/activate pip install torch==1.13.1 pip install numpy pandas scipy scikit-learn matplotlib第一行建虚拟环境并激活是隔离依赖,避免和机器上其他项目冲突;第二行装torch,老代码包用1.13最稳,2.x也能跑但偶尔有接口变动,遇到兼容报错就降回1.13;第三行是通用数据科学库。如果你的汇总包自带requirements.txt,直接 pip install -r requirements.txt 也行,但torch那行单独装更可控。
目录结构只看这几个位置就够了:data/ 放整理好的CSV数据集;models/ 是15个模型的实现;run.py 是所有实验的统一入口;scripts/或experiments/ 里是论文复现shell脚本,里面带着每个数据集和模型的推荐参数,是调参第一参考。装完先检查入口:python run.py --help,如果能打印参数说明,说明环境基本通了。
2.3 最小复现:用ETTh1跑通Informer的训练和结果输出
确认环境后,第一次跑通不要追求精度,用最短命令验证全链路。以Informer和ETTh1为例,最小训练命令长这样:
# 最小复现命令:先保证数据读取、训练、保存、测试链路全部通 python run.py \ --model Informer \ --data ETTh1 \ --features M \ --seq_len 96 \ --label_len 48 \ --pred_len 168 \ --d_model 512 \ --n_heads 8 \ --e_layers 2 \ --d_layers 1 \ --dropout 0.05 \ --learning_rate 0.0001 \ --batch_size 32 \ --train_epochs 10 \ --patience 3 \ --seed 2024各参数含义:--model选算法名;--data指定数据集,代码包内置ETTh1/ETTm1等名称;--features M表示多变量输入多变量输出,S是单变量,MS是多变量预测单变量;--seq_len是回溯窗口96小时,--label_len是decoder起始提示长度48,--pred_len是预测未来168小时。--d_model和--n_heads是Transformer核心维度参数,ETTh1这种7通道数据,512和8是Informer论文的典型搭配。--patience是早停轮数,验证集连续3轮不降就停。
这行命令在单卡上大约十几分钟能跑完。跑完看输出:程序会打印best valid loss、test MSE、test MAE,并生成结果文件。数据流是:data_loader按seq_len+label_len+pred_len切窗口,encoder吃前96步,decoder吃48步真实值拼接接下来168步的占位,输出重建,MSE在反归一化后计算。
验证一下训练结果是否真的能用,跑一次测试模式,--train_epochs设为0,表示跳过训练直接加载已有checkpoint:
# 测试模式:仅加载训练好的模型,输出测试集MSE/MAE python run.py \ --model Informer \ --data ETTh1 \ --features M \ --seq_len 96 --label_len 48 --pred_len 168 \ --d_model 512 --n_heads 8 --e_layers 2 --d_layers 1 \ --dropout 0.05 --learning_rate 0.0001 --batch_size 32 \ --train_epochs 0 --seed 2024能否跳过训练取决于checkpoint是否存在于包内预设的结果目录,如果上次训练被patience提前终止,模型也会保存。test模式不仅打印指标,还会把预测结果存成pred.npy和true.npy,后续可视化全靠这两个文件。第一次跑通后不要急着换模型,先理解这一条链路:数据读取、窗口切分、训练、保存、测试、输出,15个算法全都复用这套流程。
3. 数据预处理与实验协议:从ETT到自定义数据的边界
3.1 ETT数据集为什么是默认选择
ETT(Electricity Transformer Temperature)系列是这类代码包的默认数据集,它来自电力变压器,包含油温OT和6条外部负载数据,7列数值字段,小时级(ETTh1/ETTh2)和15分钟级(ETTm1/ETTm2)两种粒度都有。选它当默认实验集有三个原因:第一,均匀采样、无缺失值,免去数据清洗环节;第二,有明确的周期性和趋势漂移,能区分模型捕捉周期能力的好坏;第三,规模适中,单卡几分钟到半小时出一个结果,适合快速对比。
ETT的官方划分协议通常是train/valid/test按12/4/4比例顺序切分,也就是前60%训练、20%验证、20%测试。注意是严格按时间顺序切,绝不随机。有些汇总包会改成6/2/2,跑对比实验时先看一眼包里的默认划分,所有模型用同一套就行。评估指标默认是MSE和MAE,MSE对离群点敏感,MAE更贴近业务平均误差,报告结果时两个都留。
数据文件的标准形态是CSV,第一列是日期时间,后面是数值特征。ETT的时间戳格式类似2016-07-01 00:00:00,其余列是浮点数。如果你的数据时间戳不是统一间隔,代码包的data_loader一般会报错或对齐失败,这一点在下一节展开。
3.2 换自己的数据:CSV格式、归一化和滑窗参数
自己业务数据接入这套代码,核心是CSV格式对齐。常见做法是先把数据整理成两列以上的表:第一列时间戳,格式固定为YYYY-MM-DD HH:MM:SS;后面每列一个数值特征。缺失值先处理,线性插值在绝大多数场景够用,突变性的缺失用前向填充更稳妥。
归一化是这里最容易出错的一步。很多包的DataLoader里内置了StandardScaler,但标准化参数必须只在训练集上fit。手动处理时,正确写法是先按时间顺序切分,再fit训练段:
import pandas as pd from sklearn.preprocessing import StandardScaler df = pd.read_csv('my_data.csv', parse_dates=['date']) train_df = df.iloc[:int(len(df)*0.6)] valid_df = df.iloc[int(len(df)*0.6):int(len(df)*0.8)] test_df = df.iloc[int(len(df)*0.8):] scaler = StandardScaler() # 只对训练段fit,测试段的分布信息不能混进mean/std scaler.fit(train_df.drop(columns=['date']).values) for split in (train_df, valid_df, test_df): values = split.drop(columns=['date']).values scaled = scaler.transform(values) # 保存成包内data目录要求的CSV格式逻辑说明:先按时间顺序把原始表切成三段,然后只对训练段fit得到mean和std,再对三段分别transform。这样保证验证集和测试集的分布信息不泄漏进归一化参数。有些新手把全量数据fit一遍,测试集MSE会虚低,换到线上就出问题。
滑窗参数决定模型的观测视野:seq_len是看多长历史,pred_len是预测多远,label_len只对带decoder的模型有意义。常见比例是seq_len=pred_len×2,比如pred_len=168时seq_len=336。窗口数量等于总长度减去seq_len+pred_len(对decoder模型还要减去label_len),数据太短时优先缩短seq_len而不是pred_len。
3.3 模型统一入口:run.py的六个必传参数
所有模型共用run.py,理解这六个必传参数,就能控制任意一个实验:
| 参数 | 作用 | 典型值 | 影响 |
|---|---|---|---|
| --model | 选择models/目录下的模型类名 | Informer / Autoformer / PEDformer / PatchTST / DLinear | 决定网络结构和可调超参 |
| --data | 选择data/下的数据集名 | ETTh1 / ETTh2 / ETTm1 / 自定义名 | 决定数据文件读取路径和窗口总数 |
| --features | 输入输出结构 | M / S / MS | M多变量到多变量;S单变量到单变量;MS多变量到单变量 |
| --seq_len | 输入序列长度 | 96 / 336 | 越大历史信息越足,但计算量和显存上涨 |
| --label_len | decoder的提示序列长度 | 48 / 96 | 只对Informer/Autoformer/PEDformer等带decoder的模型有效 |
| --pred_len | 预测序列长度 | 168 / 336 / 720 | 越大误差越高,显存占用越高 |
六个参数中,pred_len对结果的影响最大。预测跨度从168拉到720,所有模型误差都会上涨,差异在于谁涨得慢。线上决定pred_len时不要拍脑袋,看业务提前期需求,同时准备两个档位对比。
这里还有两个容易被忽略的参数:--itr表示重复实验次数,取3时程序会连跑3次并输出均值方差,论文里常用3或5,日常调试取1就够了;--use_gpu默认等于True,多卡机器上--use_multi_gpu配合--devices指定卡号,单卡不用管。调PEDformer这类模型时,先把这六个参数固定,只动它的频域超参,否则换了模型又换数据,出了问题不知道怎么归因。
4. 分组跑15个算法:按预测长度做精度对比的策略
4.1 按预测长度对比:168、336、720三档怎么跑
15个模型逐个调参不现实,常见做法是固定数据集、固定seq_len=96,只改pred_len,三个档位各跑一遍。这一轮的价值不是刷SOTA,而是看模型在预测长度变长时误差是否失控。脚本化跑批量实验:
for model in Informer Autoformer PEDformer PatchTST DLinear; do for pred_len in 168 336 720; do python run.py \ --model $model \ --data ETTh1 \ --features M \ --seq_len 96 \ --label_len 48 \ --pred_len $pred_len \ --d_model 256 \ --n_heads 8 \ --e_layers 2 \ --d_layers 1 \ --dropout 0.05 \ --train_epochs 10 \ --patience 3 \ --seed 2024 done done这个脚本会依次跑Informer的168/336/720,然后Autoformer、PEDformer、PatchTST、DLinear,共15次实验。d_model统一设256,是为了在一个不算大的容量下公平对比,论文复现时的推荐参数可以后续再逐个替换。跑完把每个模型的test MSE/MAE记录到表格,就能看到:哪个模型在720档的误差同比上升最少。
注意:批量实验建议先只跑168档确认链路正常,确认每个模型的命令行参数都齐全后再放720档过夜,省得睡醒发现PEDformer因缺频域参数中途报错。
跑完一轮对比大约需要几个小时。中间任何一次失败不会中断整个循环,但输出日志要看,常见失败原因是PEDformer或Autoformer需要额外参数没提供,比如频域类模型在部分包里要求--n_order、--mode_index等参数存在,命令行带少了会直接报错。所以第一次跑PEDformer之前,先看包里它的default参数列表。
4.2 误差区间与模型定位:别只看MSE一个数
同一份ETTh1数据上,不同模型组的误差表现有比较清晰的分层,理解这个分层比记住数字有用。Autoformer和PEDformer靠自相关或频域分解,在336和720档位通常能保持相对低的MSE,因为长周期信号被显式建模了。PatchTST在patch_size合适时误差很稳,尤其是720档,它把序列切成小块后由编码器直接映射到长输出,不依赖长长的decoder。Informer在中短期比如168档有速度优势,到720档误差涨得比分解类快。DLinear在ETT这类强周期数据上往往不输给大多数Transformer,这是正常现象,不是代码有问题。
如果你跑出来的相对趋势和上面相反,比如PEDformer在720档比DLinear还差一大截,优先排查两件事:一是频域参数是不是被改过,二是归一化是否泄漏。很多人在这时候开始怀疑模型没有意义,其实先跑满一轮再下结论。出现方向异常时,下一步不是继续调参,而是去看每个模型在验证集上的loss曲线有没有震荡,震荡通常意味着学习率过大或数据切分有问题。
记录实验结果时,MSE、MAE之外,把每个模型的训练时间、显存峰值、参数总量一起记。线上选型时,精度差0.01但推理时间长一倍,对生产不一定划算。训练时间是调参的硬约束,Informer在ETTh1上一个epoch大约半分钟以内,PatchTST更快,Autoformer因为有自相关计算会慢一些。
4.3 结果可视化:把pred和true拼成一条曲线
数值表看不出预测错在哪,可视化能。跑完测试后,包里会在结果目录输出预测值和真实值的numpy数组,直接用它们画长序列对比图:
import numpy as np import matplotlib.pyplot as plt pred = np.load('pred.npy') # 形状 [样本数, pred_len, 特征数] true = np.load('true.npy') # 每个预测窗口取最后时间步,拼接成连续曲线 pred_series = pred[:, -1, 0] true_series = true[:, -1, 0] plt.figure(figsize=(12, 4)) plt.plot(true_series[:500], label='True', linewidth=1.2) plt.plot(pred_series[:500], label='Pred', linewidth=1.2, alpha=0.8) plt.legend() plt.title('ETTh1 OT prediction') plt.tight_layout() plt.savefig('pred_vs_true.png', dpi=150)逻辑说明:pred.npy的维度是[窗口数, 预测步长, 特征数],不要直接把它当连续预测曲线来画,那会输出很多平行线段。取pred[:, -1, 0]意思是每个窗口只取最后一步预测,再把所有窗口拼起来,得到一条等长于测试集的连续预测线。第0个特征对应ETT里的OT油温,这是业务最关心的保护对象,也是普遍预测误差最小的字段。
看这张图有几个判断要点:如果Pred曲线在波峰处整体偏低,模型在低估峰值,常见原因是MSE对离群峰值惩罚太重,模型学会了求稳;如果Pred相对True滞后几个点,序列对齐或滑窗切分可能有问题;如果Pred几乎是一条水平线,模型把所有波动都平均掉了,大概率特征学习没有起效,先检查标签是否被误归一化。作图时画500个点足够暴露问题,画全部上万点反而看不清细节。
5. 调参与避坑:长时间序列Transformer的5个常见坑
5.1 数据泄漏与标签长度:两个隐蔽的设置错误
第一个坑:归一化泄漏。现象是验证集和测试集MSE低得可疑,比论文结果还好,但拿到新数据预测时误差暴涨。原因多半是数据预处理里用全量数据的均值和标准差做了StandardScaler。解决方法是严格按3.2节的顺序:先切分再fit训练段。检查方式也简单,打印scaler.mean_和scaler.var_,再手动算一下训练段的均值和方差,对不上就有泄漏。
第二个坑:把label_len当成预测长度。现象是有人把--label_len设为和--pred_len一样甚至更大,然后发现Informer等模型显存翻了倍,训练变慢。原因在于label_len是decoder输入中真实观测部分的长度,不是要预测的步数;它给decoder提供“最近一段真实值”作为起始提示,常见做法是seq_len的一半,也就是96配48。解决方法是固定label_len=seq_len/2,只有做消融实验时才单独动它。PatchTST和DLinear不接收label_len参数,传了也会被忽略,不用奇怪。
5.2 显存与超参:pred_len和d_model怎么定
第三个坑:pred_len拉长后显存溢出。现象是pred_len从168改成720,直接OOM。原因是带decoder的模型(Informer、Autoformer、PEDformer)在解码阶段一次性生成整个pred_len长度的序列,显存占用随预测长度线性甚至更陡地增长。解决顺序是:先调小batch_size到16或8;再把seq_len同步调大,给encoder更多上下文;还不行就换PatchTST这类纯encoder输出长的模型。注意batch_size调小后要同步把learning_rate略降,不然梯度噪声变大,loss会震荡。
第四个坑:d_model在小数据集上盲目用512。现象是训练loss下降很快,验证loss却抬升,典型过拟合。原因很简单,ETTh1只有7个特征,d_model=512意味着embedding层把7维映射到512维,参数大量冗余。解决方法是d_model设为128或256起步,观察验证loss不再下降再升到512。对比实验里所有模型都用同一d_model才公平,这一点在批量跑脚本时尤其要记住。
5.3 PEDformer频域参数:调坏之后的排查思路
第五个坑:PEDformer的频域参数被乱调后性能暴跌。现象是PEDformer跑出来的MSE比DLinear还高出一大截,但没改参数之前明明正常。原因多半是动了n_order或mode_index一类的频域分量参数。PEDformer把序列变换到傅里叶域后,只保留若干个频率分量做注意力,n_order控制保留的模态数量,mode_index控制分量选择范围。调小n_order会丢掉信息,调大会引入噪声,而且这两个参数的合理区间和seq_len、pred_len耦合,不能单独拍脑袋。
解决方法是:先恢复默认值(常见是n_order=3,mode_index按包内默认的0到某个范围),确认模型回到基线;再逐个变量改回去,看到底是哪个参数导致劣化。排查用频谱图最直观:把输入序列做FFT,看能量集中在哪几个频率上,n_order应该覆盖能量峰值附近的分量个数。如果你在models目录里找不到PEDformer.py,多半文件名写的是FEDformer.py,命令行 --model 传和类名一致的那个即可。这一步是典型的参数玄学现场,但只要回到默认再逐个变量验证,就能定位到原因。
6. 进阶验证:用DLinear做消融,判断误差来自模型还是数据
6.1 为什么必须跑一遍DLinear
15个Transformer跑完,最后一定要补跑一次DLinear。它只有两层线性映射,训练一分钟内出结果,却是判断工作方向的关键指标:
# 线性基线:验证Transformer在这份数据上是否真的有增益 python run.py \ --model DLinear \ --data ETTh1 \ --features M \ --seq_len 96 \ --label_len 0 \ --pred_len 168 \ --train_epochs 10 \ --patience 3 \ --seed 2024如果DLinear的MSE和Informer接近甚至更好,直接说明这份数据的预测主要靠线性趋势和周期叠加,注意力结构带来的边际收益有限,继续调Transformer的隐藏层不如去补特征工程或外部变量。如果PEDformer和PatchTST显著低于DLinear,说明数据里确实有Transformer能抓住的非线性时序关联,继续深挖才有价值。有人拿合成正弦数据测试,所有Transformer都能把周期拟合像样,一旦换成突变和缺失较多的工业数据,差距立刻拉开。真实项目先看数据形态,再决定投入哪类模型。
6.2 三个验证技巧:多随机种子、分通道误差、分段误差曲线
验证模型稳定性,单跑一次不够。把同一组参数换seed跑五次,取MSE均值和标准差再下结论:标准差大于均值10%,基本可以判定训练不稳定,优先排查学习率和数据切分;跑五次不用改代码,循环改seed即可。
第二个技巧是分通道误差。ETT有7列特征,全局MSE掩盖了单通道差异。把pred和true按特征维度分离,逐列算MSE:通常OT油温误差最小,负载类特征误差大;如果反过来,说明数据预处理里某列的特征顺序已经错位。第三个技巧是分段误差曲线,对pred.npy按预测步长维度取平均,画误差随前进步数的曲线:误差在第30步以后快速上升,说明模型只学会了短期延续;误差全程平稳,说明预测长度还可以继续拉长,业务提前期可以设得更长。
我自己的习惯是每个项目先跑DLinear,再跑一个最强的Transformer,两者差距决定了后续调参投入。以前为了在ETTh1上把720档指标刷高,我曾把PEDformer的频域参数改到面目全非,结果换到真实业务数据上完全失效,后来老老实实从基线做起,用上面这套验证流程把大量时间省了回来。希望这套验证路径也能帮到你。
本文还有配套的精品资源,点击获取