Mamba这个名字,做序列建模的人应该都不陌生。2024年它几乎成了“Transformer替代者”话题里曝光率最高的模型之一,各种论文都在往Mamba上靠。但做时间序列预测的人,心里大概率会有一个更务实的疑问:Mamba的声势再大,真的对时序预测有效吗?这篇论文的标题恰好就问出了这个问题——Is Mamba Effective for Time Series Forecasting?
这篇论文不是 Mamba 的宣传稿,而是一次系统性的评估。作者团队在多个真实数据集上,把 Mamba 和几类有代表性的预测模型放在同一个框架下做了对比,还专门设计了三组敏感性实验,回答三个非常关键的问题:位置信息对 Mamba 到底有多重要?状态维度设置影响有多大?训练长度和推理长度不一致时它还靠不靠谱?如果你正在做时间序列预测,或者正考虑把 Mamba 引进自己的模型里,这篇论文值得花时间细读。它能帮你避开不少隐形的坑,也能让你更清醒地意识到一件事:Mamba 的“线性复杂度优势”和“对时间序列有效”根本是两回事。
1. 这篇论文到底在回答什么问题
1.1 Mamba 凭什么被拿来和 Transformer 比
先花半分钟聊背景。Transformer 在时序预测上的主要问题来自自注意力机制:序列越长,注意力矩阵越大,计算复杂度是平方级增长。虽然 PatchTST 这类工作通过“切 patch 再跑注意力”降低了 token 数量,但本质上还是在吃注意力。
Mamba 的思路完全不同。它属于状态空间模型(SSM),核心操作是“选择性扫描”:每个输入 token 经过一个隐藏状态更新。可以用一个极其简化的公式来理解:
h_t = A h_{t-1} + B x_t y_t = C h_t其中 A、B、C 不是固定的权重,而是根据输入动态生成的,所以叫“选择性”。直观地说,它像一个边走边记笔记的人,只把当前最重要的信息写进脑子里,不需要回头翻所有走过的路。计算复杂度和序列长度线性相关,跟 Transformer 的 O(N²) 自注意力相比,确实有吸引力。
有人可能会想:语言模型里 Mamba 表现不错,时序预测不也是序列任务吗?换个壳子应该也强。这个想法的漏洞在于,时间序列和文本有几个本质差异。文本有明确的词法和语法结构,时间序列的“信号”却分散在幅度、频率、趋势、噪声里;文本的 token 是离散符号,时序数据是连续数值;文本任务通常有大规模预训练,时序预测大多是从零开始训练。这些差异决定了 Mamba 在 NLP 里的优势未必能简单复制到时序任务上。论文要做的,就是把这类理所当然的假设一条条拿去实测。
1.2 论文的实验设计思路
论文的实验设计很清晰,就两条线。第一条线是“对比”。作者把 Mamba 拆成三种配置:原始 Mamba、加入位置嵌入的 Mamba(Mamba+PE)、以及一个增强版本 S-Mamba(线性映射 + Mamba 块 + 残差连接)。然后拿它们和多个有代表性的基线比,包括线性模型、PatchTST、iTransformer 等,在多组真实数据集上做评估。
第二条线是“剖析”。论文不满足于报告谁赢了,而是专门设计了位置敏感性、数值敏感性、长度敏感性三组实验,去解释“为什么这个模型会赢,在什么条件下会输”。这种“先 PK,再拆解”的思路本身就是很好的论文模板。很多人做实验只关心最终排名,忽略了结论成立的条件,而这篇论文最有价值的地方恰恰就是那些条件。
2. 模型配置与评估设置
2.1 数据集与预处理
论文用了多个公开数据集,基本覆盖了常见的时序场景:ETT 系列(电力变压器温度,有 1 小时和 15 分钟两种粒度)、Electricity(电力负荷)、Traffic(交通占用率)、Exchange(汇率)、Weather(气象)、Solar-Energy(太阳能)等。这些数据集有周期性强弱之分、通道数多少之分、噪声水平高低之分,预测长度一般取 96、192、336、720 这几个档位,属于长时预测任务比较标准的设置。
为什么选这些数据集?因为它们干净、公开、对比公平,而且跨度够大。从 15 分钟颗粒度的 ETT 到 1 小时颗粒度的 Weather,再到带大量相关通道的 Traffic,基本把时序预测里最常见的形态都覆盖了。这里有一个容易被忽略的点:数据集通道数差异极大。比如 ETTh1 只有 7 个通道,Traffic 却有 862 个通道。通道数的差异会影响模型对“跨通道依赖”的建模方式,也会直接影响 Mamba 以 token 方式处理输入时的效率和效果。
| 数据集 | 特点 | 与 Mamba 评估相关的点 |
|---|---|---|
| ETTh1 / ETTm1 | 变压器油温,周期性强 | 适合观察位置敏感性和周期特征 |
| Electricity | 电力负荷,通道多,趋势 + 周期 | 高通道数下对多变量建模能力 |
| Traffic | 交通占用率,通道数多 | 大规模通道、强周期模式 |
| Exchange | 汇率,非平稳性强 | 数值尺度变化对模型的冲击 |
| Weather | 气象多通道 | 噪声多,多尺度模式混合 |
| Solar-Energy | 太阳能功率 | 夜间接近零,动态范围大 |
2.2 基线模型与实现细节
论文选择基线的标准是“代表不同类型”,而不是“所有能跑的模型都来一遍”。几个关键基线刚好代表四条技术路线:
- DLinear / NLinear:极简线性层。它们在近两年证明了“复杂模型在时序预测上没那么神”,是很好的参考基准。
- PatchTST:基于 Transformer,用 patch 降低 token 数量,在长时预测上表现出色。
- iTransformer:Transformer 的改进版,把注意力的维度从时间步换到变量维度,专门强化多变量相关性建模。
Mamba 这边论文用了三种设置:一是“裸 Mamba”,直接把 patch 后的 token 序列喂给 Mamba 层,不加任何位置信息;二是“Mamba + PE”,在 patch token 上加入可学习位置编码;三是“S-Mamba”,先做线性投影,再进 Mamba 块,用残差连接,最后通过线性层把隐藏表示映射到预测窗口。
这里有一个需要特别留意的细节:Mamba 在架构上天然不依赖绝对位置编码,因为它通过顺序扫描隐性记住了输入次序。但时序预测里的“位置”不只是顺序,它还承载着“离预测点越近的信息越重要”这种先验知识。所以位置编码在时序任务里不是可有可无的装饰,论文后面的敏感性实验会专门证明这一点。
2.3 评价指标与统计口径
论文使用 MSE 和 MAE 两个常规指标,最终结论基于“平均排名”。平均排名的含义是:在每个数据集、每个预测长度下,把模型按 MSE 从小到大排序,再取所有配置下的平均名次。这样做比只看一两个数据集更能反映整体稳定性,也避免“在某个数据集上刷出极低 MSE,其他数据集全部崩掉”的情况。
这里值得多说一句公平性。时序预测论文的对比很容易不公平:不同模型的参数量不一样,patch 长度不一样,训练轮数不一样。论文采用统一复现框架,把各模型的 patch 长度、batch size、学习率等尽量对齐,同时保留每个模型的最佳配置搜索。这种处理方式很务实。完全统一所有超参,反而会误伤某些模型;完全自由搜索,又会让对比失去意义。按“保持兼容 + 小范围搜索”来平衡,是比较合理的实验策略。
3. 三组敏感性实验:Mamba 到底稳不稳
3.1 位置敏感性:把输入 token 顺序打乱会怎样
我读这篇论文时觉得最有趣的实验就是位置敏感性。做法很简单:把输入序列切成 patch 后,随机打乱 patch 之间的顺序,再喂给模型做预测。如果模型的预测结果没有明显变化,说明它对顺序信息不敏感;如果预测结果大幅恶化,说明顺序信息很重要。
结果非常明确:打乱顺序后,Mamba 的性能明显下降,尤其是单变量预测。这说明“Mamba 不需要位置编码”这个说法在时间序列任务上要打折扣。Mamba 虽然通过递归扫描记住了顺序,但它对“哪个 token 离预测点更近”这种重要性权重的建模,仍然需要额外位置信号的配合。加入位置嵌入之后,Mamba 在单变量场景的预测误差明显降低。而在多变量高通道数据集上,位置编码的作用会弱一些,因为多变量场景的主要增益来自跨通道交互,而不是时间顺序本身的编码。
实操上的启发是:如果你的数据通道少、序列长度中等,直接使用“裸 Mamba”可能有风险,建议加上可学习位置编码,或者直接使用 S-Mamba 这种带线性投影的结构。
3.2 数值敏感性:状态维度与数值精度
第二个敏感性实验盯的是 Mamba 的核心参数——状态维度,也就是状态空间模型里隐藏状态向量的维度,一般用 d_state 表示。论文实验表明,提高 d_state 通常能带来一致的性能提升。原因不难理解:更大的状态空间可以记住更多历史模式,相当于把“小笔记本”换成“更厚的笔记本”。
但代价同样现实。更大的 d_state 会让计算量和显存占用上升,训练速度明显下降。结合论文的观察和复现经验,在常规长序列数据集上,d_state 设为 16 到 32 之间是性价比比较高的区间,再往上涨对精度的边际收益就很低,效率损失却不小。
另一个容易踩坑的点是数值精度。Mamba 的实现依赖顺序扫描,里面的矩阵运算是逐时间步递推的,无法像 Transformer 那样把整条序列的注意力一起并行。在 fp16 或 bf16 混合精度训练下,长序列的误差累积会更明显,可能出现 loss 不降、预测输出全部变成常数的现象。我在复现时就遇到过类似情况。解决办法是让关键层维持 fp32,或者直接使用带融合内核的实现,不要用朴素的循环版本去做长序列实验。
3.3 数据长度敏感性:训练短预测长还灵吗
长时预测里经常出现“训练时用的历史窗口比较短,推理时却要处理更长的输入”的情况。论文专门测了长度外推:固定一个训练输入长度,测试时改成更长或更短的输入长度,观察哪些模型能扛住。
结果很直接:Mamba 对这种长度不匹配非常敏感。训练长度和推理长度一致时性能正常,一旦推理时把输入序列拉长,误差显著上升,不如线性模型和 Transformer 那样有一定外推能力。用一句话概括这个现象:Mamba 的状态容量在设计时就适配了训练时的序列长度,遇到更长的输入,状态会被“撑破”,没法自然延展。
这个结论直接影响使用场景选择。如果你的生产环境里历史窗口经常变化,Mamba 可能需要重新训练,或者要在输入侧做额外处理。反之,如果训练推理阶段的输入长度和预测长度都是固定的,这个缺点就不再是问题,长序列场景反而能发挥它的复杂度优势。
4. 结果综述与关键结论
4.1 总体取胜:平均第一,但不是全面碾压
论文报告了各模型在多个数据集、多个预测长度下的 MSE / MAE 与平均排名。大致来看,S-Mamba 在总平均排名上是最好的,Mamba+PE 次之,裸 Mamba 也能排到中上,但优势在不同的数据集上并不一致。我按论文代表性结果整理了一张粗略对比表,数字是约值,具体以原文为准:
| 数据集 / 预测长度 | DLinear | PatchTST | iTransformer | S-Mamba |
|---|---|---|---|---|
| ETTh1-720 MSE | 0.43 | 0.41 | 0.39 | 0.39 |
| Electricity-96 MSE | 0.20 | 0.19 | 0.17 | 0.17 |
| Traffic-96 MSE | 0.42 | 0.39 | 0.37 | 0.36 |
单看这个表可能觉得差距不大,但趋势是对的:Mamba,尤其是 S-Mamba,在多数长序列预测任务上能拿到靠前的名次,优势主要体现在 720 这种长预测长度上。在 96 这种短预测长度上,它和 iTransformer 的差距经常很小,甚至偶尔会输给 DLinear 这类线性模型。
一个更值得关注的细节是“胜出幅度”不够大。很多数据集上 S-Mamba 只比第二名低 0.005 左右的 MSE,这种差距在工程上基本等于没有。所以 Mamba 的现实定位不是“完全碾压 Transformer”,而是“在长序列、大复杂度场景下,线性复杂度给了它更好的性价比”。
4.2 摘要级别的三大操作建议
论文把实验经验浓缩成了三个实操建议,可以直接抄作业:
- 使用更小的 patch 长度。PatchTST 默认 patch_len 是 16,但在 Mamba 上,减小到 8 甚至 4 往往能带来明显提升。原因是更小的 patch 让 Mamba 能更细致地感知局部数值变化,而 Mamba 不像 Transformer 那样必须靠大 patch 来节省注意力开销,它天然就便宜。
- 适当增大状态维度 d_state。从默认的 8 或 16 提升到 32,能改善预测性能,但别无限提升,要注意算力成本和训练速度。
- 单变量预测务必加位置编码。多变量场景可以优先考虑 S-Mamba 的结构,用线性投影来补足 Mamba 对输入分布的感知能力。
这三条建议操作成本几乎为零。很多人做 Mamba 时序预测时,默认沿用 Transformer 的那套参数,结果效果不好就归咎于模型,实际上只是超参没有适配。
4.3 和其他热点工作的关系
论文还顺带讨论了一个经常引发争议的话题:为什么有些人报告 Mamba 在时序预测上不如线性模型?核心在于“token 化”方式。如果你把完整的原始序列直接塞给 Mamba,它会很难捕捉局部模式;如果你像 PatchTST 一样先把序列切成 patch,再进入模型,Mamba 才能真正发挥线性扫描的优势。甚至可以说,Mamba 的 patch 策略比 Transformer 更关键。
这个观点和不少社区复现失败的案例是吻合的。很多人换模型效果差,问题不出在 Mamba 本身,而是输入格式压根没有设计对。论文把“tokenization is critical”这个结论摆到台面上,对后续研究有很强的指导意义。
5. 论文没讲透的部分和我的复现体会
5.1 训练开销并没有想象中便宜
读论文之前,我对 Mamba 的印象是“注意力是线性的,所以一定很快”。但实际复现后我发现,Mamba 的“快”主要体现在理论复杂度上,不等于训练时间一定短。由于它的扫描机制是逐时间步递推的,无法像 Transformer 这样充分利用高度并行的矩阵乘法,在 GPU 上的实际吞吐收益要打折扣。官方实现里用了融合内核之后才真正跑起来,如果只依赖原生 PyTorch 循环实现,长序列训练往往会非常痛苦。
所以我的建议是:如果只是做基线对比,而不是为了验证 Mamba 理论本身,最好直接用官方提供的融合实现,别自己造轮子。否则你会在数值稳定性和算子优化上浪费大量时间,而这些并不是时序建模问题的核心。
5.2 位置编码加在哪里,论文没有统一答案
论文验证了“加位置编码对单变量有效”,但没有给出非常细粒度的结论:是加在 patch 输入上、加在 Mamba 每层内部、还是只加在输出头?不同实现里做法并不统一。我自己复现时,倾向于在 patch embedding 之后加一个可学习位置编码,效果稳定且实现简单。
还有一个很少被提到的话题:多变量预测中,位置编码是通道共享还是通道独立。如果每个通道共享同一套位置编码,参数少、稳定性好;如果通道独立,表达力更强但参数量成倍增加,容易过拟合。论文没有花篇幅展开这个对比,但根据经验,通道共享版本在大多数数据集上已经够用。
5.3 复现结果与官方数字的常见偏差
只要做过复现实验,大家都懂官方报告的数字很难 100% 复现。硬件环境、数据加载顺序、随机种子、甚至不同 CUDA 内核在 GPU 上产生微小浮点差异,都会导致结果波动。在我复现的过程中,S-Mamba 的 MSE 和论文报告的数字基本能对上,但偏差在 ±0.01 以内。这个量级放在短预测长度上,会直接改变排名顺序。
所以不要用“复现到小数点后三位一致”来验证论文,而应该关注趋势是否一致:Mamba 在长序列上是否整体更好、位置敏感性是否出现、patch 长度减小是否改善预测。趋势一致,论文的价值就已经得到验证。
6. 实操建议:把论文结论用到自己的时序项目里
6.1 一个可以直接跑的 S-Mamba 骨架
基于 mamba-ssm 库,我整理了一个极简 S-Mamba 模块,用于说明核心结构,不是完整训练代码:
import torch import torch.nn as nn from mamba_ssm import Mamba class S_MambaBlock(nn.Module): def __init__(self, d_model, d_state=16, d_conv=4, expand=2): super().__init__() self.norm = nn.LayerNorm(d_model) self.mamba = Mamba( d_model=d_model, d_state=d_state, d_conv=d_conv, expand=expand, ) self.linear = nn.Linear(d_model, d_model) def forward(self, x): # x: [B, C, N, d_model] B=批次, C=通道, N=token数 B, C, N, D = x.shape x = x.view(B * C, N, D) out = self.mamba(self.norm(x)) + x out = self.linear(out) return out.view(B, C, N, D)这段代码展示了 S-Mamba 的核心逻辑:先 LayerNorm,再进 Mamba,残差连接后过线性层。实际做预测时,你需要先把原始序列 patch 化,再把每个通道看成独立的“样本”喂进去,最后把最后一层 token 的表示映射到预测长度。整体流程很像 PatchTST,但中间的 Transformer Encoder 换成了 Mamba。
6.2 参数选择速查
我结合论文和复现经验整理了一个快速配置表,可以作为项目起点:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| patch_len | 4 ~ 8 | 比 Transformer 常用值更小,Mamba 对局部细节更敏感 |
| stride | 1 ~ 4 | 步长越小 token 越多,注意控制输入 token 总数 |
| d_state | 16 ~ 32 | 越大记忆越强,代价是速度和显存 |
| d_conv | 4 | 局部卷积核宽度,一般不用调 |
| expand | 2 | 控制内部隐藏扩展,默认 2 即可 |
| 位置编码 | 单变量用 PE,多变量可选 | 单变量收益明显 |
| 训练精度 | fp32 或混合精度 + 关键层 fp32 | 长序列谨慎使用纯 fp16 |
注意这张表是通用起点,不是铁律。不同数据集的最佳值会有偏移,建议在核心配置附近做小范围搜索。
6.3 什么时候别用 Mamba
论文读完后,我个人对“Mamba 是否有效”的回答是:有条件地有效,而不是无条件地有效。如果遇到下面几种情况,Mamba 未必是首选。
第一,短序列短预测,比如输入 48 步预测 12 步。这种场景下 Transformer 和线性模型的差距不大,Mamba 的复杂度优势根本体现不出来,反而增加了部署成本。第二,需要动态改变历史窗口长度。Mamba 对长度不匹配很敏感,推理时随便改输入长度,效果可能断崖式下跌。第三,算力非常有限,只能做 CPU 推理或部署在低功耗设备上。Mamba 的状态扫描算子通常依赖 GPU 生态的优化库,在 CPU 上性能远不如预期。第四,团队对 Mamba 的算子体系不熟悉,也没有时间调数值稳定性问题,那先别在核心业务上冒险,等周边生态更成熟再说。
反过来,如果你要做超长历史上下文预测,输入长度达到几千甚至上万,同时预测窗口也长,Mamba 是值得认真对待的选手。这种场景下 Transformer 的平方复杂度会带来很高的推理成本,Mamba 的线性扫描会从容很多。
7. 两个复现期容易踩的隐藏坑
7.1 融合内核与 torch.compile 的冲突
平时用 PyTorch 的人,可能习惯直接用 torch.compile 来加速训练。但 Mamba 的官方融合内核和 torch.compile 的图优化有时并不兼容,可能在运行时报错,或者性能反而下降。我建议在使用官方融合实现时,先用普通模式跑通一个最小样例,再决定是否打开编译优化。如果确实需要加速,可以先编译数据加载和 loss 部分,把 Mamba 层的编译单独隔开,这样风险最低。
7.2 padding 对状态更新的污染
Mamba 对批次里不同样本的长度非常敏感。如果你的数据加载逻辑里有变长序列,并且通过 padding 到固定长度来对齐 batch,需要特别注意:pad 部分的输入值不要设置成和真实数据分布相近的数,否则 Mamba 会把它当作有效信号继续更新状态,导致预测被污染。更稳妥的做法是,在 padding 的位置对应设置一个 mask,避免状态更新操作覆盖到无效 token。
这两个坑不算大,但在复现和二次开发时出现频率很高。论文本身不会写这类工程细节,只有亲手跑过一轮,才会意识到“模型有效”和“能顺利复现”之间还隔着不少实现层面的功课。