TimeXer代码阅读
模块
EnEmbedding
用于将时间序列嵌入为 patch-wise 与 global 的 tokens, 此处编码方式为“RoPE” 以及 “线性变换”,最终得到编码结果为两者相加,然后再将编码后的序列与 global_token(glb_token) 在patch的维度拼接起来:
此处输入 $x \in \mathbb{R}^{16,1,168}$ 为 (batch_size, var_num, seq_len), 然后经过编码转化为 $\mathbb{R}^{16, 1, 10, 512}$ (batch_size, var_num, patch_num, d_model)。与 global_token 堆叠为 $\mathbb{R}^{16,1,11,512}$ 输出。
DataEmbedding_inverted
这个模块在模型中主要用于 外部变量 的嵌入,即 ex_embedding , 输入外部变量和时间变量。将外部变量与时间变量按照通道维度拼接后输入线性层中进行嵌入,得到 $\mathbb{R}^{16, 6, 512}$ 即 (batch_size, exvar_num + temporal_num, d_model)。
Encoder
编码器,输入上面两模块(EnEmbedding 与 DataEmbedding_inverted)嵌入得到的 token 进行注意力机制:
Attention
注意力机制的实现流程:1. x通过线性层映射为 $\text{head_num} \times\text{d_model}$ 维度的queries, keys, values,这样后面进行分头操作只需要再增加一个维度。2. 进行 $\text{Softmax}(\frac{QK^T}{\sqrt{ d_{k} }})V$。此处的矩阵乘法采用 torch.einsum 进行,该函数在注意力机制中常如下使用:
1 | scores = torch.einsum("blhe,bshe->bhls", queries, keys) |
此处 “blhe,bshe->bhls” 代表
$$
[QK^T]_{b,h,l,s}=\sum_{e}Q_{b,l,h,e}K_{b,s,h,e}
$$
同时 torch.softmax 的操作在最后一个维度代表:在最后一个维度之和为1,即:
$$
\sum_{s} W_{b,h,l,s}= 1
$$
最后再将多头注意力输出结果输入至线性层中映射回 d_model 维度。
Cross Attention
相较于普通Attention机制中,queries 与 keys 的通道数相同, cross-attention 的通道数并不相同。这里作者采用的是 全局 token 与 patch token 之间的 cross-attention, 其中 queries 为全局 token. 采用 queries 作为全局 token 可以保证:1. 矩阵运算的正确性,如果选择 keys 或者 values 则需要同时改变 2 个;2. 如果选择 values, 则最终输出的结果通道数为 6, 而非 1.
Encoder
然后按照如下过程处理:
en_patch-en_patch: Full Attention -> 残差连接 -> 层归一化
en_global-ex_global: Cross Attention -> 残差连接 -> 层归一化
以上输出在通道维度(C)上拼接。并对于 d_model 维度使用一次 Linear + GELU + Linear(512 -> 2048 -> 512) 后进行残差连接。最后输入 层归一化。
多个Encoder堆叠
以上就是单层的Encoder架构,3个 Encoder 堆叠后在进行一次层归一化得到最终的输出,然后展平后输入 Linear 层转化为 预测序列长度 的片段

