Appearance
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
- decoder 侧监督窗口,长度是
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 = 725. 代码块:_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 = 1label_len = 2pred_len = horizon = 2C = 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 + 246.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. 这一层真正要固定什么
_process(...)不是 Informer 内部计算本体- 它做的是:
text
batch 四元组 -> Informer 四输入- 这里最重要的代码不是哪一行 attention,而是:
python
target -> x_dec- 这里最重要的参数不是
d_model,而是:
label_lenpred_lenenc_in / dec_in
因为它们直接决定了你送进 Informer 的张量长什么样。
9. 下一步
继续看: