Skip to content

Level 2 数据进入 Informer

Abstract

这一篇只讲一件事:

当前 batch 四元组,是怎样在 _process(...) 里被改造成 Informer 四输入的。

1. 上下文

上一层:

下一层:

这一层的出口是:

python
Informer.forward(x_enc, x_mark_enc, x_dec, x_mark_dec)

1.5 本层入口参数含义

  • input
    • encoder 侧历史数值窗口
  • target
    • decoder 侧监督窗口,长度是 label_len + pred_len
  • input_mark
    • encoder 侧时间特征
  • target_mark
    • decoder 侧时间特征
  • label_len
    • 决定 x_dec 前半段历史长度
  • pred_len
    • 决定 x_dec 后半段零占位长度

1.6 本层输出含义

本层输出不是最终预测结果,而是:

python
Informer.forward(x_enc, x_mark_enc, x_dec, x_mark_dec)

含义是:

batch 四元组已经被翻译成 Informer 能直接接收的四输入。

2. 顺序图

3. 抽象树

4. 先固定真实 batch

当前真实例子里:

  • input.shape = (4, 96, 7)
  • target.shape = (4, 72, 7)
  • input_mark.shape = (4, 96, 4)
  • target_mark.shape = (4, 72, 4)

这里几个参数已经开始直接控制张量了:

  • seq_len = 96
    • 控制 input.shape[1]
  • label_len = 48
    • 控制 x_dec 前半段历史长度
  • pred_len = horizon = 24
    • 控制 x_dec 后半段零占位长度
  • enc_in = dec_in = c_out = 7
    • 控制最后一维,也就是变量通道数

因此:

text
target 的长度 = label_len + pred_len = 48 + 24 = 72

5. 代码块:_process(...)

位置:

完整代码:

python
def _process(self, input, target, input_mark, target_mark):
    dec_input = torch.zeros_like(target[:, -self.config.horizon :, :]).float()
    dec_input = (
        torch.cat([target[:, : self.config.label_len, :], dec_input], dim=1)
        .float()
        .to(input.device)
    )
    output = self.model(input, input_mark, dec_input, target_mark)

    return {"output": output}

带中文注释的完整代码:

python
def _process(self, input, target, input_mark, target_mark):
    # input        = encoder 侧数值输入
    # target       = decoder 侧监督窗口,长度 = label_len + pred_len
    # input_mark   = encoder 侧时间特征
    # target_mark  = decoder 侧时间特征

    # 第一步:从 target 最后 pred_len 段的形状出发,造未来零占位
    dec_input = torch.zeros_like(target[:, -self.config.horizon :, :]).float()

    # 第二步:把 target 前 label_len 段的历史尾部拼到前面
    dec_input = (
        torch.cat([target[:, : self.config.label_len, :], dec_input], dim=1)
        .float()
        .to(input.device)
    )

    # 第三步:把四输入送进底层模型
    output = self.model(input, input_mark, dec_input, target_mark)

    return {"output": output}

6. 贴着 _process(...) 代码讲 toy 例子

固定 toy 参数:

  • B = 1
  • label_len = 2
  • pred_len = horizon = 2
  • C = 2

固定 toy batch:

python
input = [
    [1, 10],
    [2, 11],
    [3, 12],
    [4, 13],
]  # (1, 4, 2)

target = [
    [3, 12],
    [4, 13],
    [5, 14],
    [6, 15],
]  # (1, 4, 2)

input_mark = [
    [1, 1, 1, 1],
    [1, 1, 1, 2],
    [1, 1, 1, 3],
    [1, 1, 1, 4],
]  # (1, 4, 4)

target_mark = [
    [1, 1, 1, 3],
    [1, 1, 1, 4],
    [1, 1, 1, 5],
    [1, 1, 1, 6],
]  # (1, 4, 4)

6.1 对应代码第 1 段:取最后 pred_len 段并造零占位

对应代码:

python
dec_input = torch.zeros_like(target[:, -self.config.horizon :, :]).float()

当前这里:

  • horizon = pred_len = 2

所以先取:

python
target[:, -2:, :] = [
    [5, 14],
    [6, 15],
]  # (1, 2, 2)

然后做:

python
torch.zeros_like(...)

得到:

python
future_zeros = [
    [0, 0],
    [0, 0],
]  # (1, 2, 2)

这里参数和张量的对应关系是:

  • pred_len = 2
    • 决定未来零占位有几步
  • C = dec_in = 2
    • 决定每一步有几个通道

6.2 对应代码第 2 段:取前 label_len 段历史尾部

对应代码:

python
target[:, : self.config.label_len, :]

当前这里:

  • label_len = 2

所以取到:

python
history_tail = [
    [3, 12],
    [4, 13],
]  # (1, 2, 2)

这里参数和张量的对应关系是:

  • label_len = 2
    • 决定 decoder 端保留多少步“已知历史”

6.3 对应代码第 2 段:拼成 dec_input

对应代码:

python
dec_input = torch.cat([history_tail, future_zeros], dim=1)

拼接结果:

python
dec_input = [
    [3, 12],
    [4, 13],
    [0, 0],
    [0, 0],
]  # (1, 4, 2)

这里最关键的关系是:

text
x_dec 的长度 = label_len + pred_len

当前 toy 例子里:

text
4 = 2 + 2

真实例子里:

text
72 = 48 + 24

6.4 对应代码第 3 段:正式变成 Informer 四输入

对应代码:

python
output = self.model(input, input_mark, dec_input, target_mark)

也就是:

python
x_enc      = input
x_mark_enc = input_mark
x_dec      = dec_input
x_mark_dec = target_mark

当前 toy 例子里,它们分别是:

python
x_enc = [
    [1, 10],
    [2, 11],
    [3, 12],
    [4, 13],
]  # (1, 4, 2)

x_mark_enc = [
    [1, 1, 1, 1],
    [1, 1, 1, 2],
    [1, 1, 1, 3],
    [1, 1, 1, 4],
]  # (1, 4, 4)

x_dec = [
    [3, 12],
    [4, 13],
    [0, 0],
    [0, 0],
]  # (1, 4, 2)

x_mark_dec = [
    [1, 1, 1, 3],
    [1, 1, 1, 4],
    [1, 1, 1, 5],
    [1, 1, 1, 6],
]  # (1, 4, 4)

7. target -> x_dec 过程图

8. 这一层真正要固定什么

  1. _process(...) 不是 Informer 内部计算本体
  2. 它做的是:
text
batch 四元组 -> Informer 四输入
  1. 这里最重要的代码不是哪一行 attention,而是:
python
target -> x_dec
  1. 这里最重要的参数不是 d_model,而是:
  • label_len
  • pred_len
  • enc_in / dec_in

因为它们直接决定了你送进 Informer 的张量长什么样。

9. 下一步

继续看:

*记录并在线阅读我的笔记*