Appearance
4B SeasonalTrend 线性头
Abstract
这一篇是 04-Level4-encoder分解与线性预测总览 里的
4B子块。它只讲一件事:
seasonal 和 trend 怎样各自从
seq_len线性映射到pred_len,再相加得到最终预测。
1. 当前层第一性
这一层存在的第一性是:
把分解后的两路序列各自做最简单的线性外推,而不是再套复杂编码器。
换句话说,DLinear 的预测能力在这里最集中地体现出来:
- seasonal 一条线性头
- trend 一条线性头
- 两路结果相加
2. 上下文
父节点:
下一步:
当前入口接口:
python
seasonal_output = self.Linear_Seasonal(seasonal_init)
trend_output = self.Linear_Trend(trend_init)当前出口接口:
python
x = seasonal_output + trend_output
return x.permute(0, 2, 1)3. 顺序图
4. 抽象树
5. 完整代码
位置:
python
def encoder(self, x):
seasonal_init, trend_init = self.decompsition(x)
seasonal_init, trend_init = seasonal_init.permute(0, 2, 1), trend_init.permute(
0, 2, 1
)
if self.individual:
seasonal_output = torch.zeros(
[seasonal_init.size(0), seasonal_init.size(1), self.pred_len],
dtype=seasonal_init.dtype,
).to(seasonal_init.device)
trend_output = torch.zeros(
[trend_init.size(0), trend_init.size(1), self.pred_len],
dtype=trend_init.dtype,
).to(trend_init.device)
for i in range(self.channels):
seasonal_output[:, i, :] = self.Linear_Seasonal[i](
seasonal_init[:, i, :]
)
trend_output[:, i, :] = self.Linear_Trend[i](trend_init[:, i, :])
else:
seasonal_output = self.Linear_Seasonal(seasonal_init)
trend_output = self.Linear_Trend(trend_init)
x = seasonal_output + trend_output
return x.permute(0, 2, 1)6. 中文注释版完整代码
python
def encoder(self, x):
seasonal_init, trend_init = self.decompsition(x)
# 线性层要吃最后一维 = seq_len
seasonal_init = seasonal_init.permute(0, 2, 1)
trend_init = trend_init.permute(0, 2, 1)
if self.individual:
# 每个变量一套独立线性层
seasonal_output = torch.zeros(...)
trend_output = torch.zeros(...)
for i in range(self.channels):
seasonal_output[:, i, :] = self.Linear_Seasonal[i](seasonal_init[:, i, :])
trend_output[:, i, :] = self.Linear_Trend[i](trend_init[:, i, :])
else:
# 所有变量共享一套 seasonal / trend 线性层
seasonal_output = self.Linear_Seasonal(seasonal_init)
trend_output = self.Linear_Trend(trend_init)
# 两路预测相加
x = seasonal_output + trend_output
# 回到 [B, pred_len, C]
return x.permute(0, 2, 1)7. 固定 toy 例子
沿用上一层固定结果:
text
seasonal_init =
[
[-1/3, -1/3],
[0, 0],
[0, 0],
[1/3, 1/3],
]
trend_init =
[
[4/3, 31/3],
[2, 11],
[3, 12],
[11/3,38/3],
]固定:
seq_len = 4pred_len = 2individual = False
8. 代码块 1:为什么先 permute
代码:
python
seasonal_init = seasonal_init.permute(0, 2, 1)
trend_init = trend_init.permute(0, 2, 1)8.1 输入/输出语义
输入:
(B, seq_len, C)
输出:
(B, C, seq_len)
因为:
nn.Linear(self.seq_len, self.pred_len)作用在最后一维- 所以必须让“时间长度
seq_len”成为最后一维
8.2 toy 张量逐步演变
text
seasonal_init(channel 1) = [-1/3, 0, 0, 1/3]
seasonal_init(channel 2) = [-1/3, 0, 0, 1/3]
trend_init(channel 1) = [4/3, 2, 3, 11/3]
trend_init(channel 2) = [31/3, 11, 12, 38/3]9. 代码块 2:seasonal 线性映射
代码:
python
seasonal_output = self.Linear_Seasonal(seasonal_init)9.1 输入/输出语义
输入:
- 每个变量一条长度为
seq_len的 seasonal 向量
输出:
- 每个变量一条长度为
pred_len的 seasonal 预测向量
9.2 toy 可算过程
假设 Linear_Seasonal 的 toy 权重矩阵是:
text
Ws =
[ [1, 0, 0, 0],
[0, 0, 0, 1] ]这表示:
- 第一个未来步只看历史第一个位置
- 第二个未来步只看历史最后一个位置
对 seasonal 第一个变量:
text
[-1/3, 0, 0, 1/3]做线性映射:
text
future_1 = 1*(-1/3) + 0 + 0 + 0 = -1/3
future_2 = 0 + 0 + 0 + 1*(1/3) = 1/3所以:
text
seasonal_output(channel 1) = [-1/3, 1/3]10. 代码块 3:trend 线性映射
代码:
python
trend_output = self.Linear_Trend(trend_init)10.1 输入/输出语义
输入:
- 每个变量一条长度为
seq_len的 trend 向量
输出:
- 每个变量一条长度为
pred_len的 trend 预测向量
10.2 toy 可算过程
假设 Linear_Trend 的 toy 权重矩阵是:
text
Wt =
[ [0, 1, 0, 0],
[0, 0, 1, 0] ]对 trend 第一个变量:
text
[4/3, 2, 3, 11/3]做线性映射:
text
future_1 = 2
future_2 = 3所以:
text
trend_output(channel 1) = [2, 3]11. 代码块 4:两路相加
代码:
python
x = seasonal_output + trend_output11.1 输入/输出语义
输入:
seasonal_outputtrend_output
输出:
- 最终预测的隐藏结果
(B, C, pred_len)
11.2 toy 张量逐步演变
第一个变量:
text
seasonal_output = [-1/3, 1/3]
trend_output = [2, 3]
相加后 = [5/3, 10/3]第二个变量同理。
12. 代码块 5:回到时间维
代码:
python
return x.permute(0, 2, 1)12.1 输入/输出语义
输入:
(B, C, pred_len)
输出:
(B, pred_len, C)
为什么要这么做:
- TFB 和 forecasting 主链都把时间维放在中间:
(B, 时间, 变量)
12.2 toy 张量逐步演变
最终 toy 输出可写成:
text
[
[5/3, 32/3],
[10/3, 35/3],
]
shape = (1, 2, 2)这意味着:
- 未来第 1 步:两个变量分别预测为
5/3, 32/3 - 未来第 2 步:两个变量分别预测为
10/3, 35/3
13. 当前真实例子里的参数在这层控制什么
seq_len = 96- 两条线性头输入维度。
pred_len = 24- 两条线性头输出维度。
enc_in = 7- 一共有 7 条变量通道被并行预测。
individual = False- 7 个变量共享一套 seasonal / trend 线性头。
14. 当前层最该固定什么
- DLinear 的预测核心就是:
- seasonal 一路线性预测
- trend 一路线性预测
- 两路相加
- 它没有复杂 decoder;预测能力主要来自分解 + 线性外推。
individual=False时,所有变量共享同一套线性头。
15. 下一步
收束回整条链:
补查 torch 算子: