文中内容仅限技术学习与代码实践参考,市场存在不确定性,技术分析需谨慎验证,不构成任何投资建议。
Darts 是一个 Python 库,用于对时间序列进行用户友好型预测和异常检测。它包含多种模型,从 ARIMA 等经典模型到深度神经网络。所有预测模型都能以类似 scikit-learn 的方式使用 fit()
和 predict()
函数。该库还可以轻松地对模型进行回溯测试,将多个模型的预测结果结合起来,并将外部数据考虑在内。Darts 支持单变量和多变量时间序列和模型。基于 ML 的模型可以在包含多个时间序列的潜在大型数据集上进行训练,其中一些模型还为概率预测提供了丰富的支持。
时间序列
TimeSeries
是 Darts 中的主要数据类。TimeSeries
表示一个单变量或多变量时间序列,并带有适当的时间索引。时间索引可以是 pandas.DatetimeIndex
类型(包含日期时间),也可以是 pandas.RangeIndex
类型(包含整数;适用于无具体时间戳的序列数据)。在某些情况下,TimeSeries
甚至可表示 概率 序列,例如用于获得置信区间。
在 Darts 中,TimeSeries
用于提供一致的时间序列 API:
-
TimeSeries
保证具有适当的时间索引(基于整数或日期时间):完整且按时间排序。 -
Darts 中的所有模型均接收
TimeSeries
并输出TimeSeries
。 -
TimeSeries
支持各种时间序列操作(如按时间戳拆分、拼接等)。 -
TimeSeries
提供友好的方式来表示多维和概率序列(例如获取边际分位数)。
使用专用类型来表示时间序列(而非 Pandas DataFrame、NumPy 数组等)可消除对不同模型和函数所期望格式的依赖。
多变量时间序列 vs 多个时间序列
我们区分单变量与多变量序列:
-
多变量 序列包含多个维度(即每个时间步有多个数值)。
-
单变量 序列仅包含一个维度(即每个时间步只有一个标量值)。
有时这些维度称为 分量。单个 TimeSeries
对象可以是单变量(若仅有一个分量),也可以是多变量(若有多个分量)。在多变量序列中,所有分量共享同一时间轴,即它们共享相同的时间戳。
Darts 中的某些模型(以及所有机器学习模型)支持多变量序列。这意味着它们可将多变量序列作为输入(作为目标或协变量),且其输出的预测维度与目标维度匹配。
此外,某些模型可处理 多个时间序列,即它们可在多个 TimeSeries
对象上训练,并一次性预测多个 TimeSeries
对象。这有时称为面板数据。在这种情况下,不同的 TimeSeries
不必共享相同的时间索引——例如,某些序列可能在 1990 年,而其他序列在 2000 年。实际上,这些序列甚至可以具有不同的频率。处理多个序列的模型期望输入为 Python Sequence
的 TimeSeries
(例如简单的 TimeSeries
列表)。
图 1: 单个多变量序列。在 Darts 中,这由单个 TimeSeries
对象表示。
图 2: 多个时间序列。在 Darts 中,这由多个 TimeSeries
对象表示。这些序列可能共享或不共享同一时间轴,也可能为单变量或多变量。
-
多变量序列示例: 单个患者随时间变化的血压和心率(一个包含 2 个分量的多变量序列)。
-
多个序列示例: 多个患者的血压和心率;不同患者可能在不同时间测量(每个患者一个包含 2 个分量的多变量序列)。
我应使用多变量序列还是多个序列来解决我的问题?
使用多变量序列为模型提供了联合捕获维度的机会,而使用多个序列则让模型接触到多个观测值。因此,哪种表示方式合适取决于具体的问题,有时甚至在事前并不明确,需要通过实验确定。然而,若你试图建模多个“相关”分量随时间共同变化(例如移动物体的坐标,或与单个实体相关的多个测量值),通常自然地将这些分量捕获为单个序列中的多个分量。另一方面,如果你有这些测量的多个实例(例如,在不同实验或观测中获得),这可能意味着你有多个时间序列。此外,如果你的值不共享相同的时间跨度,它们可能应表示为不同的序列。
概率序列与确定性序列
在 Darts 中,概率预测通过对底层概率模型进行蒙特卡洛采样来表示。这种表示方式使 TimeSeries
能够表示任意联合分布(跨时间和分量),而无需依赖任何预定义的参数形式。基于此,我们定义两种序列类型:
-
概率(或 随机)序列包含多个样本。
-
确定性 序列仅包含一个样本。
创建 TimeSeries
TimeSeries
对象可通过工厂方法创建,例如:
-
TimeSeries.from_dataframe() 可从具有一个或多个列表示数值的 Pandas Dataframe 创建
TimeSeries
(列对应分量,多个列对应多变量序列)。 -
TimeSeries.from_values() 可从 1-D、2-D 或 3-D NumPy 数组创建
TimeSeries
。它将生成基于整数的时间索引(pandas.RangeIndex
类型)。1-D 对应单变量确定性序列,2-D 对应多变量确定性序列,3-D 对应多变量随机序列。 -
TimeSeries.from_times_and_values() 与
TimeSeries.from_values()
类似,但还接受时间索引。
更多方法记录在 TimeSeries API 文档中。
此外,可使用函数 concatenate()
沿不同轴拼接序列。axis=0
对应时间,axis=1
对应分量,axis=2
对应随机样本维度。例如:
from darts import concatenate
my_multivariate_series = concatenate([series1, series2, ...], axis=1)
从共享相同时间轴的某些序列生成多变量序列。
实现
在幕后,TimeSeries
包裹一个 3 维的 xarray.DataArray
对象。维度为 (time, component, sample),其中 component 维度的大小在多变量序列中大于 1,sample 维度的大小在随机序列中大于 1。DataArray
本身由 3 维 NumPy 数组支持,并在 time 维度上具有时间索引(pandas.DatetimeIndex
或 pandas.RangeIndex
),在 component(或“列”)维度上具有另一个 pandas.Index
。TimeSeries
旨在不可变,大多数操作返回新的 TimeSeries
对象。
从 TimeSeries
导出数据
TimeSeries
对象提供几种导出数据的方式,例如:
-
TimeSeries.to_dataframe() 导出 Dataframe(用于确定性序列)
-
TimeSeries.data_array() 导出保存此序列数据的
xarray
DataArray
(和索引)。 -
TimeSeries.values() 导出包含序列中一个样本值的 NumPy 数组。
-
TimeSeries.all_values() 导出包含随机序列所有样本值的 NumPy 数组。
静态协变量
可选地,TimeSeries
对象可包含静态数据(称为 静态协变量),某些模型可利用这些数据。静态协变量的示例包括:
-
商店位置——例如多变量序列中每个商店(分量)的位置
-
产品 ID
-
传感器类型
-
…
静态协变量必须由 pandas DataFrame 指定,其行与 TimeSeries
的分量匹配,列表示静态协变量的维度。它们可在使用大多数工厂方法时通过 static_covariates
参数添加到 TimeSeries
。也可使用 with_static_covariates()
方法将静态协变量添加到现有 TimeSeries
。
层次时间序列
可选地,TimeSeries
对象可包含层次结构,该结构指定其不同分量如何分组。层次结构本身指定为 Python 字典,将分量名称映射到其在层次结构中的父级名称列表。
例如,以下层次结构表示两个分量 "a"
和 "b"
累加到 "total"
:
hierarchy = {"a": ["total"], "b": ["total"]}
层次结构可用于事后预测协调。Darts 提供几种协调转换器(可与 fit()
/ transform()
一起使用)—— 参见相应的 API 文档。
更多信息与文档
TimeSeries
类的完整属性和方法列表在 API 文档中列出。此外,快速入门包含一些 TimeSeries
操作的示例。
风险提示与免责声明
本文内容基于公开信息研究整理,不构成任何形式的投资建议。历史表现不应作为未来收益保证,市场存在不可预见的波动风险。投资者需结合自身财务状况及风险承受能力独立决策,并自行承担交易结果。作者及发布方不对任何依据本文操作导致的损失承担法律责任。市场有风险,投资须谨慎。