Skip to content

Level2 数据进入 DLinear

Abstract

这一篇对应 00-DLinear总览与Level树Level 2

它只讲一件事:

batch 四元组怎样经过 _process(...),变成 DLinear 的真正输入。

1. 当前层第一性

这一层存在的第一性是:

把框架里的统一 batch 四元组,翻译成 DLinear.forward(...) 的四输入。

同时要钉死一个关键事实:

虽然 DLinear 也走统一四输入接口,但 forecasting 路径里真正决定预测的是 x_enc

也就是说,这一层的意义不是“DLinear 真需要一个 decoder”,而是:

  • TFB 给了统一的接口壳
  • DLinear 接受这个壳
  • 但它内部只强依赖其中一部分输入

2. 上下文

父节点:

下一层:

当前入口接口:

python
_process(input, target, input_mark, target_mark)

当前出口接口:

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

3. 当前真实例子里的 batch 是什么

当前真实运行例子里:

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

这些张量的语义:

  • input
    • encoder 侧历史数值窗口。
  • target
    • decoder 侧监督窗口,长度 = label_len + pred_len = 48 + 24 = 72
  • input_mark
    • input 这 96 个时间步对应的时间特征。
  • target_mark
    • target 这 72 个时间步对应的时间特征。

4. 顺序图

5. 抽象树

6. _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}

7. 中文注释版完整代码

python
def _process(self, input, target, input_mark, target_mark):
    # 第一步:先造未来 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)
    )

    # 第三步:统一调用底层模型 forward
    output = self.model(input, input_mark, dec_input, target_mark)

    return {"output": output}

8. 固定 toy 例子

固定 toy 参数(与所有文档对齐):

  • B = 2
  • seq_len = 6
  • label_len = 3
  • pred_len = horizon = 2
  • enc_in = 3

因此 target.shape = (2, label_len+pred_len, enc_in) = (2, 5, 3)

固定 toy 输入(只展示 batch=0):

text
input[0]:          shape = (6, 3)
  [ [1,  10, 100],   ← t=0
   [2,  11, 101],   ← t=1
   [3,  12, 102],   ← t=2
   [4,  13, 103],   ← t=3
   [5,  14, 104],   ← t=4
   [6,  15, 105] ]   ← t=5
全批 input.shape = (2, 6, 3)

target[0]:         shape = (5, 3)   ← label_len(3) + pred_len(2) = 5
  [ [4,  13, 103],   ← 历史尾部 t=3(与 input 重叠)
   [5,  14, 104],   ← 历史尾部 t=4
   [6,  15, 105],   ← 历史尾部 t=5
   [7,  16, 106],   ← 未来 t=6(监督真值)
   [8,  17, 107] ]   ← 未来 t=7(监督真值)
全批 target.shape = (2, 5, 3)

9. 代码块 1:先造未来零占位

代码:

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

9.1 输入/输出语义

输入:

  • target[:, -pred_len:, :]
    • 取 target 最后 pred_len 步,仅用其形状作模板。

输出:

  • dec_input
    • 与未来监督区同 shape 的零张量,形状 (2, 2, 3)

9.2 toy 张量逐步演变

先取 target[:, -2:, :](最后 pred_len=2 步):

text
batch=0:
  [ [7, 16, 106],
   [8, 17, 107] ]

torch.zeros_like(...) 后:

text
dec_input(此时 shape=(2, 2, 3)):
batch=0:
  [ [0, 0, 0],
   [0, 0, 0] ]

DLinear 不需要这个零占位,但框架统一接口要求构造。

10. 代码块 2:拼上历史尾部

代码:

python
torch.cat([target[:, : self.config.label_len, :], dec_input], dim=1)

10.1 输入/输出语义

输入:

  • target[:, :label_len, :]:历史尾部,shape (2, 3, 3)
  • dec_input:零占位,shape (2, 2, 3)

输出:

  • x_dec:shape (2, 5, 3),长度 = label_len + pred_len = 5

10.2 toy 张量逐步演变

target[:, :3, :](前 label_len=3 步):

text
batch=0:
  [ [4,  13, 103],
   [5,  14, 104],
   [6,  15, 105] ]

和零占位拼接:

text
x_dec[0], shape=(5,3):
  [ [4,  13, 103],   ← 历史尾部
   [5,  14, 104],
   [6,  15, 105],
   [0,   0,   0],   ← 未来零占位
   [0,   0,   0] ]

对 Informer:这是 decoder 的核心输入。对 DLinear:DLinear.forward 接收它但根本不使用它。

11. 代码块 3:四输入进入 DLinear

代码:

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

11.1 四输入对应关系

x_enc      = input        (2, 6, 3)  ← DLinear 唯一真正使用的输入
x_mark_enc = input_mark   (2, 6, 4)  ← DLinear forward 里接收但不用
x_dec      = dec_input    (2, 5, 3)  ← DLinear forward 里接收但不用
x_mark_dec = target_mark  (2, 5, 4)  ← DLinear forward 里接收但不用

输出:

  • output.shape = (2, 2, 3)(B, pred_len, enc_in)

11.2 最关键的解释

x_mark_encx_decx_mark_dec 三个输入由 TFB adapter 统一构造,但 DLinear 的 forward 函数签名虽然接收它们,内部运算完全不使用它们。 DLinear 的所有计算仅依赖 x_enc

12. 这一层最该固定什么

  1. DLinear 仍然走统一 _process(...) 接口。
  2. 所以 x_dec 仍然会被构造。
  3. 但 DLinear 的 forecasting 主体几乎只依赖 x_enc
  4. 这一层的根本作用,是把框架 batch 翻译成模型可接受的统一四输入。

13. 下一步

继续看:

补查 torch 算子:

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