当面对包含数十个特征、数千个序列的业务数据时,传统复杂模型如ARIMA往往力不从心。此时,一种名为TiDE的时间序列预测新方法进入了视野。它不像Transformer那样结构复杂,反而像一个“加强版MLP”,但其预测效果出色且部署简易,非常适合实际业务预测场景。
你可以这样理解:传统时序模型如LSTM、Transformer,其核心是“按时间步逐步推进”,依赖隐藏状态传递历史信息。优点是能“记忆”,但缺点也很明显:面对长序列时,训练缓慢、显存消耗大、部署复杂。
TiDE的设计思路则颇为反直觉:它摒弃了RNN循环和自注意力机制,直接将一整段历史时间窗口的数据“拉平”成一个长向量,再结合节假日、价格等外部特征,全部送入一个多层感知机(MLP)编码器中,从而得到一个代表整个序列的“隐藏表示”。随后,再用一个解码器MLP,将这个表示“展开”为未来多个时间步的预测值。
模型还设计了一条“线性残差支路”,专门捕捉数据中简单的线性趋势。这样一来,复杂的非线性模式由MLP主干学习,而简单的趋势则由线性层处理,两者协同工作,提升了模型的整体表现。
这种设计带来了几个非常实用的优点:
- 结构简单:核心就是全连接层,工程上易于调整,推理速度快。
- 多步预测一步到位:例如需要预测未来24小时,TiDE直接输出一个24维的向量,而非进行耗时的逐步滚动预测。
- 强大的特征容纳能力:在同一个输入窗口内,无论是历史特征、静态特征还是未来已知特征(如未来的节假日安排),都可以拼接在一起进行学习。
下面是一个用PyTorch实现的极简版TiDE,结构遵循论文思想但简化了细节,方便快速理解和使用。
import torch
import torch.nn as nn
import torch.nn.functional as F
class SimpleTiDE(nn.Module):
def __init__(self, input_len: int, # 历史窗口长度,比如 48 个时间步
d_in: int, # 每个时间步的特征维度
output_len: int, # 预测步数,比如未来 24 步
d_hidden: int = 256 # 隐藏维度
):
super().__init__()
self.input_len = input_len
self.d_in = d_in
self.output_len = output_len
# 编码器:把 [B, T, D] 拉平成 [B, T*D] 再过 MLP
self.encoder = nn.Sequential(
nn.Linear(input_len * d_in, d_hidden),
nn.ReLU(),
nn.Linear(d_hidden, d_hidden),
nn.ReLU(),
)
# 解码器:把序列级表示变成未来多步预测
self.decoder = nn.Sequential(
nn.Linear(d_hidden, d_hidden),
nn.ReLU(),
nn.Linear(d_hidden, output_len) # 这里先假设只预测 1 维目标
)
# 线性残差:直接对历史做线性投影,学“趋势”
self.linear_residual = nn.Linear(input_len, output_len)
def forward(self, x_hist, y_hist):
"""
x_hist: [B, T, D] 历史特征(价格、节假日、业务特征等)
y_hist: [B, T] 历史目标(比如历史销量)
return: [B, H] 未来 H 步预测
"""
B, T, D = x_hist.shape
assert T == self.input_len and D == self.d_in
# 1. 编码器:序列 -> 一个向量
x_flat = x_hist.reshape(B, T * D) # [B, T*D]
h = self.encoder(x_flat) # [B, d_hidden]
# 2. 解码器:向量 -> 未来多步
dec_out = self.decoder(h) # [B, output_len]
# 3. 线性残差:用历史目标直接线性外推
trend = self.linear_residual(y_hist) # [B, output_len]
# 4. 两条路相加
return dec_out + trend
这个版本的功能很明确:输入一段历史特征 x_hist 和历史目标值 y_hist,模型直接输出未来 output_len 步的预测值。
一个最简单的训练循环示意如下:
model = SimpleTiDE(input_len=48, d_in=10, output_len=24)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
loss_fn = nn.MSELoss()
for epoch in range(50):
for x_hist, y_hist, y_future in dataloader:
# x_hist: [B, 48, 10]
# y_hist: [B, 48]
# y_future: [B, 24]
pred = model(x_hist, y_hist)
loss = loss_fn(pred, y_future)
optimizer.zero_grad()
loss.backward()
optimizer.step()
在实际项目中,你可以灵活调整:
input_len 可以设为 96、168 等更长的历史窗口。
d_in 中可以塞入更多特征,如价格、营销活动标志、星期几、节假日、大促标识等。
- 若需要同时预测多个目标(如GMV、订单量、访客数),可将解码器最后一层输出改为
output_len * num_targets,再进行reshape。
通过这个极简的实现,我们可以看到TiDE如何利用简单的深度学习组件解决复杂的时序预测问题。其思想对于希望快速搭建高效预测模型的Python开发者而言,具有很高的参考价值。如果你想进一步探索,例如加入未来已知协变量、用PyTorch Lightning构建完整训练流程等,欢迎在云栈社区交流讨论。