我最近阅读了一篇非常有趣的论文,名为 Deep Transformer Models for Time Series Forecasting: The Influenza Prevalence Case。我认为这可能是一个有趣的项目,他的实现是从零开始的,可以帮助您了解有关时间序列预测的更多信息。
预测任务
在时间序列预测中,目标是在给定历史值的情况下预测时间序列的未来值。时间序列预测任务的一些示例是:
预测流感流行病例:时间序列预测的深度变形模型:流感流行病例
能源生产预测:使用堆叠非参数贝叶斯方法的能源消耗预测
天气预报:MetNet:降水预报的神经天气模型
例如,我们可以将一个城市的能源消耗指标存储几个月,然后训练一个能够预测该城市未来能源消耗的模型。这可以用来估计能源需求,因此能源公司可以使用这个模型来估计在任何给定时间需要生产的能源的最佳价值。
模型
我们将使用的模型是编码器-解码器 Transformer,其中编码器部分将时间序列的历史作为输入,而解码器部分以自回归方式预测未来值。
解码器使用注意机制与编码器连接。通过这种方式,解码器可以在做出预测之前学习时间序列历史中最有用的部分。
解码器使用了masked self-attention,使得网络在训练过程中不获取未来值,导致信息泄露。
编码器:
解码器:
所有型号:
可以通过以下方式使用 PyTorch 构建此架构:
encoder_layer = nn.TransformerEncoderLayer(
d_model=channels,
nhead=8,
dropout=self.dropout,
dim_feedforward=4 * channels,
)
decoder_layer = nn.TransformerDecoderLayer(
d_model=channels,
nhead=8,
dropout=self.dropout,
dim_feedforward=4 * channels,
)
self.encoder = torch.nn.TransformerEncoder(encoder_layer, num_layers=8)
self.decoder = torch.nn.TransformerDecoder(decoder_layer, num_layers=8)
数据
每当我实现一种新方法时,我都喜欢先在合成数据上进行尝试,这样更容易理解和调试。这降低了数据的复杂性,并将更多的注意力放在了实现/算法上。
我编写了一个小脚本,它生成具有不同时期、偏移量和模式的时间序列。
def generate_time_series(dataframe):
clip_val = random.uniform(0.3, 1)
period = random.choice(periods)
phase = random.randint(-1000, 1000)
dataframe["views"] = dataframe.apply(
lambda x: np.clip(
np.cos(x["index"] * 2 * np.pi / period phase), -clip_val, clip_val
)
* x["amplitude"]
x["offset"],
axis=1,
) np.random.normal(
0, dataframe["amplitude"].abs().max() / 10, size=(dataframe.shape[0],)
)
return dataframe
然后现在预测模型有哪些,该模型将一次性在所有这些时间序列上进行训练:
结果
我们现在使用这个模型来预测这些时间序列的未来值。但结果有点复杂:
预测不合适的例子
拟合示例:
结果没有我预期的那么好,特别是考虑到对合成数据做出好的预测通常很容易,但它们仍然令人鼓舞。
该模型的预测有些不一致,对于一些不好的例子现在预测模型有哪些,幅度略有高估。在好的情况下,预测与基本事实非常吻合,不包括噪声。
我可能需要更多地调试我的代码并努力优化超参数,然后才能获得更好的结果。
总结
Transformer 是目前机器学习应用中非常流行的模型,因此很自然地将它们用于时间序列预测。但是在处理时间序列时,Transformers 不应该是您的首选方法,但这是一个可以尝试的测试。
论文提及arxiv:2001.08317