入门指南

以下信息旨在帮助用户快速上手aeon。 如果需要安装,请参阅我们的安装指南以安装aeon

我们假设您对scikit-learn包有基本的了解。如果您需要关于scikit-learn的帮助,您可能想查看他们的入门指南

aeon 是一个用于从时间序列中学习的开源工具包。它提供了最新的时间序列机器学习算法,以及一系列用于以下学习任务的经典技术:

  • 分类,其中使用带有离散值标记的时间序列集合来训练模型以预测未见过的案例 (更多详情)。

  • 回归,其中使用带有连续值标签的时间序列集合来训练模型以预测未见过的案例 (更多详情)。

  • 聚类,其中使用没有任何标签的时间序列集合来训练模型以标记案例 (更多详情)。

  • 相似性搜索,其目标是评估查询时间序列与其他较长的时间序列集合之间的相似性(更多详情)。

  • 异常检测,其目标是找到单个时间序列中不代表整个序列的值或区域。

  • 预测,其目标是预测单个时间序列的未来值 (更多详情)。

  • 分割,其目标是将单个时间序列分割成区域,这些区域是时间序列中不代表整个序列的部分 (更多详情)。

aeon 还提供了上述模块使用的核心模块:

  • 转换,其中单个系列或集合被转换为不同的表示或领域。(更多详情)。

  • 距离,用于衡量两个时间序列或序列集合之间的不相似性,并包括对齐序列的函数(更多详情)。

  • 网络,为所有时间序列任务提供深度学习的核心模型

  • (更多详情).

有专门的笔记本更详细地介绍了这些模块中的每一个。本指南旨在为您提供每个任务的主要概念和代码的最简要介绍,以便开始使用。有关每个任务可用的各种估计器的更多信息,请参见上面的链接、API示例页面。

单一时间序列

时间序列是一系列假设为有序的实值数据。单变量时间序列在每个时间点都有一个单一的值。例如,来自单个传感器的心电图读数或每月使用航空公司的乘客数量将形成一个单变量序列。单个时间序列默认存储在np.ndarray中(我们尽可能在内部使用)。我们也可以处理pd.Seriespd.DataFrame对象作为输入,但这些可能会在内部转换为np.ndarray。航空公司序列是预测领域中单变量序列的经典示例。该序列是1949年至1960年国际航空公司乘客的月度总数,单位为千。

>>> from aeon.datasets import load_airline
>>> y = load_airline()  # load an example univariate series as an array
>>> y[:5]  # first five time points
606.0
508.0
461.0
390.0
432.0

多元时间序列由多个序列或通道组成,其中每个观测值是在相同时间索引下的相关记录的向量。一个例子是来自智能手表的运动轨迹,至少有三个维度(X、Y、Z坐标),或者是随时间记录的多个财务统计数据。单个多元序列输入通常默认遵循形状(n_channels, n_timepoints)。算法可能有一个axis参数来改变这一点,其中axis=1假设默认形状并且是默认设置,而axis=0假设形状(n_timepoints, n_channels)

>>> from aeon.datasets import load_uschange
>>> data = load_uschange()  # load an example multivariate series
>>> data[:,:5]  # all channels, first five time points
[[ 0.61598622  0.46037569  0.87679142 -0.27424514  1.89737076]
 [ 0.97226104  1.16908472  1.55327055 -0.25527238  1.98715363]
 [-2.45270031 -0.55152509 -0.35870786 -2.18545486  1.90973412]
 [ 4.8103115   7.28799234  7.28901306  0.98522964  3.65777061]
 [ 0.9         0.5         0.5         0.7        -0.1       ]]

我们通常将时间序列的观测次数称为n_timepoints。 如果序列是多变量的,我们将维度称为通道 (以避免与数组的维度混淆),并在代码中使用n_channels。因此 上面加载的US Change数据有五个通道和187个时间点。有关 我们提供的数据集的更多详细信息以及如何将数据加载到aeon兼容的数据 结构中,请参阅我们的datasets笔记本。

单系列模块

不同的 aeon 模块处理单个序列或序列集合。 anomaly detectionforecastingsegmentation 模块中的估计器使用 单个序列输入(它们继承自 BaseSeriesEstimator)。distances 中的函数 接受两个序列作为参数。

异常检测

异常检测(AD)是识别与其余数据显著不同的观测值的过程。更多详细信息将在我们编写完笔记本后很快提供。

>>> from aeon.datasets import load_airline
>>> from aeon.anomaly_detection import STOMP
>>> stomp = STOMP(window_size=200)
>>> scores = est.fit_predict(X) # Get the anomaly scores

分割

时间序列分割(TSS)是将时间序列划分为彼此不同的段或区域的过程。例如,这可能是将智能手表的运动轨迹分割为不同的活动,如步行、跑步和坐着。它与变化点检测领域密切相关,这是一个在统计学文献中更常用的术语。

>>> from aeon.datasets import load_airline
>>> from aeon.segmentation import ClaSPSegmenter
>>> series = load_airline()
>>> clasp = ClaSPSegmenter()  # An example segmenter
>>> clasp.fit(data)  # fit the segmenter on the data
>>> clasp.fit_predict(ts)
[51]

距离

时间序列之间的距离是许多时间序列任务中的基本操作。我们在aeon.distances模块中提供了广泛的距离函数,所有这些函数都使用numba进行了优化。它们都适用于多变量和不等长的时间序列。

>>> from aeon.datasets import load_japanese_vowels
>>> from aeon.distances import dtw_distance
>>> data = load_japanese_vowels()  # load an example multivariate series collection
>>> dtw_distance(data[0], data[1])  # calculate the dtw distance
14.416269807978

时间序列集合

时间序列集合的默认存储是一个3D的np.ndarray。 如果n_timepoints在不同情况下变化,我们将集合存储在list中的 np.ndarray数组中,每个数组具有相同数量的通道。我们没有能力使用具有不同通道数的时间序列集合。 我们还假设单个序列的所有通道的序列长度始终相同。

>>> from aeon.datasets import load_italy_power_demand
>>> X, y = load_italy_power_demand()  # load an example univariate collection
>>> X.shape
(1096, 1, 24)
>>> X[:5, :, :5]
[[[-0.71051757 -1.1833204  -1.3724416  -1.5930829  -1.4670021 ]]
 [[-0.99300935 -1.4267865  -1.5798843  -1.6054006  -1.6309169 ]]
 [[ 1.3190669   0.56977448  0.19512825 -0.08585642 -0.17951799]]
 [[-0.81244429 -1.1575534  -1.4163852  -1.5314215  -1.5026624 ]]
 [[-0.97284033 -1.3905178  -1.5367049  -1.6202404  -1.6202404 ]]]
>>> y[:5]
['1' '1' '2' '2' '1']

我们在提到集合中包含的单个时间序列时,会交替使用术语“案例”和“实例”。时间序列集合的大小在代码中被称为n_cases。集合的形状为(n_cases, n_channels, n_timepoints)

我们建议将集合存储在3D np.ndarray 中,即使每个时间序列是单变量的(即 n_channels == 1)。集合估计器将处理形状为 (n_cases, n_timepoints) 的2D输入,正如您从 scikit-learn 中所期望的那样,但可能会将形状为 (n_cases, n_timepoints) 的单变量系列集合与形状为 (n_channels, n_timepoints) 的单个多变量系列混淆。这种潜在的混淆是我们区分系列和集合估计器的原因之一。

>>>from aeon.datasets import load_basic_motions, load_plaid, load_japanese_vowels
>>> X2, y2 = load_basic_motions() # example equal length multivariate collection
>>> X2.shape
(80, 6, 100)
>>> X3, y3 = load_plaid()  # example unequal length univariate collection
>>> type(X3)
<class 'list'>
>>> len(X3)
1074
>>> X3[0].shape
(1, 500)
>>> X4, y4 = load_japanese_vowels()  # example unequal length mutlivariate collection
>>> len(X4)
640
>>> X4[0].shape
(12, 20)

基于集合的模块

classificationregressionclustering 模块中的估计器从时间序列集合中学习(它们继承自 BaseCollectionEstimator 类)。时间序列集合通常会伴随一个目标变量数组用于监督学习。similarity_search 模块也适用于时间序列集合。

集合估计器紧密遵循scikit-learn估计器接口,适当使用fitpredicttransformpredict_probafit_predictfit_transform。它们还设计为直接与scikit-learn功能配合使用,例如模型评估、参数搜索和管道(在适当的情况下)。

分类

时间序列分类(TSC)涉及在标记的时间序列集合上训练模型。这些标签,在代码中称为y,应该是类型为intstrnumpy数组。

如果您曾经使用过scikit-learn,那么分类估计器接口应该很熟悉。在这个例子中,我们在示例数据上使用动态时间规整(DTW)拟合了一个KNeighborsTimeSeriesClassifier

>>> import numpy as np
>>> from aeon.classification.distance_based import KNeighborsTimeSeriesClassifier
>>> X = [[[1, 2, 3, 4, 5, 6, 7]],  # 3D array example (univariate)
...      [[4, 4, 4, 5, 6, 7, 3]]]  # Two samples, one channel, seven series length
>>> y = [0, 1]  # class labels for each sample
>>> X = np.array(X)
>>> y = np.array(y)
>>> clf = KNeighborsTimeSeriesClassifier(distance="dtw")
>>> clf.fit(X, y)  # fit the classifier on train data
KNeighborsTimeSeriesClassifier()
>>> X_test = np.array([[2, 2, 2, 2, 2, 2, 2], [4, 4, 4, 4, 4, 4, 4]])
>>> clf.predict(X_test)  # make class predictions on new data
[0 1]

一旦分类器使用训练数据和类别标签进行拟合后,我们可以预测新案例的标签。像scikit-learn一样,predict_proba方法可用于预测类别概率,并且存在score方法来计算新数据的准确性。

回归

时间序列回归假设目标变量不是分类中的离散标签,而是一个连续变量或目标变量。与分类部分相同的输入数据考虑因素适用,模块功能类似。目标变量应该是一个类型为floatnumpy数组。

时间序列回归是预测中常用的术语,通常与滑动窗口结合使用。然而,该术语还包括“时间序列外部回归”,其中目标变量不是未来值,而是某些外部变量。 在以下示例中,我们在一个名为Covid3Month的时间序列回归问题上使用了KNeighborsTimeSeriesRegressor

>>> from aeon.regression.distance_based import KNeighborsTimeSeriesRegressor
>>> from aeon.datasets import load_covid_3month
>>> from sklearn.metrics import mean_squared_error
>>> X_train, y_train = load_covid_3month(split="train")
>>> X_test, y_test = load_covid_3month(split="test")
>>> reg = KNeighborsTimeSeriesRegressor(distance="dtw")
>>> reg.fit(X_train, y_train)  # fit the regressor on train data
KNeighborsTimeSeriesRegressor()
>>> y_pred = reg.predict(X_test)  # make label predictions on new data
>>> y_pred[:6]
[0.04218472 0.01459854 0.         0.0164468  0.06254257 0.11111111]
>>> mean_squared_error(y_test, y_pred)
0.002921957478363366

聚类

与分类和回归类似,时间序列聚类(TSCL)旨在尽可能遵循scikit-learn接口。使用与TSC和TSER模块相同的输入数据格式。此示例在ArrowHead数据集上拟合了一个TimeSeriesKMeans聚类器。

>>> from aeon.clustering import TimeSeriesKMeans
>>> from aeon.datasets import load_arrow_head
>>> from sklearn.metrics import rand_score
>>> X, y = load_arrow_head()
>>> kmeans = TimeSeriesKMeans(n_clusters=3, metric="dtw")
>>> kmeans.fit(X) # fit the clusterer
TimeSeriesKMeans(n_clusters=3)
>>> kmeans.labels_[0:10]  # cluster labels
[2 1 1 0 1 1 0 1 1 0]
>>> rand_score(y, kmeans.labels_)
0.6377792823290453

调用fit后,labels_属性包含每个时间序列的聚类标签。predict方法可用于预测新数据的聚类标签。

变压器

我们将变压器分为两类:一类是转换单一时间序列的变压器,另一类是转换集合的变压器。

单时间序列的Transformers

继承自BaseSeriesTransformer的Transformers在aeon.transformations.series包中将单个(可能是多变量的)时间序列转换为不同的时间序列或特征向量。更多信息即将发布。

以下示例展示了如何使用 AutoCorrelationSeriesTransformer 类来提取时间序列的自相关项。

>>> from aeon.transformations.series import AutoCorrelationSeriesTransformer
>>> from aeon.datasets import load_airline
>>> acf = AutoCorrelationSeriesTransformer()
>>> y = load_airline()  # load single series airline dataset
>>> res = acf.fit_transform(y)
>>> res[0][:5]
[0.96019465 0.89567531 0.83739477 0.7977347  0.78594315]

时间序列集合的Transformers

aeon.transformations.collections 模块包含一系列用于时间序列集合的转换器。这些转换器不允许单一系列输入,将二维输入类型视为单变量系列的集合,并且对输出的数据类型没有限制。

大多数时间序列分类和回归算法都基于某种形式的转换到替代特征空间。例如,我们可能会从每个序列中提取一些摘要时间序列特征,并在这些特征上拟合传统的分类器或回归器。例如,我们可以使用Catch22,它为每个序列计算22个摘要统计量。

>>> from aeon.transformations.collection.feature_based import Catch22
>>> import numpy as np
>>> X = np.random.RandomState().random(size=(4, 1, 10))  # four cases of 10 timepoints
>>> c22 = Catch22(replace_nans=True)  # transform to four cases of 22 features
>>> c22.fit_transform(X)[0]
[ 4.99485761e-01  4.12452579e-01  3.00000000e+00  1.00000000e-01
  0.00000000e+00  1.00000000e+00  2.00000000e+00  3.08148791e-34
  1.96349541e+00  2.56152262e-01 -1.09028518e-02  9.08908735e-01
  2.00000000e+00  1.00000000e+00  4.00000000e+00  1.88915916e+00
  1.00000000e+00  5.95334611e-01  0.00000000e+00  0.00000000e+00
  8.23045267e-03  0.00000000e+00]

还有序列到序列的转换,例如Padder用于延长序列并处理不等长的集合。

>>> from aeon.transformations.collection import Padder
>>> from aeon.testing.data_generation import make_example_3d_numpy_list
>>> X, _ = make_example_3d_numpy_list(  # unequal length data with 8-12 timepoints
...     n_cases=2,
...     min_n_timepoints=8,
...     max_n_timepoints=12,
...     random_state=0,
... )
>>> print(X[0])
[[0.         1.6885315  1.71589124 1.69450348 1.24712739 0.76876341
  0.59506921 0.11342595 0.54531259 0.95533023 1.62433746 0.95995434]]
>>> print(X[1])
[[2.         0.28414423 0.3485172  0.08087359 3.33047938 3.112627
  3.48004859 3.91447337 3.19663426]]
>>> pad = Padder(pad_length=12, fill_value=0)  # pad to length 12
>>> pad.fit_transform(X)
[[[0.         1.6885315  1.71589124 1.69450348 1.24712739 0.76876341
   0.59506921 0.11342595 0.54531259 0.95533023 1.62433746 0.95995434]]
 [[2.         0.28414423 0.3485172  0.08087359 3.33047938 3.112627
   3.48004859 3.91447337 3.19663426 0.         0.         0.        ]]]

aeon估计器的管道

scikit-learn 类似,aeon 提供了管道类,可用于将转换和估计器链接在一起。

对于分类、回归和聚类等机器学习任务,如果转换器输出有效的输入类型,可以使用scikit-learnmake_pipeline功能。

以下示例使用Catch22特征提取转换器和随机森林分类器进行分类。

>>> from aeon.datasets import load_italy_power_demand
>>> from aeon.transformations.collection.feature_based import Catch22
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.pipeline import make_pipeline
>>> from sklearn.metrics import accuracy_score
...
>>> # Load the italy power demand dataset
>>> X_train, y_train = load_italy_power_demand(split="train")
>>> X_test, y_test = load_italy_power_demand(split="test")
...
>>> # Create and fit the pipeline
>>> pipe = make_pipeline(
...     Catch22(replace_nans=True),
...     RandomForestClassifier(random_state=42),
... )
>>> pipe.fit(X_train, y_train)
Pipeline(steps=[('catch22', Catch22(replace_nans=True)),
                ('randomforestclassifier',
                 RandomForestClassifier(random_state=42))])
>>> # Make predictions like any other sklearn estimator
>>> accuracy_score(pipe.predict(X_test), y_test)
0.8989310009718173

与管道类似,分类、回归和聚类等任务可以使用可用的scikit-learn功能。

>>> from sklearn.metrics import accuracy_score
>>> from sklearn.model_selection import GridSearchCV, KFold
>>> from aeon.classification.distance_based import KNeighborsTimeSeriesClassifier
>>> from aeon.datasets import load_italy_power_demand
...
>>> # Load the italy power demand dataset
>>> X_train, y_train = load_italy_power_demand(split="train")
>>> X_test, y_test = load_italy_power_demand(split="test")
...
>>> knn = KNeighborsTimeSeriesClassifier()
>>> param_grid = {"n_neighbors": [1, 5], "distance": ["euclidean", "dtw"]}
...
>>> gscv = GridSearchCV(knn, param_grid, cv=KFold(n_splits=4))
>>> gscv.fit(X_train, y_train)
...
>>> y_pred = gscv.predict(X_test)
>>> y_pred[:6]
['2' '2' '2' '2' '2' '1']
>>> accuracy_score(y_test, y_pred)
0.9523809523809523
>>> gscv.best_params_
{'distance': 'euclidean', 'n_neighbors': 5}