想象你是剧场导演,最擅长执导“群像戏”——舞台上几十个演员自由交流,谁都能和谁搭话,信息在人群里任意流动。这套手法在翻译、文本摘要领域屡试不爽。可这天上司递来一个剧本,名叫《时间之河》:剧情必须严格沿着时间轴推进,第3幕的演员不许偷看第10幕的剧本,每个角色的台词都依赖他“过去”的表现。你试着把原来的排戏法直接搬上台,结果一片混乱——所有人同时说话,没人知道先后顺序,还有人偷偷翻剧本。 Transformer 就是那位“群像戏导演”,它的杀手锏叫“自注意力”(Self-Attention):序列里任意两个位置可以直接互相“通话”,距离再远也不在话下。但时间序列就像《时间之河》——数据是一个接一个按时间排好的观测值,预测未来只能靠过去。把 Transformer 原封不动搬来用时序预测,就等于导演不设座位号、不禁止偷看剧本就开演,当然会翻车。这篇笔记带你看清:导演需要做哪几件事——给演员发座位号(位置编码)、立一条“不许往后看”的规矩(因果掩码)、重新设计舞台调度(稀疏注意力)——才能把“群像戏剧场”改造为“时间剧场”。

岗位关联

对 AI 从业者而言,理解 Transformer 的时序适配是通往 Informer、PatchTST、时序大模型的第一块垫脚石:读懂位置编码与因果掩码,你就能看懂大多数现代时序模型的骨架,并动手解决真实业务里的长序列预测问题。

目录
  1. 可视化演示
  2. 全局依赖捕捉——“全员圆桌会议”
  3. 位置编码困境——“给观众发座位号”
  4. 因果掩码设计——“不许偷看剧本”
  5. 计算复杂度瓶颈——“会议成本失控”
  6. 时序结构改造——“给剧场装上日历和剧本夹”
  7. 模型演进脉络——“新一代剧场设计”
  8. 实战应用指南——“选剧场与排戏”
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示Transformer也能做的核心机制,通过全局/局部/动态/静态四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Transformer也能做:自注意力 自注意力机制的核心原理与序列建 位置编码注入时序顺序信息 核心机制可视化 Transformer也能做整体架构与关键组件

全局依赖捕捉——“全员圆桌会议”

老式剧场(RNN)排戏有个规矩:信息像接力棒一样一位一位往后传。第1幕演员要把话传给第2幕,第2幕传给第3幕……传到第100幕时,最初的信息早已模糊。小A的“群像戏剧场”(Transformer)完全不同——他开的是全员圆桌会议,台上任何一位演员都能直接对任何另一位说话,中间不需要传话筒。

这套机制叫做“自注意力”。它对序列中每个元素(token)同时计算“跟其他人的关联强度”,然后按关联强度汇总信息。对时序预测来说,这意味着一周前的某个异常峰值,可以直接“呼叫”今天的模型输出,而不必像 RNN 那样在传递过程中被稀释。比如预测明天电价,模型可以直接参考 7 天前同一时段的峰值,而不是让它淹没在漫长的传递链里。

具体做法是让每个 token 生成三样东西:Query(想问什么)、Key(能答什么)、Value(实际给出什么)。Q 和 K 做点积得到“关联分”,再用 softmax 变成权重,最后按权重把所有人的 V 聚合起来。一句话:Q 是提问,K 是简介,V 是答案。

有了圆桌会议,剧组信息流通效率最高。但问题来了——圆桌会议默认“人人平等、不分先后”,《时间之河》这个剧本要求先生后次。于是小A发现,光有会议还不够,得先解决“谁先谁后”的问题。

Attention(Q,K,V)=softmax(QK⊤dk)V\text{Attention}(Q,K,V)=\mathrm{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V
通俗说:自注意力 = 全员开会,每人发出提问(Q)、亮出简介(K),按匹配度决定听谁的答案(V)更多。
  1. 查询矩阵 Q每个位置生成一个“提问向量”,代表它想从别处获取什么信息,形状为 n 行 d_k 列。
    Q=XWQ,Q∈Rn×dkQ=XW_Q,\quad Q\in\mathbb{R}^{n\times d_k}
  2. 键矩阵 K每个位置生成一个“简介向量”,供别人的提问来匹配,形状同为 n 行 d_k 列。
    K=XWK,K∈Rn×dkK=XW_K,\quad K\in\mathbb{R}^{n\times d_k}
  3. 缩放点积得分Q 和 K 做内积得到两两“关联分”,除以根号 d_k 防止数值过大,导致后续 softmax 梯度消失。
    QK⊤dk\frac{QK^{\top}}{\sqrt{d_k}}
  4. softmax 归一化把每行得分变成和为 1 的权重,表示“我该听谁多少”。
    softmax(⋅)\mathrm{softmax}\left(\cdot\right)
  5. 加权聚合 V用权重对所有位置的“答案向量”V 加权求和,得到该位置的新表示。
    softmax(QK⊤dk)V\mathrm{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V

位置编码困境——“给观众发座位号”

群像戏剧场里,所有演员都在同一时刻交流,座位怎么排无所谓。可《时间之河》的舞台是有时间方向的:第1分钟观测到的温度和第100分钟的温度,是两种完全不同的“身份”。如果只把数值喂给模型,模型眼中它们只是两个没有编号的方块——顺序信息全丢了。

这就是 Transformer 的先天盲点:自注意力本身对“位置”无感。你把序列倒过来,注意力结果一模一样。时序预测最依赖的偏偏就是顺序,所以必须给每个位置“发座位号”。如果把原始房价序列直接喂进去,模型会发现“涨跌顺序”在数学上和“倒序”毫无区别,预测自然无从谈起。

最经典的做法是正弦位置编码:用一组频率不同的正弦波,为每个位置生成一个唯一的向量。位置越靠后,编码向量越不同;同时它还能帮模型感知相对距离——第 pos+k 位和第 pos 位的编码之间存在稳定的线性关系,就像座位号连续的两个观众能立刻算出相隔几排。

有了座位号,演员终于知道自己站在时间轴的哪一格。小A松了口气,但紧接着新问题浮出水面:圆桌会议上,有的演员忍不住偷看后面的剧本——未来信息一旦泄漏,预测就成“作弊”了。

PE(pos,2i)=sin⁡(pos100002i/d),PE(pos,2i+1)=cos⁡(pos100002i/d)PE_{(pos,2i)}=\sin\left(\frac{pos}{10000^{2i/d}}\right),\qquad PE_{(pos,2i+1)}=\cos\left(\frac{pos}{10000^{2i/d}}\right)
通俗说:位置编码 = 给每个“时刻”配一个独一无二的多维数字指纹,指纹的频率高低决定了它能覆盖的距离尺度。
  1. pos 位置号token 在序列中的绝对下标,比如第 3 个时间步的 pos = 3。
    pos=0,1,2,…pos=0,1,2,\ldots
  2. i 维度下标表示编码向量的第几维,i 越大,对应正弦波的频率越低。
    i=0,1,2,…,d2−1i=0,1,2,\ldots,\frac{d}{2}-1
  3. 偶数维用正弦偶数维度填入 sin 值,负责记录“绝对位置”信息。
    PE(pos,2i)=sin⁡(pos100002i/d)PE_{(pos,2i)}=\sin\left(\frac{pos}{10000^{2i/d}}\right)
  4. 奇数维用余弦奇数维度填入 cos 值,与 sin 组合形成正交的编码基。
    PE(pos,2i+1)=cos⁡(pos100002i/d)PE_{(pos,2i+1)}=\cos\left(\frac{pos}{10000^{2i/d}}\right)
  5. 分母的频率控制10000 的幂次让低维编码波动快(细粒度位置),高维编码波动慢(粗粒度位置)。
    2id∈[0,1)\frac{2i}{d}\in[0,1)

因果掩码设计——“不许偷看剧本”

剧场有条铁规矩:排练时任何演员不许翻到后面几页的剧本。因为正式演出时,第3幕的演员根本不知道第10幕会发生什么。小A发现他的圆桌会议有个漏洞:所有人都能看到所有人,等于开会时桌上摊着未来剧本,演到第3幕时第10幕的答案已经摆在眼前了——这叫“未来信息泄漏”。

在时序预测里,“泄漏”意味着模型在训练时看到了未来,测试时却看不到。这样的模型在训练集上成绩惊艳,一上真实预测就露馅。解决办法是加一块“掩码板”,把未来位置遮住。就像导演给每个演员发一册“已删减剧本”,只保留到当下这一幕为止。

因果掩码的工作原理很简单:构造一个与注意力得分同尺寸的上三角矩阵。当前位置 i 看向自己或过去(j ≤ i)的位置,填入 0,表示“允许看”;看向未来(j > i)的位置,填入 -∞,表示“禁止看”。掩码先加进得分矩阵,再走 softmax——-∞ 的地方概率自然变成 0,一丝信息都漏不进来。

掩码上场的瞬间,圆桌会议变成了“只准谈过去、不准聊未来”的复盘会。小A的剧场纪律达标了。但他算了一笔账:全员圆桌会议的开销和演员人数的平方成正比——演员一多,会议成本爆炸。

Attention(Q,K,V)=softmax(QK⊤dk+M)V,Mij={0,i≥j−∞,i<j\text{Attention}(Q,K,V)=\mathrm{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}+M\right)V,\quad M_{ij}=\begin{cases}0, & i\ge j\\ -\infty, & i<j\end{cases}
通俗说:因果掩码 = 给注意力得分矩阵贴一张“下三角通行证”,只有左下角能进,右上角封死。
  1. 构造掩码矩阵 M尺寸为 n×n,下三角(含对角线)全 0,上三角全 -∞。
    Mij={0,i≥j−∞,i<jM_{ij}=\begin{cases}0, & i\ge j\\ -\infty, & i<j\end{cases}
  2. 加入注意力得分把掩码逐元素加到 QK 缩放后的得分矩阵上,未来位置变成极大的负数。
    QK⊤dk+M\frac{QK^{\top}}{\sqrt{d_k}}+M
  3. softmax 归一化-∞ 经过指数运算后趋近 0,未来位置的注意力权重被完全抹除。
    softmax(QK⊤dk+M)\mathrm{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}+M\right)
  4. 输出保序聚合加权求和时只聚合“历史与当下”的信息,位置 i 的输出完全不依赖未来。
    softmax(QK⊤dk+M)V\mathrm{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}+M\right)V

计算复杂度瓶颈——“会议成本失控”

排《时间之河》第一版时,小A让全体 1000 名演员开圆桌会议。每个人都要和另外 999 人各聊一句,就是约 50 万次对话。序列长度翻倍到 2000 人,对话量直接变 4 倍——排练厅被话筒线塞满了。小A看着账单,觉得不能再这样开会了。

这就是 Transformer 自注意力的 O(n²) 复杂度:n 是序列长度,注意力矩阵有 n×n 个“对话对”。时序数据通常又长又多,比如一年 365 天 × 24 小时的电力数据有 8760 个点;直接套用原生 Transformer,训练时间会让人绝望。

复杂度公式的背后根源是:每个位置都要计算与所有其他位置的注意力权重,矩阵 n×n 是逃不掉的开销。业界为此提出各种“减负方案”:局部窗口注意力(只和附近的人聊)、稀疏注意力(只挑重要的人聊)、分解注意力(把长矩阵拆成两个短矩阵的积)。思路都是同一个——不是所有对话都必要。

小A意识到,光靠圆桌会议解决不了大剧场的长剧本。他开始改造舞台设计——把长剧本切成段、给不同的段安排不同的会议频率。这就是时序结构改造。

Computational Cost=O(n2⋅d)\text{Computational Cost}=O(n^2 \cdot d)
通俗说:序列长度 n 每翻一倍,计算量翻 4 倍——这是注意力机制最大的“账单痛点”。
  1. n² 的来源注意力权重矩阵是 n 行 n 列,每个位置要与其他 n−1 个位置各算一次关联分。
    A∈Rn×nA\in\mathbb{R}^{n\times n}
  2. d 的来源每次点积是 d 维向量内积,牵涉 d 次乘加运算。
    per-pair cost=O(d)\text{per-pair cost}=O(d)
  3. 总开销n² 对配对成本再乘上 d,得到总复杂度。
    O(n2⋅d)O(n^2\cdot d)
  4. 序列翻倍效应n 变为 2n 时,计算量变为 (2n)²·d = 4n²·d,是原来的 4 倍。
    O((2n)2⋅d)=4⋅O(n2⋅d)O((2n)^2\cdot d)=4\cdot O(n^2\cdot d)

时序结构改造——“给剧场装上日历和剧本夹”

真正的时间剧场需要三样基础设施:日历(告诉演员今天几号)、剧本夹(把戏份按幕打包)、结束语(规定每幕以什么手势收场)。小A明白,单纯在输入上加个位置编码还不够,整个数据进出的方式都要为“时间”改造。

在技术层面,时序 Transformer 的改造集中在三处。输入侧:把原始数值映射成向量,并在每个时刻叠加上“时刻标识”——位置编码可以换成相对位置编码或可学习编码,让模型更适应周期性数据。结构侧:长序列先分块或下采样,降低注意力规模。输出侧:不再是预测下一个词,而是设计专门的“预测头”输出未来若干步的数值。

一个通用的输入表示可以写成:每个时刻的原始观测值 x\_t 先过一个嵌入层变成向量,再与位置编码逐元素相加。若涉及多个序列段(比如“过去段”和“未来段”),还可以加上分段嵌入。这三种信息叠加在一起,才构成真正带“时间感”的输入。

经过改造,小A的“时间剧场”终于能排长剧了。但这只是开始。此后学术界就像剧场行业涌现新的舞台设计一样,出现了 Informer、PatchTST 等一批专为时序优化的新剧场——是时候看看他们怎么干的了。

ht=Embedding(xt)+PositionalEncoding(t)h_t = \mathrm{Embedding}(x_t) + \mathrm{PositionalEncoding}(t)
通俗说:时序结构改造 = 给每个时间步“搭积木”——数值信息、位置信息、分段信息三个模块叠成完整输入。
  1. Embedding(x_t)把第 t 个时刻的原始数值(或数值向量)映射成稠密向量,让模型能加工。
    zt=Embedding(xt),zt∈Rdz_t=\mathrm{Embedding}(x_t),\quad z_t\in\mathbb{R}^d
  2. PositionalEncoding(t)为时刻 t 生成位置编码向量,与 Embedding 同维度。
    pt=PositionalEncoding(t),pt∈Rdp_t=\mathrm{PositionalEncoding}(t),\quad p_t\in\mathbb{R}^d
  3. 逐元素相加数值向量与位置向量逐元素相加,融合“是什么”与“在何时”。
    ht=zt+pth_t=z_t+p_t
  4. 进入自注意力层融合后的 h_t 作为 Q、K、V 的源头,进入后续注意力计算。
    X=[h1,h2,…,hn]X=[h_1,h_2,\ldots,h_n]

模型演进脉络——“新一代剧场设计”

第一代时间剧场证明了“座位号 + 不许偷看 + 分幕”能行。但行业不断出现新方案:有人发明了“只让主角列席”的会议规则(Informer),有人发明了“把剧本按段打印给演员看”的做法(PatchTST)。小A赶紧去观摩,把好东西都学回来。

Informer 是 Transformer 做长序列预测的代表作,发表于 ICLR 2021。它发现注意力矩阵里其实只有少数“主导查询”真正重要:大部分位置的注意力分布接近均匀分布,贡献的增量信息很小。于是它用 ProbSparse 自注意力挑选重要的 Q 参与计算,把复杂度从 O(n²) 降到 O(n log n)。同时用蒸馏层逐步压缩序列长度,像导演每幕结束都让群演退场,只留主演。

ProbSparse 的挑选依据是 KL 散度——衡量某个 Query 的注意力分布和均匀分布的差距。差距越大,说明这个查询的选择性越强、信息量越大,就越值得保留完整计算;差距小的查询直接用一个均值近似,省下大量计算。PatchTST 则走另一条路:把连续几个时间步“糊成一个补丁”再送进 Transformer,token 数量瞬间缩减好几倍。

后来 PatchTST 干脆把一段连续时间步“糊成一个补丁”再喂给 Transformer,进一步压缩 token 数。新一代剧场越来越懂“时间”两个字怎么写。作为从业者,怎么挑剧场、怎么排戏,最后一节聊实战。

M(qi,K)=ln⁡∑j=1LKeqikj⊤d−1LK∑j=1LKqikj⊤dM(q_i,K)=\ln\sum_{j=1}^{L_K}e^{\frac{q_i k_j^{\top}}{\sqrt{d}}}-\frac{1}{L_K}\sum_{j=1}^{L_K}\frac{q_i k_j^{\top}}{\sqrt{d}}
通俗说:ProbSparse = 开会时只让“提问最刁钻的主角”坐主桌,其他配角用平均态度代替,会议成本大减。
  1. log-sum-exp 项对第 i 个查询与所有键的得分求对数加和指数,衡量注意力分布的“峰值程度”。
    ln⁡∑jeqikj⊤d\ln\sum_{j}e^{\frac{q_i k_j^{\top}}{\sqrt{d}}}
  2. 均值项计算该查询与所有键得分的算术平均,看作均匀分布下的期望得分。
    1LK∑jqikj⊤d\frac{1}{L_K}\sum_{j}\frac{q_i k_j^{\top}}{\sqrt{d}}
  3. KL 散度差值两项之差越大,说明该查询的注意力分布越偏离均匀分布、越“有的放矢”。
    M(qi,K)=(1)−(2)M(q_i,K)=\text{(1)}-\text{(2)}
  4. Top-u 筛选取 M 值最大的前 u 个查询做完整注意力计算,其余查询用全局均值替代。
    Aˉ(Q,K,V)=Softmax(QˉK⊤d)V\bar{\mathcal{A}}(Q,K,V)=\mathrm{Softmax}\left(\frac{\bar{Q}K^{\top}}{\sqrt{d}}\right)V

实战应用指南——“选剧场与排戏”

小A现在手里有各种剧场方案,但他知道,选哪个取决于剧本:短剧用简单班子,长篇史诗必须上大剧场。实战中,数据准备、超参数选择、评估指标这三件事决定成败。

先说数据。时序数据一定要按时间顺序划分训练集、验证集、测试集,绝对不能随机打乱——否则等于把未来答案塞进了训练集,模型考试时直接翻到答案页。标准化 / 归一化要按训练集的统计量计算,再应用到验证集和测试集,避免“偷看”全局均值与方差。

模型超参数方面,最重要的是回溯窗口(输入长度)和预测长度。回溯窗口不必贪长,选择与历史模式周期匹配的窗口往往最佳:预测明天的天气,回溯 7 天或 30 天比回溯 365 天更稳。注意力头数、层数先从小配置起步,遵循“先小后大、观察过拟合再扩容”的原则。评估指标常用 MAE 和 MSE,MSE 对大偏差更敏感,工业场景往往还会加上业务自定义的容忍阈值。

小A终于完成了“时间剧场”的全部设计:圆桌会议(自注意力)+ 座位号(位置编码)+ 不许偷看(因果掩码)+ 精简会议(稀疏注意力)+ 分幕排练(分块 / 蒸馏)。他拍了拍手,准备正式开演。你也一样——下一次拿到时序数据,知道该怎么给 Transformer“排戏”了吧?

LMSE=1T∑t=1T(yt−y^t)2\mathcal{L}_{\mathrm{MSE}}=\frac{1}{T}\sum_{t=1}^{T}\left(y_t-\hat{y}_t\right)^2
通俗说:MSE = 把所有预测误差平方后取平均,误差越大,惩罚越重。
  1. 误差项第 t 步的真实值与预测值之差。
    yt−y^ty_t-\hat{y}_t
  2. 平方放大对误差取平方,避免正负抵消,同时放大离群大误差。
    (yt−y^t)2\left(y_t-\hat{y}_t\right)^2
  3. 对所有时刻求平均把 T 个时刻的平方误差加起来除以 T,得到整体损失。
    1T∑t=1T(yt−y^t)2\frac{1}{T}\sum_{t=1}^{T}\left(y_t-\hat{y}_t\right)^2

AI 应用场景

电网短期负荷预测

阶段:特征工程与模型选型

解决的问题:传统统计方法(ARIMA)难以捕捉气温、节假日、历史负荷之间的复杂长程依赖,预测 24 小时后的峰值负荷常常滞后。Transformer 的自注意力让模型直接关联“去年同一天”或“三天前同一时段”的关键模式,配合因果掩码保证只用过去数据。

具体案例:某省级电网用改造后的 Informer 模型,以过去 168 小时(7 天)的负荷、温度、湿度序列为输入,预测未来 24 小时负荷曲线,MAPE 从传统方法的 6.2% 降到 3.8%,为电力调度节省了大量备用容量成本。

金融交易序列异常检测

阶段:模型推理与在线监控

解决的问题:金融高频交易数据天然是“未来的事不能偷看”——回测时若模型用了未来信息,实盘必然亏损。因果掩码在此场景是刚需;位置编码则让模型区分“开盘后第 1 分钟”和“收盘前 1 分钟”的不同市场状态。

具体案例:某量化团队用带因果掩码的 Transformer 对 5000 只股票的每分钟成交序列做在线异常检测,捕捉到了 3 次因宏观新闻引发的“闪崩”前兆,比传统滑动窗口方法的报警提前了约 4 分钟。

工业设备剩余寿命预测

阶段:部署与持续预测

解决的问题:工业传感器产生的振动、温度信号长达数万步,原生 Transformer 的 O(n²) 复杂度让长序列训练寸步难行。采用分块 + 稀疏注意力改造后,既能覆盖长周期退化趋势,又能控制计算开销。

具体案例:某航空发动机维护团队用 PatchTST 思路处理 C-MAPSS 数据集,把每 30 个时间步合成一个补丁,预测剩余寿命的 RMSE 比 LSTM 降低了 18%,而且推理速度提升 5 倍,已部署到边缘设备上。

Python 演示

python54 行
"""Transformer 时序适配: 位置编码 + 因果掩码 + 自注意力 (NumPy 手写版)"""import numpy as npimport math def positional_encoding(T, d_model):    """正弦位置编码: 给每个时间步发一个专属座位号"""    pe = np.zeros((T, d_model))    for pos in range(T):        for i in range(0, d_model, 2):            pe[pos, i] = math.sin(pos / 10000 ** (2 * i / d_model))            if i + 1 < d_model:                pe[pos, i + 1] = math.cos(pos / 10000 ** (2 * i / d_model))    return pe def causal_mask(T):    """下三角掩码: 上三角填 -1e9, softmax 后概率归零"""    return np.triu(np.full((T, T), -1e9), k=1) def attention(Q, K, V, mask=None):    """缩放点积注意力 + 可选因果掩码"""    d_k = K.shape[-1]    scores = Q @ K.T / math.sqrt(d_k)    if mask is not None:        scores = scores + mask    weights = np.exp(scores - scores.max(axis=-1, keepdims=True))    weights = weights / weights.sum(axis=-1, keepdims=True)    return weights @ V, weights # 构造一段带趋势和周期的时间序列 (长度 8)T, d_model = 8, 16t_idx = np.arange(T)x = np.sin(0.5 * t_idx) + 0.1 * t_idx # 输入嵌入 + 位置编码rng = np.random.RandomState(42)W_emb = rng.randn(1, d_model) * 0.1h = x.reshape(-1, 1) @ W_emb + positional_encoding(T, d_model) # 随机初始化 QKV 投影 (教学示范, 不训练)W_q = rng.randn(d_model, d_model) * 0.1W_k = rng.randn(d_model, d_model) * 0.1W_v = rng.randn(d_model, d_model) * 0.1 # 前向: 带因果掩码的自注意力out, attn = attention(h @ W_q, h @ W_k, h @ W_v, causal_mask(T)) print("注意力权重矩阵 (每行=查询位置, 列=可见位置):")print(np.round(attn, 2))print("\n因果性验证: 第 5 行之后的位置权重全为 0 ->", np.all(attn[5, 6:] < 1e-6)) # 取最后一个位置的输出, 映射为下一步预测W_out = rng.randn(d_model, 1) * 0.1next_pred = out[-1] @ W_outprint("\n预测下一步值:", round(float(next_pred[0]), 4))
目的:用 NumPy 从零实现“位置编码 + 因果掩码 + 缩放点积注意力”的前向过程,直观验证时序 Transformer 的三个核心适配机制。
  1. def positional_encoding(T, d_model)生成 T 个时间步的 d 维正弦位置编码,相当于给每个时刻发座位号。
  2. pe[pos, i] = math.sin(...)偶数维度填正弦值,奇数维度填余弦值,频率随维度递减。
  3. def causal_mask(T)返回上三角为 -1e9 的掩码矩阵,加进得分后 softmax 会把未来位置权重压成 0。
  4. scores = Q @ K.T / math.sqrt(d_k)计算缩放点积得分,除以根号 d_k 防止数值过大。
  5. weights = np.exp(scores - scores.max(...))用减最大值技巧做数值稳定的 softmax 分子。
  6. h = x.reshape(-1, 1) @ W_emb + positional_encoding(T, d_model)嵌入与位置编码逐元素相加,构成带时间感知的输入。
  7. np.triu(np.full((T, T), -1e9), k=1)k=1 表示从主对角线上一行开始遮挡,确保对角线(自己)可见。

常见误区

误区我觉得 Transformer 的注意力机制很强大,RNN 都能记住顺序,Transformer 肯定也行,所以直接把原始时间序列丢进去就好。

正解自注意力是“排列等变”的——把输入序列倒过来,输出只是跟着倒,模型根本没意识到“顺序”的存在。就像圆桌会议上大家自由发言,座位怎么排无所谓。时序预测必须先加位置编码,否则模型看到的只是一袋乱序数字。

为何常见:很多教程讲注意力时只强调“并行计算、长程依赖”,很少专门讲排列等变性,初学者误以为“能看全局”就等于“知道先后”。

误区我理解的因果掩码是在数据预处理阶段把未来时刻的样本手动清空,比如把第 t 时刻之后的值全设置成 0 再训练。

正解因果掩码不是在数据上删值,而是在注意力得分矩阵上加一层上三角 -∞ 掩码,让 softmax 之后未来位置的权重归零。数据本身完整保留,只是模型“看”不到未来——就像导演不是撕掉剧本,而是给每位演员发一册删减版剧本,知道下一页的内容被撕掉了。

为何常见:“掩码(Mask)”这个翻译容易让人联想到处理缺失值时的“置零”,忽略了它发生在注意力计算内部而非数据层面。

误区既然 Transformer 能处理长依赖,那我回溯一年的数据做输入,模型一定能学到更多规律,预测自然更准。

正解序列长度 n 翻倍,自注意力计算量翻 4 倍(O(n²)),训练时间和显存都会爆炸;更关键的是,过长的窗口会引入大量无关噪声,还会稀释近期重要模式。实际工程中,回溯窗口应与业务周期匹配——预测明天,回溯 7 天或 30 天往往比回溯 365 天效果更好。

为何常见:人们容易把“模型能力上限”误解为“输入越多越好”,忽视了计算代价和信噪比之间的权衡。

误区Transformer 是最新最强架构,做时序预测肯定比 LSTM 好,所以项目直接上 Transformer 就稳了。

正解Transformer 的优势在大规模数据和长序列上才明显;小样本(比如几千个时间步)时,LSTM 的归纳偏置(天然处理顺序)反而更有优势,而且训练更快、调参更容易。时序场景里选模型要看数据量、序列长度、业务实时性要求,不能无脑追新。

为何常见:技术宣传往往突出 SOTA 结果而忽略实验条件,“新架构必胜”的观念在初学者中很普遍。

面试题

Q1. Transformer 中 Q、K、V 向量是由什么产生的?

单选题 · easy

  • A.同一份输入经过三个不同的线性映射得到← 正确答案
  • B.三个不同网络层共享一份权重得到
  • C.输入向量经过三次卷积操作得到
  • D.由固定的随机矩阵直接赋值得到

答案:A。Q、K、V 分别由输入 X 乘以三个不同的可学习权重矩阵 W_Q、W_K、W_V 得到,就像剧场里三个副导演从同一份演员名册中分别整理出“提问清单”“简介册”“答案册”。B 错在共享权重会导致三者完全相同,注意力失去意义;C 的卷积不属于标准 Transformer 的生成方式;D 用固定随机矩阵则无法训练。

Q2. 注意力公式中为什么要除以根号 d_k?

单选题 · easy

  • A.防止点积数值过大压垮 softmax← 正确答案
  • B.为了让向量维度变得更小
  • C.保证输出向量的均值恒为零
  • D.降低矩阵乘法的计算复杂度

答案:A。当维度 d_k 较大时,点积数值会变得很大,softmax 进入饱和区导致梯度趋近于零。除以根号 d_k 相当于“音量调低”,把得分拉回合理区间。这就像开圆桌会议时主持人让大家压低声音说话,避免讨论太激烈反而听不清。其余选项与缩放因子的数学作用无关。

Q3. 原生 Transformer 直接用于时间序列预测,最大的先天问题是什么?

单选题 · mid

  • A.缺失序列位置的顺序信息← 正确答案
  • B.无法进行梯度反向传播
  • C.输出层的维度不够高
  • D.不能处理非数值型数据

答案:A。自注意力是排列等变的,输入顺序颠倒后输出也跟着颠倒,模型完全不知道先后关系。时间序列预测的核心就是“顺序即因果”,所以必须加位置编码。B 错误,Transformer 完全可微;C 和 D 都不是结构性的先天缺陷,可通过调整输出头或嵌入层解决。

Q4. 因果掩码矩阵中,代表“未来不可见”的位置应填入什么值?

单选题 · mid

  • A.负无穷或一个极大的负数← 正确答案
  • B.正无穷一个极大的正数
  • C.常数 1 让权重均匀分布
  • D.全零矩阵什么都不填写

答案:A。填入 -∞ 后,经过 softmax 时指数运算结果趋近于 0,未来位置的注意力权重被彻底抹除。这就好比导演在剧本上把未来页面全部涂黑,演员根本看不到。B 会放大未来信息;C 会让未来参与投票;D 相当于没有掩码。

Q5. 因果掩码被加在注意力流程的哪个环节?

单选题 · mid

  • A.QK 点积缩放之后、softmax 之前← 正确答案
  • B.softmax 归一化处理完之后
  • C.输入数据进入嵌入层之前
  • D.加权求和计算出结果之后

答案:A。掩码必须先加到缩放后的得分矩阵上,再做 softmax,这样 -∞ 才能转化为 0 概率。如果先 softmax 再加掩码,相当于权重已经归一化,掩码就会破坏概率和。类似导演必须在演员亮完相后再宣布谁被淘汰,而不是提前淘汰再让演员亮相。

Q6. 把 Transformer 改造用于时序预测,常见的可行做法有哪些?

多选题 · mid

  • A.在输入层叠加位置编码← 正确答案
  • B.在自注意力中加入因果掩码← 正确答案
  • C.使用稀疏注意力降低长序列开销← 正确答案
  • D.删除所有激活函数简化模型

答案:ABC。位置编码补顺序、因果掩码防泄漏、稀疏注意力控成本,三者正是本文的核心改造手段。D 删除全部激活函数会使网络退化为线性变换,严重损失表达能力,绝非可行方案。

Q7. 原生自注意力对长度为 n 的序列,计算复杂度是多少?

单选题 · hard

  • A.O(n²·d)← 正确答案
  • B.O(n·log n)
  • C.O(n·d)
  • D.O(d²)

答案:A。注意力权重矩阵是 n×n,每个元素的计算涉及 d 维点积,因此总复杂度为 O(n²·d)。这就像 1000 人圆桌会议上每个人要和其余 999 人各聊一句。Informer 等模型正是为了把 n² 降下来才提出稀疏注意力。B 是 Informer 的目标复杂度,C 是线性复杂度理想值,D 与序列长度无关。

Q8. 关于 Informer 的 ProbSparse 自注意力,下列说法正确的是?

多选题 · mid

  • A.只挑选少数“主导 Query”计算完整注意力← 正确答案
  • B.能把计算复杂度降至 O(n·log n)← 正确答案
  • C.完全放弃使用注意力机制
  • D.用全局平均池化替代所有查询

答案:AB。ProbSparse 的核心是用 KL 散度衡量每个 Query 的注意力分布与均匀分布的差异,只保留差异大的“主演”做完整计算。A 和 B 正是其设计目标。C、D 说反了——它仍然用注意力,只是对非主导查询用均值近似,并非完全替换或删除。

Q9. 时间序列预测任务划分训练集与测试集时,正确做法是什么?

单选题 · mid

  • A.按时间先后顺序切分数据← 正确答案
  • B.随机打乱所有样本后切分
  • C.按数值大小排序后再切分
  • D.让训练集区间覆盖测试集区间

答案:A。时序数据不能随机打乱,否则模型会从训练集里“偷看”到未来信息,测试集失去意义。就像考试前把答案混进复习资料,考得再好也是假的。必须按时间顺序切分,且训练集只能使用更早的数据。

Q10. 关于位置编码的下列说法,哪些是正确的?

多选题 · hard

  • A.正弦位置编码具有一定的长度外推能力← 正确答案
  • B.可学习位置编码在训练中更灵活← 正确答案
  • C.相对位置编码只关注两个位置的间隔← 正确答案
  • D.位置编码必须在每一层重新计算一次

答案:ABC。正弦编码用固定公式生成,对未见过的长度也能计算出编码,因此有外推能力(A 对);可学习编码是参数,能在训练中自适应调整(B 对);相对位置编码关注的是间隔 k 而非绝对位置(C 对)。D 错误——标准实现通常在输入层加一次位置编码,后续层共享位置信息即可,逐层重算反而浪费。