Autoformer复现笔记:长序列预测中Transformer的三大瓶颈与解法

发布时间:2026/10/19 12:59:42
Autoformer复现笔记:长序列预测中Transformer的三大瓶颈与解法 如果你也是做时序预测的大概率跟我一样被同一个问题反复折磨Transformer在训练集上拟合得漂漂亮亮可预测窗口一拉到192步以上误差就像漏气的轮胎一样肉眼可见地膨胀。我今年年初读到了Autoformer——一篇把“序列分解”和“自相关机制”整个塞进Transformer结构里的时间序列预测论文之后花了两个周末复现和改代码。今天这篇学习日记就把Autoformer的核心机制、复现时踩过的坑以及它到底擅长处理什么数据一次讲清楚。这篇笔记适合两类人看一是已经在用Transformer做长序列预测、但感觉效果卡在某个瓶颈上的朋友二是刚接触时序预测、想弄清楚“为什么Transformer会被替代”的新手。我不打算复述论文里那些形式化的表述而是按我自己从读论文、复现代码、跑实验到总结边界条件的顺序把Autoformer讲透。1. 为什么读到AutoformerTransformer做时序预测的三道坎先说背景。我手里一个实际项目是短期电力负荷预测数据有很强的日周期和周周期但整体均值还在缓慢漂移。最开始我用标准Transformer训练损失下降得很漂亮验证集也还行可一旦把预测窗口从48步拉到192步误差就明显失控。那段时间我反复调参收益都很有限后来才意识到问题可能不在参数上而在结构上。Transformer处理时间序列时至少有三道坎是绕不开的。第一道坎是非平稳性。负荷数据、气象数据、流量数据均值方差都会随时间漂移。Attention本质上是加权求和对绝对尺度并不敏感但最终输出层要把隐状态映射回真实数值。训练集均值是20测试段均值突然变成25模型在测试段上就会系统性偏低。你可以在输入侧做归一化可一旦预测目标本身的偏移和训练分布不一致模型没有机制去补偿这种偏移。第二道坎是复杂度。Self-Attention是O(L²)的L是序列长度。192步还能忍到720步、960步显存和时间都直接爆炸。之前我做长序列实验单卡跑一个Transformerbatch开到32序列长度1024一个epoch要等很久很久。所以圈里后来的工作很多都在“怎么降低Attention复杂度”上做文章比如把注意力矩阵稀疏化、或者用低秩近似。第三道坎最容易被忽略也是我认为Autoformer真正抓准的地方长序列里最有价值的相关性往往不是局部的而是跨周期的。电力负荷每天同一时刻的形态高度相似这种相关性相隔96步、192步远远超过普通Attention能有效聚合的范围。Attention在理论上能注意到任意两个位置实际上它要在一堆噪声权重中学会“每隔96步就强相关”这种整齐结构需要大量数据而且位置编码也很难表达这种刚性周期关系。我自己做过一个小实验验证第三点。构造一条严格周期为50的合成序列用单层Attention去拟合。结果Attention确实在相隔一个周期的两个位置之间产生了峰值但峰值很浅、很宽对相位偏移特别敏感。同样的数据如果直接算自相关函数周期为50的位置会出现非常尖锐的峰几乎没有歧义。Autoformer的出发点就是这三道坎的交叉点把分解做成模型内部结构应对非平稳把Attention换成自相关机制显式建模周期依赖再用FFT把复杂度压到O(L log L)。这三个改动分别对应了我上面说的三道坎这也是我后来愿意花两个周末去复现它的原因。2. 论文的三大改动逐个拆Decomposition、Auto-Correlation、Series-wise NormalizationAutoformer的核心改动有三个分别解决不同层面的问题。我不按论文里的顺序讲按我理解它们的顺序讲先拆趋势再做周期建模最后处理数据标准化。这三个改动单独拿出来都不算特别新奇但组合在一起就把Transformer做时序预测时的结构性缺陷补上了。2.1 序列分解把趋势和周期拆干净再干活业务数据基本都能拆成三部分趋势、周期/季节、残差。传统做法是在数据预处理阶段用STL或者移动平均先拆一遍把分解结果当成特征送进模型。Autoformer的做法不太一样它把分解做成了模型结构的一部分在每一个Encoder块和Decoder块的入口都做一次分解。为什么要这样做因为一次分解只代表一种分辨率的趋势。你在一开始把趋势全拆掉剩下的“季节项”其实还是混合着不同尺度的周期而Autoformer是每个block都分解出当前层的近似趋势网络越深剥掉的趋势残差越细致。这有点像剥洋葱每层剥掉一层相对光滑的壳剩下的越来越细碎。实现上序列分解层就是一个带padding的移动平均import torch import torch.nn as nn class SeriesDecomp(nn.Module): def __init__(self, kernel_size): super().__init__() self.avg nn.AvgPool1d( kernel_size, stride1, padding(kernel_size - 1) // 2, padding_modereflect ) def forward(self, x): # x shape: (batch, length, channels)先转到 (batch, channels, length) x x.transpose(1, 2) x_trend self.avg(x) x_trend x_trend.transpose(1, 2) x_seasonal x - x_trend return x_seasonal, x_trend这里面有个细节很容易被忽略padding。移动平均的窗口在序列两端会覆盖到不完整区域如果不做特殊处理trend在边界会产生明显跳变。论文用的方式是反射填充效果比零填充稳定很多。我第一次复现时没注意这个细节结果预测序列的首尾偏差明显变大这个坑后面单独讲。移动平均的kernel_size也是个超参数论文里默认是25也就是以25步内的局部均值作为趋势。这个值不是随便定的它跟数据的最小周期尺度有关。如果你数据的最小周期是24比如按小时采样的一天kernel设成25是合理的如果你的数据是按分钟采样、最小周期是60那就得调大。我在后面实验部分会说怎么调。2.2 Auto-Correlation用“回看自己”找到周期替换Attention这是Autoformer最具辨识度的改动——把Self-Attention整个换掉换成Auto-Correlation机制。先说直觉。自相关函数描述的是“一个序列和它自己延迟τ步之后的相关程度”。序列和自身在延迟0处必然最相关如果序列存在周期P那么在τP、2P、3P这些位置相关性会出现峰值。换句话说自相关函数天然能暴露一个序列里隐藏的周期结构。Self-Attention和Auto-Correlation的最大区别在于Attention是逐点的——它计算第i个位置和第j个位置之间的相关性再做加权聚合Auto-Correlation是片段级的——它找出最显著的几个时间延迟把整个序列按这些延迟做循环位移然后把位移后的序列与原始序列做加权聚合。这相当于一次性把“每隔τ步的形态变化”全部聚合起来。实现上Auto-Correlation的计算非常简单根本不需要像Attention那样的Q和K矩阵乘法。它用的是Wiener-Khinchin定理一个信号的自相关函数等于它的傅里叶变换模平方的逆傅里叶变换。用FFT算复杂度是O(L log L)比O(L²)的Attention友好太多。简化理解版本大概是这样的def auto_correlation(x, top_k3): # x shape: (batch, length, channels) # 1. 用FFT快速计算自相关函数 fft_x torch.fft.rfft(x, dim1) corr torch.fft.irfft(fft_x * torch.conj(fft_x), nx.size(1), dim1) # 2. 找到自相关最强的top_k个时延排除0 # 实际代码里还要考虑同一周期下多个延迟的聚合 # 3. 选出的时延记为 delays形状 (batch, top_k) # 4. 对原始序列按每个时延做循环移位 shifted [] for delay in delays: shifted.append(torch.roll(x, shiftsdelay.item(), dims1)) # 5. 用自相关强度作为权重把shifted结果加权求和 return weighted_sum这个代码只是为了示意实际实现还要对多个周期重叠的延迟做聚合。不过核心思想已经表达清楚了找到时延、移位、加权求和。那为什么不直接用频谱分析找主周期、然后按周期重建序列呢因为真实数据的周期往往是非严格的。以电力负荷为例工作日和周末形态不同但又有相似性气温数据受天气影响日周期会被拉伸或压缩。直接按固定周期重建是硬模型稍微偏离就崩。Auto-Correlation仍然是软的它把相关性最高的几个时延挑出来但最后还是学习出来的权重去聚合能容忍周期偏移。把Auto-Correlation和Self-Attention放在一起对比差异就很明显了比较维度Self-AttentionAuto-Correlation依赖类型逐点依赖周期依赖片段级聚合复杂度O(L²)O(L log L)周期发现隐式需要大量数据学习显式通过自相关峰值直接暴露位置先验靠位置编码弱天然支持等距重复结构可解释性弱强能从自相关时延读出周期我在复现时最大的感触是Auto-Correlation学到的东西比Attention可解释得多。训练完打印自相关的top-k时延能直接看到模型找到的周期和你业务上的周期是否一致。这种可解释性在落地项目里非常值钱。2.3 Series-wise Normalization先标准化再预测预测完再还原第三个改动最不起眼但实际提效非常明显叫Series-wise Normalization全局序列归一化。前面说到非平稳性训练段均值是20测试段均值变成25模型就崩。传统的BatchNorm是按特征维度归一化一个batchLayerNorm是对每条样本的所有特征归一化它们都没有针对“每条序列样本自身的时间维均值漂移”建模。Series-wise的做法非常直接对每一条样本序列沿时间维计算它的均值和标准差先归一化再送进模型模型输出预测结果之后把均值和标准差乘回去。def series_norm(x): # x shape: (batch, length, features) mean x.mean(dim1, keepdimTrue) std x.std(dim1, keepdimTrue) 1e-5 return (x - mean) / std, mean, std def series_denorm(pred, mean, std): return pred * std mean就这么几行没有可学习的参数训练和推理都做。为什么这么简单的东西有效因为归一化之后模型学到的是序列的“形状”而不是绝对数值。不同offset的样本在归一化空间里变得可比模型参数就能跨样本共享预测完之后再把均值加回来恢复真实量纲。我在自己的数据上做过对照实验加上Series-wise Normalization长序列预测的MSE差不多能降10%到15%。这个收益不是来自模型结构变复杂而是来自把“去偏置”这个动作从隐式学习变成了显式结构。很多做工程的同事习惯把所有归一化放在数据预处理阶段搞混了训练集和测试集这会导致信息泄漏。Series-wise没有这个问题它每个样本独立统计不跨样本、不跨特征天然安全。3. 我的复现实验结构配置、超参与结果对照看完论文之后我第一反应是“改动挺巧但我自己数据上有没有用还得跑一跑”。我在公开数据集和手头业务数据上都做了复现实验先说配置再说结果。我的复现主要基于论文提供的公开实现思路自己用PyTorch重写没有直接套别人的现成代码。数据用了一个小时粒度的负荷数据集和公开的电耗数据预测长度分别设为96、192、336、720。baseline选了标准Transformer和一个稀疏注意力的变体Informer两个我都调过参尽量让对比公平。关键超参数如下参数取值d_model512n_heads8encoder layers2decoder layers1decomposition kernel_size25batch_size32learning rate1e-4optimizerAdamlossMSE训练epochs60早停patience10插一句Autoformer的decoder结构跟Informer有点像不是直接输入一个prompt就能输出整段预测而是输入一段“start token”——也就是历史序列末尾的一小段再加上未来序列的占位部分用可学习的position embedding填充输出完整预测。这个设计让decoder在预测时能看到一部分真实历史而不是纯自回归地一个点一个点往后滚。复现结果大概是这样我在两个数据集上取了平均表现预测长度TransformerInformerAutoformer960.4120.3980.3611920.4680.4410.3913360.5120.4780.4087200.5960.5420.452数值是我的复现结果不是论文原值但趋势一致预测窗口越短Autoformer的优势越小一旦预测长度超过192优势明显拉开到720步时相对标准Transformer大概有20%左右的MSE降幅。为什么越长越强我的理解是序列越长单个样本里能观察到的完整周期次数越多自相关时延搜索的空间越大分解层能剥出的趋势信息也越多。短序列根本容纳不了几个周期自相关和分解都发挥不出结构性优势。不过也要说清楚Autoformer绝对性能强但不算全面碾压。短窗口预测12步以内场景简单线性模型、梯度提升树甚至差分移动平均都不差跑得还比Transformer快几个数量级。长序列预测、周期结构明显的场景才是Autoformer的主场。4. 复现路上最值得说的三个坑复现一篇论文最花时间的往往不是“把结构搭出来”而是把那些论文没写清楚的工程细节补齐。我在复现Autoformer时遇到三个坑每个都花了不少时间定位写出来给大家避雷。4.1 分解层边界padding首尾点误差直接吃掉MSE第一个坑出现在序列分解层。现象训练loss下降正常但验证loss一直震荡而且预测序列的前几个点和最后几个点的误差明显比其他位置大。我一开始以为是decoder的start token长度设得不对试了很多轮都没解决。排查过程我把分解层的输入输出打印出来发现trend序列在两端出现了很明显的跳变。原因很简单——我用的AvgPool1d默认padding是0窗口滑动到序列两端时实际参与平均的元素变少trend被压扁seasonal项在边界就出现了虚假的突起。用零填充也一样只是位置换了。解法把padding_mode改成reflect让序列在边界按镜像补充。改完之后边界误差立刻降低整体MSE大概改善了0.01到0.02在720步长预测上尤其明显。心得这类“边界效应”在时间序列模型里非常普遍。任何带窗口的算子移动平均、卷积、池化都要认真考虑边界怎么补。论文里一笔带过的东西往往就是复现效果差几个百分点的根源。4.2 top_k时延的选择弱周期数据上Auto-Correlation失灵第二个坑不是bug是适用范围问题。我在一个有周期但不强的数据上测试时发现Autoformer效果不升反降。打印自相关时延后看到模型选出的top-k个时延几乎全集中在很小的值附近基本是τ1、2、3这种相邻延迟。原因自相关函数在没有强周期的序列上会单调衰减最大值必然出现在τ0附近。Auto-Correlation本来想选“最显著的周期时延”但实际选出来的只是“最近的延迟”相当于退化成了一个只看邻近窗口的局部模型长距离依赖反而没抓到。解法我试了两种方案。一种是把top_k参数调小别让模型把权重分配到一堆没意义的相邻时延上另一种是在弱周期数据集上混合使用普通Attention和Auto-Correlation让模型自己判断该用哪种依赖。第二种效果更好一点但实现复杂度也上来了。启示Auto-Correlation强在“周期性”但如果数据本身没有明显的周期性结构这个机制就是空转。论文实验数据大多是负荷、交通、气象这类强周期数据掩盖了这个问题。你在自己的数据上复现之前先算一下自相关函数看看有没有明显的周期性山峰。4.3 Series-wise Normalization的信息泄漏归一化维度搞错第三个坑是最阴间的。现象训练loss正常下降eval loss前期非常低但后期突然上涨而且预测曲线的整体水平老是对不上真实值。我一度以为是模型过拟合了加了dropout、调weight decay都没用。排查过程仔细检查后发现问题出在我把Series-wise Normalization实现成了“整个batch一起归一化”而不是“每条样本单独归一化”。我当时为了省事把归一化的mean和std算在batch维度上这等于在训练时让每条样本“看到”了同batch其他样本的统计信息。模型学会了偷偷利用这种batch统计信息预测未来水平但推理时只有一个样本根本无从参考eval自然崩。解法把mean和std严格按dim1时间维单独计算不跨样本、不跨特征。代码就三行但含义完全不同。这句话不管是做研究还是做工程都适用任何归一化手段都要想清楚它的统计量是在哪个维度上算的。算错了维度轻则效果打折扣重则给出完全虚假的eval指标。5. Autoformer的边界在哪我踩过的两类失败场景复现了一段时间后我对Autoformer的适用边界越来越清晰。它不是一个“哪里都能用”的万能模型用错场景会非常尴尬。5.1 无周期、高噪声数据退化成局部模型有一个数据让我印象很深某类突发事件的发生次数几乎没有任何周期性完全看随机因素偶尔有一点缓慢漂移。拿Autoformer试了一下预测结果基本就是一条接近“上一个值”的水平线比一个简单的last-value baseline还略差。原因就是上面说的自相关函数单调衰减选出来的时延全是小值Auto-Correlation彻底丧失了远距离聚合能力分解层把“趋势”全剥走之后剩下的季节性项其实全是噪声模型学不到任何有效结构。这类数据应该用什么我的建议是如果确认无周期就别用Autoformer这种“周期结构性”模型换成MLP、线性模型或者专门处理非平稳的模型效果可能更好速度也快。5.2 变量间强耦合、时间结构弱只建模时间维度不够另一种失败场景是多变量数据。Autoformer的核心改进都在时间维度的结构上变量之间的关系仍然靠Transformer原始的注意力机制来建模。如果数据的变量之间有很强的物理耦合性——比如传感器网络里某个点位的数值由其他几个点位的数值决定——那么Autoformer的表现就一般。这不是Autoformer的错而是它设计时的侧重点不同它的注意力机制主要用在时间语境中即使有多维或多通道输入主要被当作类似通道的组合来使用。纯粹的时序建模和变量关系建模是两回事。我后来在思路里留下的判断标准是先看数据在三个维度上的特征——有没有周期性、有没有趋势漂移、变量间是强耦合还是弱耦合。如果在“周期性”和“漂移”上是强特征Autoformer值得优先尝试如果主要是变量间关系强那应该先考虑变量建模方向如果三者都弱简单模型就够了。数据特征Autoformer适配度强周期 趋势漂移 长预测窗口非常适合周期弱 短窗口不推荐强变量耦合 弱时间结构一般需额外设计无周期高噪声基本无效6. 最后几句闲话Autoformer给我最大的收获不是它在长序列预测上比Transformer好了多少而是它示范了一种思路把业务领域里已经很成熟的先验知识——序列分解、周期相关性、非平稳归一化——想办法变成神经网络结构的一部分而不是把它们当作外部数据预处理。我自己以前很喜欢堆结构、调参、换损失函数但效果总是不稳定。复现Autoformer之后我才意识到模型结构的每一块都应该对应一个具体的“为什么”这个模块到底帮模型解决了哪个偏差如果回答不上来这个模块大概率只是热闹。Autoformer的三个改动每一个都能对应上我开头说的三道坎这种“结构服务于问题”的清晰感比它带来的准确率提升更值得学习。如果你也想复现一篇类似的时序论文我的建议是先别急着抄代码把同样思路用在自己的数据上算一下自相关函数画一下趋势分解图确认这个模型解决的是不是你要解决的问题。如果数据没有周期硬套Autoformer只会得到一个漂亮但没用的模型。反过来如果你的数据和负荷预测一样有明显周期和漂移那Autoformer是值得放进候选列表的头号选手。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询