1. Attention
高效自注意力机制
经典的自注意力机制(Vaswani等,2017)基于三元组输入,即查询(Query, Q Q Q)、键(Key, K K K)和值(Value, V V V),其执行的缩放点积计算定义如下:
A ( Q , K , V ) = Softmax ( Q ‾ K ⊤ d ) V A(Q, K, V) = \text{Softmax}\left(\frac{\overline{Q}K^\top}{\sqrt{d}}\right)V A(Q,K,V)=Softmax(dQK⊤)V
其中, Q ‾ ∈ R L Q × d \overline{Q} \in \mathbb{R}^{L_Q \times d} Q∈RLQ×d, K ∈ R L K × d K \in \mathbb{R}^{L_K \times d} K∈RLK×d, V ∈ R L V × d V \in \mathbb{R}^{L_V \times d} V∈RLV×d, d d d 是输入的维度。
为了进一步讨论自注意力机制,设 q i , k i , v i q_i, k_i, v_i qi,ki,vi 分别表示矩阵 Q , K , V Q, K, V Q,K,V 的第 i i i 行。根据(Tsai等,2019)的公式,第 i i i 个查询的注意力可以定义为概率形式的核平滑器(kernel smoother):
A ( q i , K , V ) = ∑ j k ( q i , k j ) v j ∑ l k ( q i , k l ) = E p ( k j ∣ q i ) [ v j ] A(q_i, K, V) = \sum_j k(q_i, k_j) \frac{v_j}{\sum_l k(q_i, k_l)} = \mathbb{E}_{p(k_j | q_i)}[v_j] A(qi,K,V)=j∑k(qi,kj)∑lk(qi,kl)vj=Ep(kj∣qi)[vj]
其中,
k
(
q
i
,
k
j
)
k(q_i, k_j)
k(qi,kj) 是查询
q
i
q_i
qi 和键
k
j
k_j
kj 之间的相似度函数,输出是基于查询
q
i
q_i
qi 对所有键的概率加权值
v
j
v_j
vj 的期望值
E
p
(
k
j
∣
q
i
)
[
v
j
]
\mathbb{E}_{p(k_j | q_i)}[v_j]
Ep(kj∣qi)[vj]。
在这里,
p
(
k
j
∣
q
i
)
p(k_j | q_i)
p(kj∣qi) 被定义为查询
q
i
q_i
qi 对键
k
j
k_j
kj 的注意力概率,它的计算公式为:
p ( k j ∣ q i ) = k ( q i , k j ) ∑ l k ( q i , k l ) p(k_j | q_i) = \frac{k(q_i, k_j)}{\sum_l k(q_i, k_l)} p(kj∣qi)=∑lk(qi,kl)k(qi,kj)
其中, k ( q i , k j ) k(q_i, k_j) k(qi,kj) 选择了非对称指数核函数:
k ( q i , k j ) = exp ( q i k j ⊤ d ) k(q_i, k_j) = \exp\left(\frac{q_i k_j^\top}{\sqrt{d}}\right) k(qi,kj)=exp(dqikj⊤)
自注意力通过计算这个概率 p ( k j ∣ q i ) p(k_j | q_i) p(kj∣qi),结合对应的值(value)来生成输出。这个过程需要二次时间复杂度的点积计算,且占用 O ( L Q L K ) O(L_Q L_K) O(LQLK) 的内存,这在提升预测能力时是一个主要的瓶颈。
此前的一些研究表明,自注意力概率的分布具有潜在的稀疏性。因此,研究者设计了在不显著影响性能的情况下,对所有 p ( k j ∣ q i ) p(k_j | q_i) p(kj∣qi) 进行“选择性”计算的策略。例如:
- Sparse Transformer(Child等,2019)结合了行输出和列输入的计算,稀疏性来自于分离的空间相关性。
- LogSparse Transformer(Li等,2019)注意到了自注意力中的周期模式,强制每个单元通过指数步长关注其前一个单元。
- Longformer(Beltagy等,2020)进一步扩展了前两者的工作,设计了更加复杂的稀疏配置。
然而,这些方法仅限于通过启发式方法进行的理论分析,它们对每个多头自注意力使用相同的策略,限制了进一步的改进空间。
查询稀疏性度量(Query Sparsity Measure)
根据公式 1 1 1,第 i i i 个查询对所有键的注意力被定义为概率 p ( k j ∣ q i ) p(k_j | q_i) p(kj∣qi),输出是其与值 v v v 的组合。主导的点积促使相应查询的注意力概率分布偏离均匀分布。如果 p ( k j ∣ q i ) p(k_j | q_i) p(kj∣qi) 接近均匀分布 q ( k j ∣ q i ) = 1 L K q(k_j | q_i) = \frac{1}{L_K} q(kj∣qi)=LK1,则自注意力将变成对值 V V V 的简单求和,从而对输入没有实际帮助且显得冗余。
自然地,分布 p p p 和 q q q 之间的“相似性”可以用来区分哪些查询是“重要的”。
Kullback-Leibler 散度
我们通过 Kullback-Leibler (KL) 散度 来衡量这种“相似性”,公式如下:
K L ( q ∥ p ) = ln ( ∑ l = 1 L K e q i k l ⊤ d ) − 1 L K ∑ j = 1 L K q i k j ⊤ d − ln L K KL(q \parallel p) = \ln \left( \sum_{l=1}^{L_K} e^{\frac{q_i k_l^\top}{\sqrt{d}}} \right) - \frac{1}{L_K} \sum_{j=1}^{L_K} \frac{q_i k_j^\top}{\sqrt{d}} - \ln L_K KL(q∥p)=ln(l=1∑LKedqikl⊤)−LK1j=1∑LKdqikj⊤−lnLK
解释:
- 公式中, q q q 是均匀分布,表示在没有显著注意力的情况下每个键被等概率关注。
- p p p 是真实的注意力分布,取决于每个查询和键的点积关系。
- KL 散度 用于衡量两个概率分布之间的差异: q q q 和 p p p。这里用于评估注意力分布与均匀分布之间的偏离程度。
稀疏度量定义
在忽略常数项后,稀疏度量可以简化为:
M ( q i , K ) = ln ( ∑ j = 1 L K e q i k j ⊤ d ) − 1 L K ∑ j = 1 L K q i k j ⊤ d (2) M(q_i, K) = \ln \left( \sum_{j=1}^{L_K} e^{\frac{q_i k_j^\top}{\sqrt{d}}} \right) - \frac{1}{L_K} \sum_{j=1}^{L_K} \frac{q_i k_j^\top}{\sqrt{d}} \tag{2} M(qi,K)=ln(j=1∑LKedqikj⊤)−LK1j=1∑LKdqikj⊤(2)
解释:
-
第一项是查询 $ q_i $ 对所有键的 对数-和-指数(Log-Sum-Exp, LSE),即:
LSE ( q i , K ) = ln ( ∑ j = 1 L K e q i k j ⊤ d ) \text{LSE}(q_i, K) = \ln \left( \sum_{j=1}^{L_K} e^{\frac{q_i k_j^\top}{\sqrt{d}}} \right) LSE(qi,K)=ln(j=1∑LKedqikj⊤)
它通常用于计算软最大值,从而度量各个键在查询 $ q_i $ 的作用下的总体影响。 -
第二项是所有键的点积值的 算术平均值,表示为:
1 L K ∑ j = 1 L K q i k j ⊤ d \frac{1}{L_K} \sum_{j=1}^{L_K} \frac{q_i k_j^\top}{\sqrt{d}} LK1j=1∑LKdqikj⊤
它反映了键对查询的整体平均响应。
ProbSparse自注意力机制
基于提出的稀疏度量方法,我们设计了ProbSparse自注意力机制,其中每个键(key)只与前 u u u个占主导地位的查询(queries)进行关联。具体形式如下:
A ( Q , K , V ) = Softmax ( Q K ⊤ d ) V (3) A(Q, K, V) = \text{Softmax} \left( \frac{Q K^\top}{\sqrt{d}} \right)V \tag{3} A(Q,K,V)=Softmax(dQK⊤)V(3)
其中, Q Q Q 是一个与查询 q q q 相同大小的稀疏矩阵,它只包含在稀疏度量 M ( q , K ) M(q, K) M(q,K) 下前 u u u个查询。由一个常数采样因子 c c c 控制,我们设置 u = c ⋅ ln L Q u = c \cdot \ln L_Q u=c⋅lnLQ,这使得ProbSparse自注意力只需计算每个查询-键对的 O ( ln L Q ) O(\ln L_Q) O(lnLQ) 点积,且该层的内存使用保持在 O ( L K ln L Q ) O(L_K \ln L_Q) O(LKlnLQ)。
在多头注意力的角度下,这种注意力机制为每个头生成了不同的稀疏查询-键对,从而避免了严重的信息损失。
问题与解决方案
然而,要计算所有查询的稀疏度量 M ( q i , K ) M(q_i, K) M(qi,K),需要计算每个查询-键对的点积,这导致时间复杂度为 O ( L Q L K ) O(L_Q L_K) O(LQLK),并且LSE操作(Log-Sum-Exp)可能存在数值稳定性问题。为了提高效率,我们提出了一个经验近似方法来快速获取查询稀疏性度量。
引理1:
对于每个查询
q
i
∈
R
d
q_i \in \mathbb{R}^d
qi∈Rd 和键
k
j
∈
R
d
k_j \in \mathbb{R}^d
kj∈Rd,有如下界限:
ln
L
K
≤
M
(
q
i
,
K
)
≤
max
j
{
q
i
k
j
⊤
d
}
−
1
L
K
∑
j
=
1
L
K
q
i
k
j
⊤
d
+
ln
L
K
\ln L_K \leq M(q_i, K) \leq \max_j \left\{ \frac{q_i k_j^\top}{\sqrt{d}} \right\} - \frac{1}{L_K} \sum_{j=1}^{L_K} \frac{q_i k_j^\top}{\sqrt{d}} + \ln L_K
lnLK≤M(qi,K)≤jmax{dqikj⊤}−LK1j=1∑LKdqikj⊤+lnLK
当
q
i
∈
K
q_i \in K
qi∈K 时,上述不等式同样成立。(详细证明见附录D.1)
稀疏度量的近似方法
基于引理1,我们提出了最大-均值度量,如下:
M ( q i , K ) = max j { q i k j ⊤ d } − 1 L K ∑ j = 1 L K q i k j ⊤ d (4) M(q_i, K) = \max_j \left\{ \frac{q_i k_j^\top}{\sqrt{d}} \right\} - \frac{1}{L_K} \sum_{j=1}^{L_K} \frac{q_i k_j^\top}{\sqrt{d}} \tag{4} M(qi,K)=jmax{dqikj⊤}−LK1j=1∑LKdqikj⊤(4)
通过边界松弛的方式,该公式在长尾分布下近似成立(见附录D.2)。在长尾分布中,我们只需随机采样 U = L K ln L Q U = L_K \ln L_Q U=LKlnLQ 个点积对来计算 M ( q i , K ) M(q_i, K) M(qi,K),即将其他点积对视为零。然后从这些采样的点积中选择稀疏的Top- u u u查询作为 Q Q Q。
注意:在稀疏度量 M ( q i , K ) M(q_i, K) M(qi,K) 中,最大算子对零值不敏感,且在数值上是稳定的。
复杂度分析
在实际应用中,查询和键的输入长度在自注意力计算中通常是相等的,即 L Q = L K = L L_Q = L_K = L LQ=LK=L。因此,总的ProbSparse自注意力机制的时间复杂度和空间复杂度为 O ( L ln L ) O(L \ln L) O(LlnL)。
如何筛选筛选“积极”的q
这样我们可以得到每个q的 M 得分,得分越大这个q越“积极”。
然后我们在全部的q里选择 M 得分较大的前U个,定义为“积极”的q。来进行QKV矩阵乘法的计算。(U的取值根据实际情况来定,原论文中序列长度为96,作者定义U=25,即选择得分较大的25个Q。)
明白了如何选择“积极”的q之后,大家肯定会想
- 为了求解这个度量得分 M ,还是要计算全部的QK点积,这样难道不是更“复杂”了吗?并没有减少计算量或者加快计算速度。
- 而且只计算“积极”的Q,“懒惰”的q就完全抛弃吗?矩阵的形状不就发生了变化吗?这会影响后续的计算吗?
我们来看看作者是如何解决这两个问题的,这部分隐藏在作者的实际代码实现里。
这里首先看第一点度量得分 M 的计算,我们只是想用这个得分去筛选“积极”的q,用所有的k参与计算,计算量确实太大了。实际上并没有计算全部的QK点积,而是进行了一个抽样。
正常情况下如上推导,将每个“积极”的Q和所有k(原论文中是96个k)计算,但在论文源码的实践中,在计算前会随机选取一部分k(原论文中是25个k)来计算,也可以作为它的分布。
直观的从上图可以看出。我们只选取9个k也可以大致知道这个曲线变化的情况。
由此,我们只需要一部分的k就可以对全部Q的“积极”性进行排序,然后进行选择。
“懒惰”的q是不是就完全不要了呢?
根据上述的内容,我们允许每个k仅关注U个“积极”的q来获得ProbSparse自注意力:
A
(
Q
,
K
,
V
)
=
Softmax
(
Q
‾
K
⊤
d
)
V
A(Q, K, V) = \text{Softmax}\left(\frac{\overline{Q}K^\top}{\sqrt{d}}\right)V
A(Q,K,V)=Softmax(dQK⊤)V
其中, Q ‾ ∈ R L Q × d \overline{Q} \in \mathbb{R}^{L_Q \times d} Q∈RLQ×d 就是top u个queries选拔后的。
回顾一下原始的Transformer计算时的过程:
我们按照原论文中的数据,假设序列长度为96。
这里的维度是:
softmax ( Q K T d ) ∈ R 96 × 96 \text{softmax} \left( \frac{QK^T}{\sqrt{d}} \right) \in \mathbb{R}^{96 \times 96} softmax(dQKT)∈R96×96
V ∈ R 96 × 64 V \in \mathbb{R}^{96 \times 64} V∈R96×64
因此最终输出为:
Z ∈ R 96 × 64 Z \in \mathbb{R}^{96 \times 64} Z∈R96×64
如果我们选择 U = 25 U=25 U=25 个“积极”的查询 Q Q Q 来计算:
softmax ( Q ˉ K T d ) ∈ R 25 × 96 \text{softmax} \left( \frac{\bar{Q}K^T}{\sqrt{d}} \right) \in \mathbb{R}^{25 \times 96} softmax(dQˉKT)∈R25×96
V ∈ R 96 × 64 V \in \mathbb{R}^{96 \times 64} V∈R96×64
因此最终输出为:
Z ∈ R 25 × 64 Z \in \mathbb{R}^{25 \times 64} Z∈R25×64
对于剩余的“懒惰”的查询 q q q,作者采取的办法是,用 V V V 向量的平均来代替这些查询对应的时间点的向量。
2. Embedding
嵌入层包含三种主要的嵌入方式:
- 值嵌入(Value Embedding)
- 位置嵌入(Positional Embedding)
- 时间嵌入(Temporal Embedding)
从上图看到,在原始向量上不止增加了Transformer架构必备的PositionEmbedding(位置编码)还增加了与时间相关的各种编码。
在 LSTF 问题中,捕获远程独立性的能力需要全局信息,例如分层时间戳(周、月和年)和不可知时间戳(假期、事件)。
具体在这里增加什么样的GlobalTimeStamp还需要根据实际问题来确认,如果计算高铁动车车站的人流量,显然“假期”的时间差就是十分重要的。如果计算公交地铁等通勤交通工具的人流量,显然“星期”可以更多的揭示是否为工作日。
3. Encoder
编码器:在内存限制下处理更长的序列输入
编码器被设计用于提取长序列输入中的稳健的远程依赖关系。在输入表示之后,第
t
t
t 个序列输入
X
t
X^t
Xt 变形为一个矩阵
X
en
t
∈
R
L
x
×
d
model
X^t_{\text{en}} \in \mathbb{R}^{L_x \times d_{\text{model}}}
Xent∈RLx×dmodel。为了更清晰地展示编码器的结构,图3中给出了编码器的简图。
在这个架构中我们拿出一个Encoder(也就是一个梯形)来看作者在哪些方面做了改进。
论文中提出了一种新的EncoderStack结构,由多个Encoder和蒸馏层组合而成。我们拿出单个Encoder来看,如下图:
这里先看一下左边绿色的部分,是Encoder的输入。由上面深绿色的scalar和下面浅绿色的stamp组成。
- 深绿色的scalar就相当于我们之前Transformer里的input-embedding 是我们原始输入的向量。
- 浅绿色的stamp包含之前Transformer里的 Positional Ecoding(位置编码)来表示输入序列的相对位置。在时序预测任务中,这个stamp其实由LocalTimeStamp(也就是位置编码)和GobalTimeStamp(与时序相关的编码)共同构成。
我们在后面编码部分再详细展开Encoder的输入部分。我们来看一下后面Encoder的结构
自注意力蒸馏(Self-attention Distilling)
作为ProbSparse自注意力机制的自然结果,编码器的特征映射中包含了冗余的值 V V V 的组合。为了减少冗余,我们使用了蒸馏操作,该操作优先保留主导特征,使得下一层的自注意力特征图更加集中。这一操作在时间维度上大幅裁剪了输入数据,如图3中注意力块的n头权重矩阵(重叠的红色方块)所示。受膨胀卷积(Yu等,2017;Gupta和Rush,2017)的启发,我们的“蒸馏”过程将第 j j j 层的输入传递到第 ( j + 1 ) (j + 1) (j+1) 层,具体过程如下:
X j + 1 t = MaxPool ( ELU ( Conv1d ( [ X j t ] AB ) ) ) (5) X^t_{j+1} = \text{MaxPool} \left( \text{ELU} \left( \text{Conv1d}([X^t_j]_{\text{AB}}) \right) \right) \tag{5} Xj+1t=MaxPool(ELU(Conv1d([Xjt]AB)))(5)
其中, [ ⋅ ] AB [·]_{\text{AB}} [⋅]AB 代表注意力块,它包含了多头ProbSparse自注意力以及一些基本操作, Conv1d ( ⋅ ) \text{Conv1d}(·) Conv1d(⋅) 是在时间维度上执行的一维卷积操作(核宽度为3),并伴随了ELU(Clevert等,2016)激活函数。之后,我们添加了一个步幅为2的最大池化层,对 X t X^t Xt 进行下采样,堆叠一层后将 X t X^t Xt 缩小为一半,从而将整个内存使用量减少到 O ( ( 2 − ε ) L log L ) O((2 - \varepsilon) L \log L) O((2−ε)LlogL),其中 ε \varepsilon ε 是一个较小的数。
为了增强蒸馏操作的鲁棒性,我们构建了主堆栈的副本,每个副本的输入大小逐渐减少,像金字塔一样逐层减少自注意力蒸馏层的数量,最终使得它们的输出维度对齐。这样,我们可以将所有堆栈的输出进行拼接,得到编码器的最终隐藏表示。
详细解释:
-
自注意力蒸馏:自注意力机制往往会带来冗余的信息组合,特别是在长序列任务中,因此需要蒸馏操作来集中保留最重要的信息。通过该操作,输入的时间维度得到了显著减少,同时仍保留了主要特征。这类似于卷积操作中的膨胀卷积,通过扩大感受野获取更大的上下文信息。
-
卷积与池化:使用一维卷积(Conv1d)和ELU激活函数,处理时间维度信息;随后,通过最大池化(MaxPool)进行下采样,将输入长度减半,进一步减少内存使用。
-
内存优化:该机制通过减少每一层的输入大小,使得内存使用量大大降低,且通过金字塔结构减少层数,确保输出维度一致性。
-
金字塔结构:编码器的最终输出通过对多层堆栈进行拼接得到。随着层数的减少,每层输出的维度保持一致,确保最终隐藏表示的信息完备性和有效性。
这种设计使得编码器能够在有限的内存条件下高效处理长序列输入,并通过蒸馏和金字塔结构保留重要特征,同时避免信息丢失。
EncoderStack结构介绍
作者为了提高encoder的鲁棒性,还提出了一个strick。上面的Encoder是主stack,输入整个embedding后经过了三个Attention Block,最终得到Feature Map。
还可以再复制一份具有一半输入的embedding(直接取96个时间点的后48个),让它让经过两个Attention Block(标注处理流程是“similar operation”也就是相同的处理流程),最终会得到和上面维度相同的Feature Map,然后把两个Feature Map拼接。作者认为这种方式对短周期的数据可能更有效一些。
输入:32
×
\times
× 8
×
\times
× 96
×
\times
× 512
输出:32
×
\times
× 8
×
\times
× 48
×
\times
× 512
论文中提出的EncoderStack 其实是由多个Encoder 和蒸馏层组合而成的
那么我们来详细解释一下上面的这张图。
1.每个水平stack代表一个单独的Encoder Module;
啥意思呢?
也就是说,下面用红色笔圈出来的这一坨是第一个stack
而剩下那部分是第二个stack
下面的stack还写了similar operation
2.上面的stack是主stack,它接收整个输入序列,而第二个stack取输入的一半,并且第二个stack扔掉一层自我注意蒸馏层的数量,使这两个stack的输出维度使对齐的;
这句话的意思是,红色圈圈的部分中输入减半
,作为第二个stack的输入。(这里减半的处理方法就是直接用96个时间点的后48个得到一半)
3.红色层是自我注意机制的点积矩阵,通过对各层进行自我注意蒸馏得到级联降低;
这一句说的就是蒸馏的操作了,也就是上面手画图例的convLayer,还是通过一维卷积来进行蒸馏的。
4.连接2个stack的特征映射作为编码器的输出。
最后很简单,把手画图里的Encoder1 和 Encoder2 25和26的输出连接起来,就能得到最终的51维输出了。(这里的51或许还是因为卷积取整,导致这个数看起来不太整)
有下面的热力图发现,使用这样的注意力机制和Encoder结构,特征更为明显且与之前的模式基本一致。
4. Decoder
解码器:通过一次前向过程生成长序列输出
解码器采用了标准的结构(Vaswani等,2017),如图2所示,由两层相同的多头注意力层堆叠而成。然而,在长序列预测中,我们采用了一种生成式推理方法,以缓解长序列预测中速度的下降问题。
我们将解码器输入如下向量:
X de t = Concat ( X token t , X 0 t ) ∈ R ( L token + L y ) × d model X^t_{\text{de}} = \text{Concat}(X^t_{\text{token}}, X^t_0) \in \mathbb{R}^{(L_{\text{token}} + L_y) \times d_{\text{model}}} Xdet=Concat(Xtokent,X0t)∈R(Ltoken+Ly)×dmodel
其中, X token t ∈ R L token × d model X^t_{\text{token}} \in \mathbb{R}^{L_{\text{token}} \times d_{\text{model}}} Xtokent∈RLtoken×dmodel 是起始标记(start token), X 0 t ∈ R L y × d model X^t_0 \in \mathbb{R}^{L_y \times d_{\text{model}}} X0t∈RLy×dmodel 是目标序列的占位符(值设为0)。在ProbSparse自注意力计算中,应用了遮掩多头注意力机制(masked multi-head attention),通过将遮掩的点积值设为 − ∞ -\infty −∞ 来防止每个位置关注到未来的时刻位置,从而避免自回归问题。最后,通过全连接层获取最终输出,其输出维度 d y d_y dy 取决于我们执行的是单变量预测还是多变量预测。
生成式推理
Decoder的输入如下:
在 Informer 模型的解码器中,输入序列由两部分拼接而成:起始标记(Start Token) 和 预测序列占位符,分别对应
X
token
X_{\text{token}}
Xtoken 和
X
0
X_0
X0。
解码器的输入可以表示为:
X
de
=
{
X
token
,
X
0
}
X_{\text{de}} = \{ X_{\text{token}}, X_0 \}
Xde={Xtoken,X0}
- X token ∈ R L token × d model X_{\text{token}} \in \mathbb{R}^{L_{\text{token}} \times d_{\text{model}}} Xtoken∈RLtoken×dmodel:表示开始的 token(起始标记),即已知的序列片段。它通常选取预测序列之前的一段已知序列,例如过去的几天的温度数据。
- X 0 ∈ R L y × d model X_0 \in \mathbb{R}^{L_y \times d_{\text{model}}} X0∈RLy×dmodel:表示预测序列的占位符,其维度与目标预测序列一致,初始化时通常用 0 填充。
如果我们想要预测7天的温度,decoder就需要输入前面1-7天的温度,后面用0填充8-14天需要预测的温度的位置,这就是一种Mask的机制。
-
已知的温度数据(Start Token, X token X_{\text{token}} Xtoken):
- 例如,在预测未来 7 天的温度时,我们可以使用前 48 个时间步的已知温度数据作为起始标记。这些数据包含了历史的上下文信息,为解码器提供了预测未来值的重要依据。
- 因此, X token X_{\text{token}} Xtoken 的维度为 48 × d model 48 \times d_{\text{model}} 48×dmodel。
-
预测序列的占位符( X 0 X_0 X0):
- 对于未来 7 天的预测,我们需要一个长度为 24 个时间步的占位符,这些占位符的初始值设为 0。这些 0 值会被逐渐替换为模型的预测结果。
- X 0 X_0 X0 的维度为 24 × d model 24 \times d_{\text{model}} 24×dmodel。
因此,解码器的输入序列
X
de
X_{\text{de}}
Xde 的整体维度为:
X
de
∈
R
(
48
+
24
)
×
d
model
=
R
72
×
d
model
X_{\text{de}} \in \mathbb{R}^{(48 + 24) \times d_{\text{model}}} = \mathbb{R}^{72 \times d_{\text{model}}}
Xde∈R(48+24)×dmodel=R72×dmodel
这种输入方式适用于长序列时间序列预测,尤其是在处理长时间段的数据时,它能够有效减少计算时间,并且可以一次性输出整个预测序列。
起始标记在自然语言处理中的“动态解码”(Devlin等,2018)中已被高效应用,我们将其扩展为生成式推理方式。与选择特定的标记作为token不同,我们从输入序列中采样长度为 L token L_{\text{token}} Ltoken 的子序列,例如从输出序列之前的某段已知数据中选择。
例如,在预测168个点(实验中为7天的温度预测)时,我们会选择目标序列之前的已知5天数据作为“start-token”,并将生成式推理解码器的输入设置为 X de = { X 5d , X 0 } X_{\text{de}} = \{X_{\text{5d}}, X_0\} Xde={X5d,X0},其中 X 0 X_0 X0 包含目标序列的时间戳,即目标周的上下文信息。这样,解码器可以通过一次前向过程生成预测输出,而无需像传统的编码器-解码器架构那样进行耗时的“动态解码”。
损失函数
我们选择均方误差(MSE)损失函数,用于对目标序列的预测进行优化。损失从解码器的输出开始,反向传播回整个模型中。
主要要点:
- 遮掩多头注意力:在ProbSparse自注意力计算中,遮掩未来的时间步,防止自回归。
- 生成式推理:采用一个起始标记(start token)作为输入,通过一次前向推理生成整个输出,避免了动态解码的开销。
- 损失函数:使用MSE损失函数进行优化,针对目标序列的预测。
这种生成式解码器设计,能够在保持高效计算的同时,处理长序列的生成问题,从而在长时间序列预测任务中表现优异。