TimeSeries

TimeSeries 是 Darts 中的主要数据类。TimeSeries 表示单变量或多元时间序列,带有正确的时间索引。时间索引可以是 pandas.DatetimeIndex 类型(包含日期时间),也可以是 pandas.RangeIndex 类型(包含整数;对于表示没有特定时间戳的顺序数据很有用)。在某些情况下,TimeSeries 甚至可以表示概率序列,例如用于获取置信区间。

TimeSeries 在 Darts 中用于提供一致的、专用于时间序列的 API

  • TimeSeries 保证拥有正确的时间索引(基于整数或日期时间):完整且按时间排序。

  • Darts 中的所有模型都使用 TimeSeries 并产生 TimeSeries

  • TimeSeries 允许进行各种时间序列操作(例如按时间戳分割、连接等)。

  • TimeSeries 提供了一种用户友好的方式来表示多维和概率序列(例如获取边际分位数)。

使用专用类型来表示时间序列(而不是 Pandas DataFrame、NumPy 数组等)消除了对不同模型和函数期望格式约定的依赖。

多元时间序列 vs 多时间序列

我们区分单变量序列和多元序列

  • 一个多元序列包含多个维度(即每个时间步长有多个值)。

  • 一个单变量序列只包含一个维度(即每个时间步长只有一个标量值)。

有时这些维度被称为分量。一个 TimeSeries 对象可以是单变量(如果它只有一个分量),也可以是多元(如果它有多个分量)。在多元序列中,所有分量共享相同的时间轴。也就是说,它们共享相同的时间戳。

Darts 中的一些模型(以及所有机器学习模型)支持多元序列。这意味着它们可以接受多元序列作为输入(作为目标或协变量),并且它们生成的预测将与目标的维度相匹配。

此外,一些模型可以处理多个时间序列,这意味着它们可以同时在多个 TimeSeries 对象上训练,并用于同时预测多个 TimeSeries 对象。这有时被称为面板数据。在这种情况下,不同的 TimeSeries 不需要共享相同的时间索引——例如,有些序列可能在 1990 年,有些在 2000 年。实际上,这些序列甚至不需要具有相同的频率。处理多个序列的模型期望输入为 TimeSeries 的 Python Sequence(例如,一个简单的 TimeSeries 列表)。

figure1

图 1:单个多元序列。在 Darts 中,这由一个 TimeSeries 对象表示。

figure2

图 2:多个时间序列。在 Darts 中,这由多个 TimeSeries 对象表示。这些序列可以共享或不共享相同的时间轴,并且可以是单变量或多元的。

  • 多元序列示例:单个患者随时间变化的血压和心率(一个包含 2 个分量的多元序列)。

  • 多序列示例:多个患者的血压和心率;可能针对不同患者在不同时间测量(每个患者一个包含 2 个分量的多元序列)。

我的问题应该使用多元序列还是多序列?

使用多元序列将为模型提供共同捕捉维度(components)的机会,而使用多序列将使模型接触到多个观测值。因此,哪种表示形式是正确的取决于具体问题,在某些情况下甚至可能事先不清楚,需要通过实验确定。然而,如果您的情况是试图对随时间一起变化的几个“相关”分量进行建模(例如移动物体的坐标,或与单个实体相关的多个测量值),通常自然地将它们作为单个序列中的多个分量来捕捉。另一方面,如果您有此类测量值的多个实例(例如,在不同实验或观测中获得),这可能意味着您拥有多个时间序列。此外,如果您的值不共享相同的时间跨度,则应将其表示为不同的序列。

概率序列和确定性序列

在 Darts 中,概率预测通过从底层概率模型中抽取 Monte Carlo 样本来表示。这种表示允许 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.DatetimeIndexpandas.RangeIndex),在 *component*(或“列”)维上还有另一个 pandas.IndexTimeSeries 旨在是不可变的,并且大多数操作都会返回新的 TimeSeries 对象。

TimeSeries 导出数据

TimeSeries 对象提供了几种导出数据的方式,例如

静态协变量

可选地,TimeSeries 对象可以包含静态数据(称为静态协变量),这可以被一些模型利用。静态协变量的示例包括

  • 商店位置 - 例如,对于多元序列中的每个商店(分量)

  • 产品 ID

  • 传感器类型

静态协变量必须由一个 pandas DataFrame 指定,其行与 TimeSeries 的分量匹配,列表示静态协变量的维度。在使用大多数工厂方法时,可以使用 static_covariates 参数将它们添加到 TimeSeries 中。它们也可以使用 with_static_covariates() 方法添加到现有 TimeSeries 中。

分层时间序列

可选地,TimeSeries 对象可以包含一个层级结构(hierarchy),该结构指定其不同分量如何分组。层级结构本身被指定为一个 Python 字典,将分量的名称映射到其在层级结构中父级名称的列表。

例如,以下层级结构表示两个分量 "a""b" 相加等于 "total"

hierarchy = {"a": ["total"], "b": ["total"]}

层级结构可用于后验预测协调(posthoc forecast reconciliation)。Darts 提供了几种协调转换器(可与 fit()/transform() 一起使用)——参见相应的 API 文档

更多信息和文档

TimeSeries 类的完整属性和方法列表列在API 文档中。此外,快速入门包含一些 TimeSeries 操作的示例。