设置说明:本 notebook 提供了关于 sktime 支持的预测学习任务的教程。在 binder 上,这应该可以直接运行。
为了按预期运行本 notebook,请确保已在您的 python 环境中安装了带有基本依赖项要求的 sktime。
要在本地开发版本的 sktime 上运行此 notebook,建议进行可编辑的开发者安装,请参阅sktime 开发者安装指南获取说明。
使用 sktime 进行预测#
在预测中,使用过去的数据对时间序列进行时间上的向前预测。这与 scikit-learn 及类似库支持的表格预测任务显着不同。

sktime 为各种经典和机器学习风格的预测算法提供了一个通用的、类似 scikit-learn 的接口,以及构建管道和复合机器学习模型的工具,包括时间调优方案,或如 scikit-learn 回归器的步进应用等归约方法。
第 1 节概述了 sktime 支持的常见预测工作流程。
第 2 节讨论了 sktime 中可用的预测器系列。
第 3 节讨论了高级组合模式,包括管道构建、归约、调优、集成和 autoML。
第 4 节介绍了如何编写符合 sktime 接口的自定义估计器。
更多参考
关于预测与
scikit-learn式监督预测的区别以及将预测误诊为监督预测的陷阱的更多详细信息,请参阅本 notebook如需科学参考,请参阅我们关于使用 sktime 进行预测的论文,其中我们更详细地讨论了
sktime的预测模块,并用它来复现和扩展 M4 研究。
目录#
1. 基本预测工作流程
1.1 数据容器格式
1.2 基本部署工作流程 - 批量拟合和预测
1.2.1 基本部署工作流程概览
1.2.2 在拟合时需要预测范围的预测器
1.2.3 可以利用外生数据的预测器
1.2.4 多元预测器
1.2.5 预测区间和分位数预测
1.2.6 面板预测和分层预测
1.3 基本评估工作流程 - 根据实际观测值评估批量预测
1.3.1 基本批量预测评估工作流程概览 - 函数度量接口
1.3.2 基本批量预测评估工作流程概览 - 度量类接口
1.4 高级部署工作流程:滚动更新和预测
1.4.1 使用 update 方法更新预测器
1.4.2 在不更新模型的情况下移动“当前”状态
1.4.3 对一批数据进行步进预测
1.5 高级评估工作流程:滚动重采样和聚合误差,滚动回测
2. sktime 中的预测器 - 搜索、标签、常见系列
2.1 预测器查找 - 注册表
2.2 预测器标签
2.2.1 能力标签:多元、概率、分层
2.2.2 按标签查找和列出预测器
2.2.3 列出所有预测器标签
2.3 常见预测器类型
2.3.1 statsmodels 中的指数平滑、Theta 预测器、autoETS
2.3.2 ARIMA 和 autoARIMA
2.3.3 BATS 和 TBATS
2.3.4 Facebook prophet
2.3.5 状态空间模型 (结构化时间序列)
2.3.6 StatsForecast 中的 AutoArima
3. 高级组合模式 - 管道、归约、autoML 及更多
3.1 归约:从预测到回归
3.2 管道化、去趋势和去季节性
3.2.1 基本预测管道
3.2.2 去趋势器作为管道组件
3.2.3 复杂管道组合和参数检查
3.3 参数调优
3.3.1 使用 ForecastingGridSearchCV 进行基本调优
3.3.2 复杂组合的调优
3.3.3 选择度量标准并检索得分
3.4 autoML 即自动化模型选择、集成和对冲
3.4.1 autoML 即自动化模型选择,使用调优加多路复用器
3.4.2 autoML:通过 OptimalPassthrough 选择变换器组合
3.4.3 简单集成策略
3.4.4 预测加权集成和对冲集成
4. 扩展指南 - 实现您自己的预测器
5. 总结
包导入#
[1]:
import warnings
import numpy as np
import pandas as pd
# hide warnings
warnings.filterwarnings("ignore")
1. 基本预测工作流程#
本节解释了基本的预测工作流程及其关键接口点。
我们将介绍以下四种工作流程
基本部署工作流程:批量拟合和预测
基本评估工作流程:根据实际观测值评估批量预测
高级部署工作流程:拟合和滚动更新/预测
高级评估工作流程:使用滚动预测分割并计算分段和聚合误差,包括常见的回测方案
所有工作流程对输入数据格式都有共同的假设。
sktime 使用 pandas 表示时间序列
主要使用
pd.DataFrame表示时间序列和序列。行表示时间索引,列表示变量。pd.Series也可用于单变量时间序列和序列也可以传递
numpy数组(1D 和 2D),但建议使用pandas。
使用 Series.index 和 DataFrame.index 表示时间序列或序列索引。sktime 支持 pandas 的整数、周期和时间戳索引用于简单时间序列。
sktime 支持面板和分层时间序列的进一步、附加的容器格式,这些将在第 1.6 节中讨论。
示例:作为本教程的运行示例,我们使用一个教科书数据集,即 Box-Jenkins 航空公司数据集,其中包含 1949 年至 1960 年国际航空旅客的月度总数。数值单位为千人。参见“Makridakis, Wheelwright and Hyndman (1998) Forecasting: methods and applications”,练习章节 2 和 3。
[2]:
from sktime.datasets import load_airline
from sktime.utils.plotting import plot_series
[3]:
y = load_airline()
# plotting for visualization
plot_series(y)
[3]:
(<Figure size 1152x288 with 1 Axes>,
<AxesSubplot:ylabel='Number of airline passengers'>)
[4]:
y.index
[4]:
PeriodIndex(['1949-01', '1949-02', '1949-03', '1949-04', '1949-05', '1949-06',
'1949-07', '1949-08', '1949-09', '1949-10',
...
'1960-03', '1960-04', '1960-05', '1960-06', '1960-07', '1960-08',
'1960-09', '1960-10', '1960-11', '1960-12'],
dtype='period[M]', length=144)
通常,期望用户使用 pandas 和兼容 pandas 的内置加载功能来加载用于预测的数据集,例如 read_csv,或者如果数据以其他内存格式(例如 numpy.array)可用,则使用 Series 或 DataFrame 构造函数。
sktime 预测器可能接受 pandas 邻近格式的输入,但将以 pandas 格式生成输出,并尝试将输入强制转换为 pandas 格式。
注意:如果您喜欢的格式未正确转换或强制转换,请考虑将该功能贡献给 sktime。
最简单的用例工作流程是批量拟合和预测,即,将预测模型拟合到一批历史数据,然后请求未来时间点的预测。
此工作流程的步骤如下
数据准备
指定请求预测的时间点。这使用
numpy.array或ForecastingHorizon对象。预测器的指定和实例化。这遵循类似
scikit-learn的语法;预测器对象遵循熟悉的scikit-learnBaseEstimator接口。使用预测器的
fit方法将预测器拟合到数据。使用预测器的
predict方法进行预测。
下面首先逐步概述了基本部署工作流程的原始变体。
最后,提供了单单元格工作流程,其中包含与模式的常见偏差(第 1.2.1 节及后续)。
步骤 1 - 数据准备#
如第 1.1 节所述,假定数据采用 pd.Series 或 pd.DataFrame 格式。
[5]:
from sktime.datasets import load_airline
from sktime.utils.plotting import plot_series
[6]:
# in the example, we use the airline data set.
y = load_airline()
plot_series(y)
[6]:
(<Figure size 1152x288 with 1 Axes>,
<AxesSubplot:ylabel='Number of airline passengers'>)
步骤 2 - 指定预测范围#
现在我们需要指定预测范围并将其传递给我们的预测算法。
有两种主要方式
使用整数的
numpy.array。这假定时间序列中存在整数索引或周期性索引(PeriodIndex);整数表示我们想要进行预测的时间点或周期数。例如,1表示预测下一个周期,2表示预测下下个周期,依此类推。使用
ForecastingHorizon对象。这可用于定义预测范围,使用任何支持的索引类型作为参数。不假定存在周期性索引。
预测范围可以是绝对的,即引用未来的特定时间点,也可以是相对的,即引用与当前时间点的时间差。默认情况下,当前时间点是传递给预测器的任何 y 中看到的最新时间点。
基于 numpy.array 的预测范围始终是相对的;ForecastingHorizon 对象可以是相对的,也可以是绝对的。特别是,绝对预测范围只能使用 ForecastingHorizon 指定。
使用 numpy 预测范围#
[7]:
fh = np.arange(1, 37)
fh
[7]:
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36])
这将请求未来三年的月度预测,因为原始序列周期为 1 个月。在另一个示例中,要仅预测下个月和第五个月,可以写
import numpy as np
fh = np.array([2, 5]) # 2nd and 5th step ahead
使用基于 ForecastingHorizon 的预测范围#
ForecastingHorizon 对象接受绝对索引作为输入,但根据 is_relative 标志将输入视为绝对或相对。
如果传递 pandas 的时间差类型,ForecastingHorizon 将自动假定为相对范围;如果传递 pandas 的值类型,它将假定为绝对范围。
在我们的示例中定义绝对 ForecastingHorizon
[8]:
from sktime.forecasting.base import ForecastingHorizon
[9]:
fh = ForecastingHorizon(
pd.PeriodIndex(pd.date_range("1961-01", periods=36, freq="M")), is_relative=False
)
fh
[9]:
ForecastingHorizon(['1961-01', '1961-02', '1961-03', '1961-04', '1961-05', '1961-06',
'1961-07', '1961-08', '1961-09', '1961-10', '1961-11', '1961-12',
'1962-01', '1962-02', '1962-03', '1962-04', '1962-05', '1962-06',
'1962-07', '1962-08', '1962-09', '1962-10', '1962-11', '1962-12',
'1963-01', '1963-02', '1963-03', '1963-04', '1963-05', '1963-06',
'1963-07', '1963-08', '1963-09', '1963-10', '1963-11', '1963-12'],
dtype='period[M]', is_relative=False)
ForecastingHorizon 可以通过 to_relative 和 to_absolute 方法在相对和绝对之间进行转换。这两种转换都需要传递一个兼容的 cutoff
[10]:
cutoff = pd.Period("1960-12", freq="M")
[11]:
fh.to_relative(cutoff)
[11]:
ForecastingHorizon([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36],
dtype='int64', is_relative=True)
[12]:
fh.to_absolute(cutoff)
[12]:
ForecastingHorizon(['1961-01', '1961-02', '1961-03', '1961-04', '1961-05', '1961-06',
'1961-07', '1961-08', '1961-09', '1961-10', '1961-11', '1961-12',
'1962-01', '1962-02', '1962-03', '1962-04', '1962-05', '1962-06',
'1962-07', '1962-08', '1962-09', '1962-10', '1962-11', '1962-12',
'1963-01', '1963-02', '1963-03', '1963-04', '1963-05', '1963-06',
'1963-07', '1963-08', '1963-09', '1963-10', '1963-11', '1963-12'],
dtype='period[M]', is_relative=False)
步骤 3 - 指定预测算法#
为了进行预测,需要指定一个预测算法。这使用类似 scikit-learn 的接口来完成。最重要的是,所有 sktime 预测器都遵循相同的接口,因此无论选择哪种预测器,前面和剩余的步骤都是相同的。
对于此示例,我们选择预测上次观测值的朴素预测方法。可以使用管道和归约构造语法进行更复杂的指定;这将在第 2 节中稍后介绍。
[13]:
from sktime.forecasting.naive import NaiveForecaster
[14]:
forecaster = NaiveForecaster(strategy="last")
步骤 4 - 将预测器拟合到已见数据#
现在需要将预测器拟合到已见数据
[15]:
forecaster.fit(y)
[15]:
NaiveForecaster()
步骤 5 - 请求预测#
最后,我们请求指定预测范围的预测。这需要在拟合预测器之后进行
[16]:
y_pred = forecaster.predict(fh)
[17]:
# plotting predictions and past data
plot_series(y, y_pred, labels=["y", "y_pred"])
[17]:
(<Figure size 1152x288 with 1 Axes>,
<AxesSubplot:ylabel='Number of airline passengers'>)
1.2.1 基本部署工作流程概览#
为了方便起见,我们将基本部署工作流程在一个单元格中呈现。这使用相同的数据,但预测器不同:预测同月观察到的最新值。
[18]:
from sktime.datasets import load_airline
from sktime.forecasting.base import ForecastingHorizon
from sktime.forecasting.naive import NaiveForecaster
[19]:
# step 1: data specification
y = load_airline()
# step 2: specifying forecasting horizon
fh = np.arange(1, 37)
# step 3: specifying the forecasting algorithm
forecaster = NaiveForecaster(strategy="last", sp=12)
# step 4: fitting the forecaster
forecaster.fit(y)
# step 5: querying predictions
y_pred = forecaster.predict(fh)
[20]:
# optional: plotting predictions and past data
plot_series(y, y_pred, labels=["y", "y_pred"])
[20]:
(<Figure size 1152x288 with 1 Axes>,
<AxesSubplot:ylabel='Number of airline passengers'>)
1.2.2 在 fit 中已需要预测范围的预测器#
有些预测器需要在 fit 中已经提供预测范围。如果未在 fit 中传递,这些预测器将产生信息性错误消息。所有预测器在 fit 中已传递预测范围后,都会记住该范围以供预测。此外,允许使用此类预测器的修改后工作流程如下
[21]:
# step 1: data specification
y = load_airline()
# step 2: specifying forecasting horizon
fh = np.arange(1, 37)
# step 3: specifying the forecasting algorithm
forecaster = NaiveForecaster(strategy="last", sp=12)
# step 4: fitting the forecaster
forecaster.fit(y, fh=fh)
# step 5: querying predictions
y_pred = forecaster.predict()
1.2.3 可以利用外生数据的预测器#
许多预测器可以利用外生时间序列,即,不是预测对象但对预测 y 有用的其他时间序列。外生时间序列总是作为 X 参数传递给 fit、predict 和其他方法(见下文)。外生时间序列应始终作为 pandas.DataFrames 传递。大多数能够处理外生时间序列的预测器会假定传递给 fit 的 X 的时间索引是传递给 fit 的 y 的时间索引的超集;并且传递给 predict 的 X 的时间索引是 fh 中时间索引的超集,尽管这不是一般的接口限制。不使用外生时间序列的预测器仍然接受此参数(但在内部不使用)。
传递外生数据的通用工作流程如下
[22]:
# step 1: data specification
y = load_airline()
# we create some dummy exogeneous data
X = pd.DataFrame(index=y.index)
# step 2: specifying forecasting horizon
fh = np.arange(1, 37)
# step 3: specifying the forecasting algorithm
forecaster = NaiveForecaster(strategy="last", sp=12)
# step 4: fitting the forecaster
forecaster.fit(y, X=X, fh=fh)
# step 5: querying predictions
y_pred = forecaster.predict(X=X)
注意:如工作流程 1.2.1 和 1.2.2 所述,一些使用外生变量的预测器也可能仅在 predict 中需要预测范围。此类预测器也可以按照步骤 4 和 5 进行调用,如下所示
forecaster.fit(y, X=X)
y_pred = forecaster.predict(fh=fh, X=X)
1.2.4. 多元预测#
sktime 中的所有预测器都支持多元预测 - 一些预测器是“真正的”多元预测器,其他所有预测器都是“按列应用”。
下面是使用 sktime.datasets 中的 Longley 数据集,并使用 VAR(向量自回归)预测器的通用多元预测工作流程示例。工作流程与单变量预测器相同,但输入具有多个变量(列)。
[23]:
from sktime.datasets import load_longley
from sktime.forecasting.var import VAR
_, y = load_longley()
y = y.drop(columns=["UNEMP", "ARMED", "POP"])
forecaster = VAR()
forecaster.fit(y, fh=[1, 2, 3])
y_pred = forecaster.predict()
多元预测器的输入 y 是一个 pandas.DataFrame,其中每列代表一个变量。
[24]:
y
[24]:
| GNPDEFL | GNP | |
|---|---|---|
| Period | ||
| 1947 | 83.0 | 234289.0 |
| 1948 | 88.5 | 259426.0 |
| 1949 | 88.2 | 258054.0 |
| 1950 | 89.5 | 284599.0 |
| 1951 | 96.2 | 328975.0 |
| 1952 | 98.1 | 346999.0 |
| 1953 | 99.0 | 365385.0 |
| 1954 | 100.0 | 363112.0 |
| 1955 | 101.2 | 397469.0 |
| 1956 | 104.6 | 419180.0 |
| 1957 | 108.4 | 442769.0 |
| 1958 | 110.8 | 444546.0 |
| 1959 | 112.6 | 482704.0 |
| 1960 | 114.2 | 502601.0 |
| 1961 | 115.7 | 518173.0 |
| 1962 | 116.9 | 554894.0 |
多元预测器的结果 y_pred 是一个 pandas.DataFrame,其中列是每个变量的预测值。y_pred 中的变量与多元预测器的输入 y 中的变量相同。
[25]:
y_pred
[25]:
| GNPDEFL | GNP | |
|---|---|---|
| 1963 | 121.688295 | 578514.398653 |
| 1964 | 124.353664 | 601873.015890 |
| 1965 | 126.847886 | 625411.588754 |
如上所述,所有预测器都接受多元输入并会产生多元预测。共有两类
真正的多元预测器,例如
VAR。对一个内生(y)变量的预测将依赖于其他变量的值。单变量预测器,例如
ARIMA。预测将按内生(y)变量进行,不受其他变量影响。
要显示完整的多元预测器列表,请搜索标签 'scitype:y' 的标签值为 'multivariate' 或 'both' 的预测器,如下所示
[26]:
from sktime.registry import all_estimators
for forecaster in all_estimators(filter_tags={"scitype:y": ["multivariate", "both"]}):
print(forecaster[0])
单变量预测器的标签值为 'univariate',并将为每列拟合一个模型。要访问按列划分的模型,请访问 forecasters_ 参数,该参数将已拟合的预测器存储在一个 pandas.DataFrame 中,已拟合的预测器位于对应于进行预测的变量的列中
[27]:
from sktime.datasets import load_longley
from sktime.forecasting.arima import ARIMA
_, y = load_longley()
y = y.drop(columns=["UNEMP", "ARMED", "POP"])
forecaster = ARIMA()
forecaster.fit(y, fh=[1, 2, 3])
forecaster.forecasters_
[27]:
| GNPDEFL | GNP | |
|---|---|---|
| 预测器 | ARIMA() | ARIMA() |
1.2.5 概率预测:预测区间、分位数、方差和分布预测#
sktime 提供了统一的接口来进行概率预测。以下方法可能可用于概率预测
predict_interval生成区间预测。除了任何predict参数外,必须提供参数coverage(标称区间覆盖率)。predict_quantiles生成分位数预测。除了任何predict参数外,必须提供参数alpha(分位数)。predict_var生成方差预测。这与predict的参数相同。predict_proba生成完整的分布预测。这与predict的参数相同。
并非所有预测器都能返回概率预测,但如果一个预测器提供了一种概率预测,它也能返回其他类型的概率预测。具有此类能力的预测器列表可以通过 registry.all_estimators 查询,搜索那些 capability:pred_int 标签值为 True 的预测器。
概率预测的基本工作流程与基本预测工作流程相似,不同之处在于使用其中一种概率预测方法代替 predict
[28]:
import numpy as np
from sktime.datasets import load_airline
from sktime.forecasting.theta import ThetaForecaster
# until fit, identical with the simple workflow
y = load_airline()
fh = np.arange(1, 13)
forecaster = ThetaForecaster(sp=12)
forecaster.fit(y, fh=fh)
[28]:
ThetaForecaster(sp=12)
现在我们介绍不同的概率预测方法。
predict_interval - 区间预测#
predict_interval 接受参数 coverage,该参数是一个浮点数(或浮点数列表),表示查询的预测区间的标称覆盖率。predict_interval 生成对称预测区间,例如,覆盖率为 0.9 将返回分位数 0.5 - coverage/2 = 0.05 的“下限”预测,以及分位数 0.5 + coverage/2 = 0.95 的“上限”预测。
[29]:
coverage = 0.9
y_pred_ints = forecaster.predict_interval(coverage=coverage)
y_pred_ints
[29]:
| 覆盖率 | ||
|---|---|---|
| 0.9 | ||
| 下限 | 上限 | |
| 1961-01 | 418.280122 | 464.281951 |
| 1961-02 | 402.215882 | 456.888054 |
| 1961-03 | 459.966115 | 522.110499 |
| 1961-04 | 442.589311 | 511.399213 |
| 1961-05 | 443.525029 | 518.409479 |
| 1961-06 | 506.585817 | 587.087736 |
| 1961-07 | 561.496771 | 647.248955 |
| 1961-08 | 557.363325 | 648.062362 |
| 1961-09 | 477.658059 | 573.047750 |
| 1961-10 | 407.915093 | 507.775353 |
| 1961-11 | 346.942927 | 451.082014 |
| 1961-12 | 394.708224 | 502.957139 |
返回的 y_pred_ints 是一个带有列多级索引的 pandas.DataFrame:第一级是拟合中 y 的变量名(如果不存在变量名,则为 Coverage),第二级是计算区间的覆盖率分数,顺序与输入 coverage 中相同;第三级列为 lower 和 upper。行是进行预测的索引(与 y_pred 或 fh 中的相同)。条目是同一行索引的标称覆盖率预测区间的下限/上限(作为列名)。
漂亮地绘制预测区间预测
[30]:
from sktime.utils import plotting
# also requires predictions
y_pred = forecaster.predict()
fig, ax = plotting.plot_series(
y, y_pred, labels=["y", "y_pred"], pred_interval=y_pred_ints
)
predict_quantiles - 分位数预测#
sktime 提供 predict_quantiles 作为统一接口来返回预测的分位数。类似于 predict_interval。
predict_quantiles 有一个参数 alpha,包含正在查询的分位数。类似于 predict_interval 的情况,alpha 可以是 float 或 list of floats。
[31]:
y_pred_quantiles = forecaster.predict_quantiles(alpha=[0.275, 0.975])
y_pred_quantiles
[31]:
| 分位数 | ||
|---|---|---|
| 0.275 | 0.975 | |
| 1961-01 | 432.922220 | 468.688317 |
| 1961-02 | 419.617697 | 462.124924 |
| 1961-03 | 479.746288 | 528.063108 |
| 1961-04 | 464.491078 | 517.990290 |
| 1961-05 | 467.360287 | 525.582417 |
| 1961-06 | 532.209080 | 594.798752 |
| 1961-07 | 588.791161 | 655.462877 |
| 1961-08 | 586.232268 | 656.750127 |
| 1961-09 | 508.020008 | 582.184819 |
| 1961-10 | 439.699997 | 517.340642 |
| 1961-11 | 380.089755 | 461.057159 |
| 1961-12 | 429.163185 | 513.325951 |
y_pred_quantiles,即 predict_quantiles 的输出,是一个带有两级列多级索引的 pandas.DataFrame。第一级是拟合中 y 的变量名(如果不存在变量名,则为 Quantiles),第二级是查询的分位数(来自 alpha)。行是进行预测的索引(与 y_pred 或 fh 中的相同)。条目是针对同一行时间索引、该变量和该分位数的分位数预测。
备注:为清晰起见:分位数预测和(对称)区间预测可以按如下方式相互转换。
alpha < 0.5: alpha 分位数预测等于覆盖率 = (0.5 - alpha) * 2 的预测区间的下限
alpha > 0.5: alpha 分位数预测等于覆盖率 = (alpha - 0.5) * 2 的预测区间的上限
predict_var - 方差预测#
predict_var 生成方差预测
[32]:
y_pred_var = forecaster.predict_var()
y_pred_var
[32]:
| 0 | |
|---|---|
| 1961-01 | 195.540039 |
| 1961-02 | 276.196489 |
| 1961-03 | 356.852939 |
| 1961-04 | 437.509389 |
| 1961-05 | 518.165839 |
| 1961-06 | 598.822289 |
| 1961-07 | 679.478739 |
| 1961-08 | 760.135189 |
| 1961-09 | 840.791639 |
| 1961-10 | 921.448089 |
| 1961-11 | 1002.104539 |
| 1961-12 | 1082.760989 |
输出 y_pred_var 的格式与 predict 相同,不同之处在于它总是被强制转换为 pandas.DataFrame,并且条目不是点预测,而是方差预测。
predict_proba - 分布预测#
要预测完整的预测分布,可以使用 predict_proba。由于这会返回 tensorflow Distribution 对象,因此必须安装 sktime 的深度学习依赖集 dl(包括 tensorflow 和 tensorflow-probability 依赖)。
[33]:
y_pred_proba = forecaster.predict_proba()
y_pred_proba
[33]:
<tfp.distributions.Normal 'Normal' batch_shape=[12, 1] event_shape=[] dtype=float32>
predict_proba 返回的分布默认为时间点上的边际分布,而非时间点上的联合分布。更准确地说,返回的 Distribution 对象的格式和解释如下
批量形状为 1D,长度与 fh 相同
事件形状为 1D,长度等于被预测的变量数量
第 i 个(批量)分布是 fh 第 i 个条目的预测
第 j 个(事件)分量是第 j 个变量,顺序与
fit/update中的 y 相同
要返回联合预测分布,可以将 marginal 参数设置为 False(目前正在进行中)。在这种情况下,将返回一个事件形状为 2D (len(fh), len(y)) 的 Distribution。
1.2.6 面板预测和分层预测#
sktime 提供了统一的接口来进行面板预测和分层预测。
所有 sktime 预测器都可以应用于面板和分层数据,这些数据需要以特定的输入格式呈现。并非真正的面板或分层预测器将按实例应用。
传递面板和分层数据的推荐格式(非唯一格式)是具有 MultiIndex 行的 pandas.DataFrame。在此 MultiIndex 中,最后一级必须采用与 sktime 兼容的时间索引格式,其余级别是面板或层次节点。
示例数据
[34]:
from sktime.utils._testing.hierarchical import _bottom_hier_datagen
y = _bottom_hier_datagen(no_levels=2)
y
[34]:
| 旅客 | |||
|---|---|---|---|
| l2_agg | l1_agg | 时间点 | |
| l2_node01 | l1_node04 | 1949-01 | 1751.046693 |
| 1949-02 | 1847.272729 | ||
| 1949-03 | 2072.660808 | ||
| 1949-04 | 2024.264252 | ||
| 1949-05 | 1895.470000 | ||
| ... | ... | ... | ... |
| l2_node03 | l1_node05 | 1960-08 | 7843.728855 |
| 1960-09 | 6557.204770 | ||
| 1960-10 | 5942.431795 | ||
| 1960-11 | 5016.687658 | ||
| 1960-12 | 5563.869028 |
864 行 × 1 列
如前所述,所有预测器,无论是真正的分层预测器还是非分层预测器,都可以应用本节描述的所有工作流程来生成分层预测。
语法与普通时间序列完全相同,除了输入和输出数据中的层次级别
[35]:
from sktime.forecasting.arima import ARIMA
fh = [1, 2, 3]
forecaster = ARIMA()
forecaster.fit(y, fh=fh)
forecaster.predict()
[35]:
| 旅客 | |||
|---|---|---|---|
| l2_agg | l1_agg | 时间点 | |
| l2_node01 | l1_node04 | 1961-01 | 7025.301868 |
| 1961-02 | 6932.869186 | ||
| 1961-03 | 6843.846928 | ||
| l2_node02 | l1_node01 | 1961-01 | 426.544850 |
| 1961-02 | 421.282983 | ||
| 1961-03 | 416.207550 | ||
| l1_node02 | 1961-01 | 2831.238136 | |
| 1961-02 | 2796.463164 | ||
| 1961-03 | 2762.919857 | ||
| l1_node03 | 1961-01 | 3281.334598 | |
| 1961-02 | 3235.589398 | ||
| 1961-03 | 3191.591150 | ||
| l1_node06 | 1961-01 | 699.784723 | |
| 1961-02 | 687.976011 | ||
| 1961-03 | 676.678320 | ||
| l2_node03 | l1_node05 | 1961-01 | 5492.522368 |
| 1961-02 | 5423.732250 | ||
| 1961-03 | 5357.407064 |
类似于多元预测,并非真正的分层预测器会按实例拟合。按实例拟合的预测器可以在 forecasters_ 参数中访问,该参数是一个 pandas.DataFrame,其中给定实例的预测器放置在对应于它们进行预测的实例索引的行中
[36]:
forecaster.forecasters_
[36]:
| 预测器 | ||
|---|---|---|
| l2_agg | l1_agg | |
| l2_node01 | l1_node04 | ARIMA() |
| l2_node02 | l1_node01 | ARIMA() |
| l1_node02 | ARIMA() | |
| l1_node03 | ARIMA() | |
| l1_node06 | ARIMA() | |
| l2_node03 | l1_node05 | ARIMA() |
如果数据既是分层又是多元的,并且预测器无法真正处理其中任何一种情况,则 forecasters_ 属性将同时具有用于变量的列索引和用于实例的行索引,并按实例和变量进行预测器拟合
[37]:
from sktime.forecasting.arima import ARIMA
from sktime.utils._testing.hierarchical import _make_hierarchical
y = _make_hierarchical(n_columns=2)
fh = [1, 2, 3]
forecaster = ARIMA()
forecaster.fit(y, fh=fh)
forecaster.forecasters_
[37]:
| c0 | c1 | ||
|---|---|---|---|
| h0 | h1 | ||
| h0_0 | h1_0 | ARIMA() | ARIMA() |
| h1_1 | ARIMA() | ARIMA() | |
| h1_2 | ARIMA() | ARIMA() | |
| h1_3 | ARIMA() | ARIMA() | |
| h0_1 | h1_0 | ARIMA() | ARIMA() |
| h1_1 | ARIMA() | ARIMA() | |
| h1_2 | ARIMA() | ARIMA() | |
| h1_3 | ARIMA() | ARIMA() |
关于分层预测的更多详细信息,包括归约、聚合、协调,将在“分层预测”教程中介绍。
在部署预测器之前评估其统计性能,并在持续部署时定期重新评估性能,这是一种良好的实践。基本批量预测任务的评估工作流程(如第 1.2 节中的工作流程所解决)包括将批量预测与实际值进行比较。这有时被称为(按批量进行的)回测。
基本评估工作流程如下
将代表性选择的历史序列分割为时间上的训练集和测试集。测试集在时间上应位于训练集的未来。
通过将预测器拟合到训练集,并查询测试集的预测结果,获得批量预测,如第 1.2 节所示
指定定量性能度量来比较实际测试集与预测结果
计算测试集上的定量性能
检验此性能是否在统计上优于选定的基线性能
注意:步骤 5(测试)目前在 sktime 中不受支持,但已列入开发路线图。目前,建议使用适当方法的自定义实现(例如,Diebold-Mariano 检验;平稳置信区间)。
注意:请注意,此评估设置决定了给定算法在过去数据上的表现如何。结果仅在未来性能可以假定反映过去性能的范围内具有代表性。这可以在某些假设下(例如,平稳性)论证,但通常是不成立的。因此,在多次应用算法的情况下,建议监测预测性能。
示例:在本示例中,我们将使用与第 1.2 节相同的航空公司数据。但是,不是预测未来 3 年,而是保留航空公司数据的最后 3 年(下文:y_test),并查看三年前,当被要求预测最近 3 年(下文:y_pred)时,该预测器将如何从之前的年份(下文:y_train)进行预测。“如何”由定量性能度量(下文:mean_absolute_percentage_error)衡量。这被认为是预测器在未来 3 年表现如何的指示(即第 1.2 节中所做的事情)。这是否准确取决于统计假设和数据属性(注意:通常并不准确 - 过去的性能通常不能指示未来的性能)。
步骤 1 - 将历史数据集分割为时间上的训练集和测试批量#
[38]:
from sktime.split import temporal_train_test_split
[39]:
y = load_airline()
y_train, y_test = temporal_train_test_split(y, test_size=36)
# we will try to forecast y_test from y_train
[40]:
# plotting for illustration
plot_series(y_train, y_test, labels=["y_train", "y_test"])
print(y_train.shape[0], y_test.shape[0])
步骤 2 - 从 y_train 对 y_test 进行预测#
这几乎是第 1.2 节工作流程的逐字复制,使用 y_train 预测 y_test 的索引。
[41]:
# we can simply take the indices from `y_test` where they already are stored
fh = ForecastingHorizon(y_test.index, is_relative=False)
forecaster = NaiveForecaster(strategy="last", sp=12)
forecaster.fit(y_train)
# y_pred will contain the predictions
y_pred = forecaster.predict(fh)
[42]:
# plotting for illustration
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
[42]:
(<Figure size 1152x288 with 1 Axes>,
<AxesSubplot:ylabel='Number of airline passengers'>)
步骤 3 和 4 - 指定预测度量标准,在测试集上进行评估#
下一步是指定预测度量标准。这些是输入预测和实际序列时返回数字的函数。它们与 sklearn 度量标准不同,因为它们接受带有索引的序列而不是 np.array。预测度量标准可以通过两种方式调用
使用简洁的函数接口,例如
mean_absolute_percentage_error,这是一个 python 函数(y_true : pd.Series, y_pred : pd.Series) -> float使用可组合的类接口,例如
MeanAbsolutePercentageError,这是一个 python 类,可以使用相同的签名调用
普通用户可以选择使用函数接口。类接口支持高级用例,例如参数修改、自定义度量组合、度量参数调优(本教程不包括)。
[43]:
from sktime.performance_metrics.forecasting import mean_absolute_percentage_error
[44]:
# option 1: using the lean function interface
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
# note: the FIRST argument is the ground truth, the SECOND argument are the forecasts
# the order matters for most metrics in general
[44]:
0.13189432350948402
为了正确解释这样的数字,了解相关度量标准的属性(例如,越低越好)以及与合适的基线和竞争算法进行比较很有用(参见步骤 5)。
[45]:
from sktime.performance_metrics.forecasting import MeanAbsolutePercentageError
[46]:
# option 2: using the composable class interface
mape = MeanAbsolutePercentageError(symmetric=False)
# the class interface allows to easily construct variants of the MAPE
# e.g., the non-symmetric version
# it also allows for inspection of metric properties
# e.g., are higher values better (answer: no)?
mape.get_tag("lower_is_better")
[46]:
True
[47]:
# evaluation works exactly like in option 2, but with the instantiated object
mape(y_test, y_pred)
[47]:
0.13189432350948402
注意:某些度量标准,例如 mean_absolute_scaled_error,在评估时也需要训练集。在这种情况下,训练集应作为 y_train 参数传递。请参阅各个度量标准的 API 参考。
注意:对于利用外生数据的预测器,工作流程是相同的 - 不会将 X 传递给度量标准。
步骤 5 - 根据基准测试性能#
一般来说,预测性能应根据基准性能进行定量测试。
目前(sktime v0.12.x),这是一个路线图开发项目。非常欢迎贡献。
1.3.1 基本批量预测评估工作流程概览 - 函数度量接口#
为了方便起见,我们将基本批量预测评估工作流程在一个单元格中呈现。此单元格使用简洁的函数度量接口。
[48]:
from sktime.datasets import load_airline
from sktime.forecasting.base import ForecastingHorizon
from sktime.forecasting.naive import NaiveForecaster
from sktime.performance_metrics.forecasting import mean_absolute_percentage_error
from sktime.split import temporal_train_test_split
[49]:
# step 1: splitting historical data
y = load_airline()
y_train, y_test = temporal_train_test_split(y, test_size=36)
# step 2: running the basic forecasting workflow
fh = ForecastingHorizon(y_test.index, is_relative=False)
forecaster = NaiveForecaster(strategy="last", sp=12)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
# step 3: specifying the evaluation metric and
# step 4: computing the forecast performance
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
# step 5: testing forecast performance against baseline
# under development
[49]:
0.13189432350948402
1.3.2 基本批量预测评估工作流程概览 - 度量类接口#
为了方便起见,我们将基本批量预测评估工作流程在一个单元格中呈现。此单元格使用度量标准的高级类规范接口。
[50]:
from sktime.datasets import load_airline
from sktime.forecasting.base import ForecastingHorizon
from sktime.forecasting.naive import NaiveForecaster
from sktime.performance_metrics.forecasting import MeanAbsolutePercentageError
from sktime.split import temporal_train_test_split
[51]:
# step 1: splitting historical data
y = load_airline()
y_train, y_test = temporal_train_test_split(y, test_size=36)
# step 2: running the basic forecasting workflow
fh = ForecastingHorizon(y_test.index, is_relative=False)
forecaster = NaiveForecaster(strategy="last", sp=12)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
# step 3: specifying the evaluation metric
mape = MeanAbsolutePercentageError(symmetric=False)
# if function interface is used, just use the function directly in step 4
# step 4: computing the forecast performance
mape(y_test, y_pred)
# step 5: testing forecast performance against baseline
# under development
[51]:
0.13189432350948402
常见的用例要求预测器定期更新新数据并进行滚动预测。如果必须在固定的时间点(例如,每天或每周)进行同类预测,这尤其有用。sktime 预测器通过 update 和 update_predict 方法支持这种部署工作流程。
update 方法可以在预测器已经拟合后调用,以摄取新数据并进行更新的预测 - 这被称为“更新步骤”。
更新后,预测器的内部“当前”状态(cutoff)设置为更新批次中看到的最新时间戳(假定晚于之前见过的数据)。
通用模式如下
指定预测策略
指定相对预测范围
使用
fit将预测器拟合到初始批量数据使用
predict对相对预测范围进行预测获取新数据;使用
update摄取新数据使用
predict对更新后的数据进行预测根据需要重复步骤 5 和 6
示例:假设在航空公司示例中,我们想提前一年进行预测,但从 1957 年 12 月开始,每个月都进行预测。最初几个月,预测将按如下方式进行
[52]:
from sktime.datasets import load_airline
from sktime.forecasting.ets import AutoETS
from sktime.utils.plotting import plot_series
[53]:
# we prepare the full data set for convenience
# note that in the scenario we will "know" only part of this at certain time points
y = load_airline()
[54]:
# December 1957
# this is the data known in December 1957
y_1957Dec = y[:-36]
# step 1: specifying the forecasting strategy
forecaster = AutoETS(auto=True, sp=12, n_jobs=-1)
# step 2: specifying the forecasting horizon: one year ahead, all months
fh = np.arange(1, 13)
# step 3: this is the first time we use the model, so we fit it
forecaster.fit(y_1957Dec)
# step 4: obtaining the first batch of forecasts for Jan 1958 - Dec 1958
y_pred_1957Dec = forecaster.predict(fh)
[55]:
# plotting predictions and past data
plot_series(y_1957Dec, y_pred_1957Dec, labels=["y_1957Dec", "y_pred_1957Dec"])
[55]:
(<Figure size 1152x288 with 1 Axes>,
<AxesSubplot:ylabel='Number of airline passengers'>)
[56]:
# January 1958
# new data is observed:
y_1958Jan = y[[-36]]
# step 5: we update the forecaster with the new data
forecaster.update(y_1958Jan)
# step 6: making forecasts with the updated data
y_pred_1958Jan = forecaster.predict(fh)
[57]:
# note that the fh is relative, so forecasts are automatically for 1 month later
# i.e., from Feb 1958 to Jan 1959
y_pred_1958Jan
[57]:
1958-02 341.514630
1958-03 392.849241
1958-04 378.518543
1958-05 375.658188
1958-06 426.006944
1958-07 470.569699
1958-08 467.100443
1958-09 414.450926
1958-10 360.957054
1958-11 315.202860
1958-12 357.898458
1959-01 363.036833
Freq: M, dtype: float64
[58]:
# plotting predictions and past data
plot_series(
y[:-35],
y_pred_1957Dec,
y_pred_1958Jan,
labels=["y_1957Dec", "y_pred_1957Dec", "y_pred_1958Jan"],
)
[58]:
(<Figure size 1152x288 with 1 Axes>,
<AxesSubplot:ylabel='Number of airline passengers'>)
[59]:
# February 1958
# new data is observed:
y_1958Feb = y[[-35]]
# step 5: we update the forecaster with the new data
forecaster.update(y_1958Feb)
# step 6: making forecasts with the updated data
y_pred_1958Feb = forecaster.predict(fh)
[60]:
# plotting predictions and past data
plot_series(
y[:-35],
y_pred_1957Dec,
y_pred_1958Jan,
y_pred_1958Feb,
labels=["y_1957Dec", "y_pred_1957Dec", "y_pred_1958Jan", "y_pred_1958Feb"],
)
[60]:
(<Figure size 1152x288 with 1 Axes>,
<AxesSubplot:ylabel='Number of airline passengers'>)
……依此类推。
先运行 update 然后运行 predict 的简写是 update_predict_single - 对于某些算法,这可能比分别调用 update 和 predict 更高效
[61]:
# March 1958
# new data is observed:
y_1958Mar = y[[-34]]
# step 5&6: update/predict in one step
forecaster.update_predict_single(y_1958Mar, fh=fh)
[61]:
1958-04 349.161935
1958-05 346.920065
1958-06 394.051656
1958-07 435.839910
1958-08 433.316755
1958-09 384.841740
1958-10 335.535138
1958-11 293.171527
1958-12 333.275492
1959-01 338.595127
1959-02 336.983070
1959-03 388.121198
Freq: M, dtype: float64
在滚动部署模式下,将估计器的“当前”状态(cutoff)移至更晚的时间可能很有用,例如,如果未观测到新数据,但时间已经推移;或者如果计算耗时过长,并且必须查询预测结果。
update 接口通过 update 和其他更新函数的 update_params 参数提供了此选项。
如果 update_params 设置为 False,则不会执行模型更新计算;仅存储数据,并将内部“当前”状态(cutoff)设置为最新日期。
[62]:
# April 1958
# new data is observed:
y_1958Apr = y[[-33]]
# step 5: perform an update without re-computing the model parameters
forecaster.update(y_1958Apr, update_params=False)
[62]:
AutoETS(auto=True, n_jobs=-1, sp=12)
sktime 也可以使用完整的批量数据模拟更新/预测部署模式。
这在部署中并不有用,因为它需要提前准备好所有数据;但是,它在回放中很有用,例如用于模拟或模型评估。
可以使用 update_predict 和一个重新采样构造函数来调用更新/预测回放模式,该构造函数编码了精确的步进方案。
[63]:
# from sktime.datasets import load_airline
# from sktime.forecasting.ets import AutoETS
# from sktime.split import ExpandingWindowSplitter
# from sktime.utils.plotting import plot_series
注意:已注释掉 - 接口的这一部分目前正在重做中。欢迎贡献和 PR。
[64]:
# for playback, the full data needs to be loaded in advance
# y = load_airline()
[65]:
# step 1: specifying the forecasting strategy
# forecaster = AutoETS(auto=True, sp=12, n_jobs=-1)
# step 2: specifying the forecasting horizon
# fh - np.arange(1, 13)
# step 3: specifying the cross-validation scheme
# cv = ExpandingWindowSplitter()
# step 4: fitting the forecaster - fh should be passed here
# forecaster.fit(y[:-36], fh=fh)
# step 5: rollback
# y_preds = forecaster.update_predict(y, cv)
为了评估预测器在滚动预测中的性能,需要在模拟滚动预测的设置中对其进行测试,通常是在过去数据上进行。请注意,第 1.3 节中的批量回测不适合作为滚动部署的评估设置,因为它仅测试单个预测批量。
高级评估工作流程可以使用 evaluate 基准测试函数执行。evaluate 接受以下参数
待评估的
forecaster用于时间分割的
scikit-learn重新采样策略(下文中的cv),例如ExpandingWindowSplitter或SlidingWindowSplitter一个
strategy(字符串):预测器应始终重新拟合,还是仅拟合一次然后更新
[66]:
from sktime.forecasting.arima import AutoARIMA
from sktime.forecasting.model_evaluation import evaluate
from sktime.split import ExpandingWindowSplitter
[67]:
forecaster = AutoARIMA(sp=12, suppress_warnings=True)
cv = ExpandingWindowSplitter(
step_length=12, fh=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], initial_window=72
)
df = evaluate(forecaster=forecaster, y=y, cv=cv, strategy="refit", return_data=True)
df.iloc[:, :5]
[67]:
| 测试_平均绝对百分比误差 | 拟合时间 | 预测时间 | 训练窗口长度 | 截止点 | |
|---|---|---|---|---|---|
| 0 | 0.061710 | 4.026436 | 0.006171 | 72 | 1954-12 |
| 1 | 0.050042 | 5.211994 | 0.006386 | 84 | 1955-12 |
| 2 | 0.029802 | 8.024385 | 0.005885 | 96 | 1956-12 |
| 3 | 0.053773 | 4.231226 | 0.005654 | 108 | 1957-12 |
| 4 | 0.073820 | 5.250797 | 0.006525 | 120 | 1958-12 |
| 5 | 0.030976 | 11.651850 | 0.006294 | 132 | 1959-12 |
[68]:
# visualization of a forecaster evaluation
fig, ax = plot_series(
y,
df["y_pred"].iloc[0],
df["y_pred"].iloc[1],
df["y_pred"].iloc[2],
df["y_pred"].iloc[3],
df["y_pred"].iloc[4],
df["y_pred"].iloc[5],
markers=["o", "", "", "", "", "", ""],
labels=["y_true"] + ["y_pred (Backtest " + str(x) + ")" for x in range(6)],
)
ax.legend();
待办:性能指标、平均值和测试 - 欢迎对 sktime 和教程的贡献。
2. sktime 中的预测器 - 查找、属性、主要系列#
本节总结了如何
在 sktime 中搜索预测器
预测器的属性、相应的搜索选项和标签
sktime中常用的预测器类型
通常,sktime 中所有可用的预测器都可以使用 all_estimators 命令列出。
这将列出 sktime 中的所有预测器,即使其软依赖项未安装。
[69]:
from sktime.registry import all_estimators
all_estimators("forecaster", as_dataframe=True)
[69]:
| 名称 | 估计器 | |
|---|---|---|
| 0 | ARIMA | <class 'sktime.forecasting.arima.ARIMA'> |
| 1 | AutoARIMA | <class 'sktime.forecasting.arima.AutoARIMA'> |
| 2 | AutoETS | <class 'sktime.forecasting.ets.AutoETS'> |
| 3 | AutoEnsembleForecaster | <class 'sktime.forecasting.compose._ensemble.A... |
| 4 | BATS | <class 'sktime.forecasting.bats.BATS'> |
| 5 | BaggingForecaster | <class 'sktime.forecasting.compose._bagging.Ba... |
| 6 | ColumnEnsembleForecaster | <class 'sktime.forecasting.compose._column_ens... |
| 7 | ConformalIntervals | <class 'sktime.forecasting.conformal.Conformal... |
| 8 | Croston | <class 'sktime.forecasting.croston.Croston'> |
| 9 | DirRecTabularRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Dir... |
| 10 | DirRecTimeSeriesRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Dir... |
| 11 | DirectTabularRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Dir... |
| 12 | DirectTimeSeriesRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Dir... |
| 13 | DontUpdate | <class 'sktime.forecasting.stream._update.Dont... |
| 14 | DynamicFactor | <class 'sktime.forecasting.dynamic_factor.Dyna... |
| 15 | EnsembleForecaster | <class 'sktime.forecasting.compose._ensemble.E... |
| 16 | ExponentialSmoothing | <class 'sktime.forecasting.exp_smoothing.Expon... |
| 17 | ForecastX | <class 'sktime.forecasting.compose._pipeline.F... |
| 18 | ForecastingGridSearchCV | <class 'sktime.forecasting.model_selection._tu... |
| 19 | ForecastingPipeline | <class 'sktime.forecasting.compose._pipeline.F... |
| 20 | ForecastingRandomizedSearchCV | <class 'sktime.forecasting.model_selection._tu... |
| 21 | MultioutputTabularRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Mul... |
| 22 | MultioutputTimeSeriesRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Mul... |
| 23 | MultiplexForecaster | <class 'sktime.forecasting.compose._multiplexe... |
| 24 | NaiveForecaster | <class 'sktime.forecasting.naive.NaiveForecast... |
| 25 | NaiveVariance | <class 'sktime.forecasting.naive.NaiveVariance'> |
| 26 | OnlineEnsembleForecaster | <class 'sktime.forecasting.online_learning._on... |
| 27 | PolynomialTrendForecaster | <class 'sktime.forecasting.trend.PolynomialTre... |
| 28 | Prophet | <class 'sktime.forecasting.fbprophet.Prophet'> |
| 29 | ReconcilerForecaster | <class 'sktime.forecasting.reconcile.Reconcile... |
| 30 | RecursiveTabularRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Rec... |
| 31 | RecursiveTimeSeriesRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Rec... |
| 32 | SARIMAX | <class 'sktime.forecasting.sarimax.SARIMAX'> |
| 33 | STLForecaster | <class 'sktime.forecasting.trend.STLForecaster'> |
| 34 | StackingForecaster | <class 'sktime.forecasting.compose._stack.Stac... |
| 35 | StatsForecastAutoARIMA | <class 'sktime.forecasting.statsforecast.Stats... |
| 36 | TBATS | <class 'sktime.forecasting.tbats.TBATS'> |
| 37 | ThetaForecaster | <class 'sktime.forecasting.theta.ThetaForecast... |
| 38 | TransformedTargetForecaster | <class 'sktime.forecasting.compose._pipeline.T... |
| 39 | TrendForecaster | <class 'sktime.forecasting.trend.TrendForecast... |
| 40 | UnobservedComponents | <class 'sktime.forecasting.structural.Unobserv... |
| 41 | UpdateEvery | <class 'sktime.forecasting.stream._update.Upda... |
| 42 | UpdateRefitsEvery | <class 'sktime.forecasting.stream._update.Upda... |
| 43 | VAR | <class 'sktime.forecasting.var.VAR'> |
| 44 | VARMAX | <class 'sktime.forecasting.varmax.VARMAX'> |
| 45 | VECM | <class 'sktime.forecasting.vecm.VECM'> |
结果数据框最后一列的条目是类,可以直接用于构造,或者只是检查正确的导入路径。
对于遍历预测器的逻辑,默认输出格式可能更方便
[70]:
forecaster_list = all_estimators("forecaster", as_dataframe=False)
# this returns a list of (name, estimator) tuples
forecaster_list[0]
[70]:
('ARIMA', sktime.forecasting.arima.ARIMA)
sktime 的所有预测器都有所谓的标签,这些标签描述了估计器的属性,例如,是否为多元、概率等。本节将描述标签的使用、检查和检索。
每个预测器都有标签,这些标签是键值对,可以描述能力或内部实现细节。
最重要的“能力”类标签如下
requires-fh-in-fit - 布尔值。预测器是否需要在 fit 中就提供预测范围 fh(True),还是可以在 predict 中晚些提供(False)。
scitype:y - 字符串。预测器是单变量("univariate")、严格多元("multivariate"),还是可以处理任意数量的变量("both")。
capability:pred_int - 布尔值。预测器是否可以通过 predict_interval 等返回概率预测,参见第 1.5 节。
ignores-exogeneous-X - 布尔值。预测器是否使用外生变量 X(False)或不使用(True)。如果预测器不使用 X,仍可以传递它以保持接口一致性,但会被忽略。
handles-missing-data - 布尔值。预测器是否可以处理输入 X 或 y 中的缺失数据。
可以通过 get_tags(列出所有标签)和 get_tag(获取一个标签的值)方法检查预测器实例的标签。
标签值可能取决于超参数选择。
[71]:
from sktime.forecasting.arima import ARIMA
ARIMA().get_tags()
[71]:
{'scitype:y': 'univariate',
'ignores-exogeneous-X': False,
'capability:pred_int': True,
'handles-missing-data': True,
'y_inner_mtype': 'pd.Series',
'X_inner_mtype': 'pd.DataFrame',
'requires-fh-in-fit': False,
'X-y-must-have-same-index': True,
'enforce_index_type': None,
'fit_is_empty': False,
'python_version': None,
'python_dependencies': 'pmdarima'}
y_inner_mtype 和 X_inner_mtype 指示预测器是否原生支持处理面板或分层数据 - 如果此处出现面板或分层 mtype,则表示支持(参见数据类型教程)。
可以使用 all_tags 工具获取所有标签的解释,参见第 2.2.3 节。
要列出带有标签的预测器,可以使用 all_estimators 工具并带有 return_tags 参数。
然后,生成的数据框可用于表格查询或子集选取。
[72]:
from sktime.registry import all_estimators
all_estimators(
"forecaster", as_dataframe=True, return_tags=["scitype:y", "requires-fh-in-fit"]
)
[72]:
| 名称 | 估计器 | scitype:y | requires-fh-in-fit | |
|---|---|---|---|---|
| 0 | ARIMA | <class 'sktime.forecasting.arima.ARIMA'> | univariate | False |
| 1 | AutoARIMA | <class 'sktime.forecasting.arima.AutoARIMA'> | univariate | False |
| 2 | AutoETS | <class 'sktime.forecasting.ets.AutoETS'> | univariate | False |
| 3 | AutoEnsembleForecaster | <class 'sktime.forecasting.compose._ensemble.A... | univariate | False |
| 4 | BATS | <class 'sktime.forecasting.bats.BATS'> | univariate | False |
| 5 | BaggingForecaster | <class 'sktime.forecasting.compose._bagging.Ba... | univariate | False |
| 6 | ColumnEnsembleForecaster | <class 'sktime.forecasting.compose._column_ens... | both | False |
| 7 | ConformalIntervals | <class 'sktime.forecasting.conformal.Conformal... | univariate | False |
| 8 | Croston | <class 'sktime.forecasting.croston.Croston'> | univariate | False |
| 9 | DirRecTabularRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Dir... | univariate | True |
| 10 | DirRecTimeSeriesRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Dir... | univariate | True |
| 11 | DirectTabularRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Dir... | univariate | True |
| 12 | DirectTimeSeriesRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Dir... | univariate | True |
| 13 | DontUpdate | <class 'sktime.forecasting.stream._update.Dont... | univariate | False |
| 14 | DynamicFactor | <class 'sktime.forecasting.dynamic_factor.Dyna... | multivariate | False |
| 15 | EnsembleForecaster | <class 'sktime.forecasting.compose._ensemble.E... | univariate | False |
| 16 | ExponentialSmoothing | <class 'sktime.forecasting.exp_smoothing.Expon... | univariate | False |
| 17 | ForecastX | <class 'sktime.forecasting.compose._pipeline.F... | univariate | True |
| 18 | ForecastingGridSearchCV | <class 'sktime.forecasting.model_selection._tu... | both | False |
| 19 | ForecastingPipeline | <class 'sktime.forecasting.compose._pipeline.F... | both | False |
| 20 | ForecastingRandomizedSearchCV | <class 'sktime.forecasting.model_selection._tu... | both | False |
| 21 | MultioutputTabularRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Mul... | univariate | True |
| 22 | MultioutputTimeSeriesRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Mul... | univariate | True |
| 23 | MultiplexForecaster | <class 'sktime.forecasting.compose._multiplexe... | both | False |
| 24 | NaiveForecaster | <class 'sktime.forecasting.naive.NaiveForecast... | univariate | False |
| 25 | NaiveVariance | <class 'sktime.forecasting.naive.NaiveVariance'> | univariate | False |
| 26 | OnlineEnsembleForecaster | <class 'sktime.forecasting.online_learning._on... | univariate | False |
| 27 | PolynomialTrendForecaster | <class 'sktime.forecasting.trend.PolynomialTre... | univariate | False |
| 28 | Prophet | <class 'sktime.forecasting.fbprophet.Prophet'> | univariate | False |
| 29 | ReconcilerForecaster | <class 'sktime.forecasting.reconcile.Reconcile... | univariate | False |
| 30 | RecursiveTabularRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Rec... | univariate | False |
| 31 | RecursiveTimeSeriesRegressionForecaster | <class 'sktime.forecasting.compose._reduce.Rec... | univariate | False |
| 32 | SARIMAX | <class 'sktime.forecasting.sarimax.SARIMAX'> | univariate | False |
| 33 | STLForecaster | <class 'sktime.forecasting.trend.STLForecaster'> | univariate | False |
| 34 | StackingForecaster | <class 'sktime.forecasting.compose._stack.Stac... | univariate | True |
| 35 | StatsForecastAutoARIMA | <class 'sktime.forecasting.statsforecast.Stats... | univariate | False |
| 36 | TBATS | <class 'sktime.forecasting.tbats.TBATS'> | univariate | False |
| 37 | ThetaForecaster | <class 'sktime.forecasting.theta.ThetaForecast... | univariate | False |
| 38 | TransformedTargetForecaster | <class 'sktime.forecasting.compose._pipeline.T... | both | False |
| 39 | TrendForecaster | <class 'sktime.forecasting.trend.TrendForecast... | univariate | False |
| 40 | UnobservedComponents | <class 'sktime.forecasting.structural.Unobserv... | univariate | False |
| 41 | UpdateEvery | <class 'sktime.forecasting.stream._update.Upda... | univariate | False |
| 42 | UpdateRefitsEvery | <class 'sktime.forecasting.stream._update.Upda... | univariate | False |
| 43 | VAR | <class 'sktime.forecasting.var.VAR'> | multivariate | False |
| 44 | VARMAX | <class 'sktime.forecasting.varmax.VARMAX'> | multivariate | False |
| 45 | VECM | <class 'sktime.forecasting.vecm.VECM'> | multivariate | False |
要事先按特定标签和标签值进行筛选,可以使用 filter_tags 参数
[73]:
# this lists all forecasters that can deal with multivariate data
all_estimators(
"forecaster", as_dataframe=True, filter_tags={"scitype:y": ["multivariate", "both"]}
)
[73]:
| 名称 | 估计器 | |
|---|---|---|
| 0 | ColumnEnsembleForecaster | <class 'sktime.forecasting.compose._column_ens... |
| 1 | DynamicFactor | <class 'sktime.forecasting.dynamic_factor.Dyna... |
| 2 | ForecastingGridSearchCV | <class 'sktime.forecasting.model_selection._tu... |
| 3 | ForecastingPipeline | <class 'sktime.forecasting.compose._pipeline.F... |
| 4 | ForecastingRandomizedSearchCV | <class 'sktime.forecasting.model_selection._tu... |
| 5 | MultiplexForecaster | <class 'sktime.forecasting.compose._multiplexe... |
| 6 | TransformedTargetForecaster | <class 'sktime.forecasting.compose._pipeline.T... |
| 7 | VAR | <class 'sktime.forecasting.var.VAR'> |
| 8 | VARMAX | <class 'sktime.forecasting.varmax.VARMAX'> |
| 9 | VECM | <class 'sktime.forecasting.vecm.VECM'> |
重要提示:如上所述,标签值可能取决于超参数设置,例如,ForecastingPipeline 只有当其中的预测器可以处理多元数据时才能处理多元数据。
在如上所示的检索中,类的标签通常设置为指示最一般的潜在值,例如,如果对于某些参数选择,估计器可以处理多元数据,则它将出现在列表中。
要列出所有预测器标签并附带标签解释,可以使用 all_tags 工具
[74]:
import pandas as pd
from sktime.registry import all_tags
# wrapping this in a pandas DataFrame for pretty display
pd.DataFrame(all_tags(estimator_types="forecaster"))[[0, 3]]
[74]:
| 0 | 3 | |
|---|---|---|
| 0 | X-y-must-have-same-index | fit/update 中的 X/y 和 predict 中的 X/fh 是否具有 ... |
| 1 | X_inner_mtype | 内部 _fit/_pr... 使用哪种机器类型 |
| 2 | capability:pred_int | 预测器是否实现了 predict_interval... |
| 3 | capability:pred_var | 预测器是否实现了 predict_variance? |
| 4 | enforce_index_type | 传递给输入检查、输入转换索引... |
| 5 | ignores-exogeneous-X | 预测器是否忽略外生数据 (X)? |
| 6 | requires-fh-in-fit | 预测器是否需要在 f 中已传递 fh... |
| 7 | scitype:y | 预测器支持哪种序列类型?... |
| 8 | y_inner_mtype | 内部 _fit/_pr... 使用哪种机器类型 |
sktime 支持许多常用的预测器,其中许多是从最先进的预测包中集成的。所有预测器都在统一的 sktime 接口下可用。
目前稳定支持的一些类包括
来自
statsmodels的ExponentialSmoothing、ThetaForecaster和autoETS来自
pmdarima的ARIMA和AutoARIMA来自
statsforecast的AutoARIMA来自
tbats的BATS和TBATS用于预测多项式趋势的
PolynomialTrendProphet,它是 Facebookprophet的接口
这不是完整列表,请使用第 2.1 节和 2.2 节中演示的 all_estimators。
为了说明,下面所有估计器都将基于基本预测工作流程呈现 - 尽管它们也支持统一 sktime 接口下的高级预测和评估工作流程(参见第 1 节)。
要在其他工作流程中使用,只需将“预测器规范块”(”forecaster=”)替换为下面示例中呈现的预测器规范块。
[75]:
# imports necessary for this chapter
from sktime.datasets import load_airline
from sktime.forecasting.base import ForecastingHorizon
from sktime.performance_metrics.forecasting import mean_absolute_percentage_error
from sktime.split import temporal_train_test_split
from sktime.utils.plotting import plot_series
# data loading for illustration (see section 1 for explanation)
y = load_airline()
y_train, y_test = temporal_train_test_split(y, test_size=36)
fh = ForecastingHorizon(y_test.index, is_relative=False)
sktime 集成了 statsmodels 中的一些统计预测算法:指数平滑、Theta 和 auto-ETS。
例如,要在航空公司数据集上使用带有加性趋势分量和乘性季节性的指数平滑,我们可以编写以下代码。请注意,由于这是月度数据,季节性周期 (sp) 的一个良好选择是 12(= 假设的一年周期)。
[76]:
from sktime.forecasting.exp_smoothing import ExponentialSmoothing
[77]:
forecaster = ExponentialSmoothing(trend="add", seasonal="additive", sp=12)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[77]:
0.05114163237371178
状态空间模型的指数平滑也可以像 R 中的 ets 函数一样实现自动化。这在 AutoETS 预测器中实现。
[78]:
from sktime.forecasting.ets import AutoETS
[79]:
forecaster = AutoETS(auto=True, sp=12, n_jobs=-1)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[79]:
0.06186318537056982
[80]:
# todo: explain Theta; explain how to get theta-lines
sktime 为其 ARIMA 类模型提供了 pmdarima 接口。对于带有设定参数的经典 ARIMA 模型,请使用 ARIMA 预测器。
[81]:
from sktime.forecasting.arima import ARIMA
[82]:
forecaster = ARIMA(
order=(1, 1, 0), seasonal_order=(0, 1, 0, 12), suppress_warnings=True
)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[82]:
0.04356744885278522
AutoARIMA 是一个自动调优的 ARIMA 变体,可自动获取最优的 pdq 参数。
[83]:
from sktime.forecasting.arima import AutoARIMA
[84]:
forecaster = AutoARIMA(sp=12, suppress_warnings=True)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[84]:
0.041489714388809135
[85]:
forecaster = AutoARIMA(sp=12, suppress_warnings=True)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_pred, y_test)
[85]:
0.040936759322166255
[86]:
# to obtain the fitted parameters, run
forecaster.get_fitted_params()
# should these not include pdq?
[86]:
{'ar.L1': -0.24111779230017605,
'sigma2': 92.74986650446229,
'order': (1, 1, 0),
'seasonal_order': (0, 1, 0, 12),
'aic': 704.0011679023331,
'aicc': 704.1316026849419,
'bic': 709.1089216855343,
'hqic': 706.0650836393346}
sktime 为其提供了 `tbats <intive-DataScience/tbats>`__ 包中的 BATS 和 TBATS 接口。
[87]:
from sktime.forecasting.bats import BATS
[88]:
forecaster = BATS(sp=12, use_trend=True, use_box_cox=False)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[88]:
0.08185558959286515
[89]:
from sktime.forecasting.tbats import TBATS
[90]:
forecaster = TBATS(sp=12, use_trend=True, use_box_cox=False)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[90]:
0.08024090844021753
sktime 提供了对 Facebook 的 `fbprophet <facebook/prophet>`__ 接口。
[91]:
from sktime.forecasting.fbprophet import Prophet
当前接口不支持周期索引,只支持 pd.DatetimeIndex。考虑通过贡献 sktime 来改进这一点。
[92]:
# Convert index to pd.DatetimeIndex
z = y.copy()
z = z.to_timestamp(freq="M")
z_train, z_test = temporal_train_test_split(z, test_size=36)
[93]:
forecaster = Prophet(
seasonality_mode="multiplicative",
n_changepoints=int(len(y_train) / 12),
add_country_holidays={"country_name": "Germany"},
yearly_seasonality=True,
weekly_seasonality=False,
daily_seasonality=False,
)
forecaster.fit(z_train)
y_pred = forecaster.predict(fh.to_relative(cutoff=y_train.index[-1]))
y_pred.index = y_test.index
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[93]:
0.07276862950407971
我们还可以使用 `UnobservedComponents <https://statsmodels.cn/stable/generated/statsmodels.tsa.statespace.structural.UnobservedComponents.html>`__ 类从 `statsmodels <https://statsmodels.cn/stable/index.html>`__ 生成使用状态空间模型的预测。
[94]:
from sktime.forecasting.structural import UnobservedComponents
[95]:
# We can model seasonality using Fourier modes as in the Prophet model.
forecaster = UnobservedComponents(
level="local linear trend", freq_seasonal=[{"period": 12, "harmonics": 10}]
)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[95]:
0.0497366365924174
sktime 为其 AutoARIMA 类模型提供了 StatsForecast 接口。AutoARIMA 是一个自动调优的 ARIMA 变体,可自动获取最优的 pdq 参数。
[96]:
from sktime.forecasting.statsforecast import StatsForecastAutoARIMA
[97]:
forecaster = StatsForecastAutoARIMA(sp=12)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_pred, y_test)
[97]:
0.04093539044441262
3. 高级组合模式 - 管道、降维、自动机器学习等#
sktime 支持多种高级组合模式,以便从更简单的组件创建预测器。
Reduction(降维)- 从“更简单”科学类型的估计器构建预测器,例如
scikit-learn回归器。一个常见示例是通过滚动窗口进行特征/标签表格化,也称为“直接降维策略”。Tuning(调优)- 以数据驱动的方式确定预测器的超参数值。一个常见示例是对训练/测试拆分进行时间滚动重采样的网格搜索。
Pipelining(管道化)- 将转换器与预测器连接以获得一个预测器。一个常见示例是先去除趋势和季节性,然后进行预测,其中一个实例是常见的“STL 预测器”。
AutoML,也称为自动模型选择 - 使用自动调优策略不仅选择超参数,还选择整个预测策略。一个常见示例是在线多路复用器调优。
为了说明,下面所有估计器都将基于基本预测工作流程呈现 - 尽管它们也支持统一 sktime 接口下的高级预测和评估工作流程(参见第 1 节)。
要在其他工作流程中使用,只需将“预测器规范块”(”forecaster=”)替换为下面示例中呈现的预测器规范块。
[98]:
# imports necessary for this chapter
from sktime.datasets import load_airline
from sktime.forecasting.base import ForecastingHorizon
from sktime.performance_metrics.forecasting import mean_absolute_percentage_error
from sktime.split import temporal_train_test_split
from sktime.utils.plotting import plot_series
# data loading for illustration (see section 1 for explanation)
y = load_airline()
y_train, y_test = temporal_train_test_split(y, test_size=36)
fh = ForecastingHorizon(y_test.index, is_relative=False)
sktime 提供了一个元估计器,允许使用任何 scikit-learn 估计器进行预测。
模块化且与 scikit-learn 兼容,因此我们可以轻松应用任何
scikit-learn回归器来解决我们的预测问题,参数化且可调优,允许我们调优超参数,例如窗口长度或生成预测的策略。
自适应,因为它将
scikit-learn的估计器接口适应为预测器的接口,确保我们可以调优并正确评估我们的模型。
示例:我们将定义一种表格化降维策略,将 k 最近邻回归器(sklearn KNeighborsRegressor)转换为预测器。组合算法是符合 sktime 预测器接口的对象(图:大机器人),并且包含回归器作为可参数访问的组件(图:小机器人)。在 fit 中,组合算法使用滑动窗口策略对数据进行表格化,并将回归器拟合到表格化数据(图:左半部分)。在 predict 中,组合算法向回归器提供最后观察到的窗口以获得预测(图:右半部分)。

下面,使用简写函数 make_reduction 构建组合,该函数生成 sktime 预测器科学类型的估计器。调用时传入一个构建好的 scikit-learn 回归器 regressor,以及可以稍后作为超参数进行调优的附加参数。
[99]:
from sklearn.neighbors import KNeighborsRegressor
from sktime.forecasting.compose import make_reduction
[100]:
regressor = KNeighborsRegressor(n_neighbors=1)
forecaster = make_reduction(regressor, window_length=15, strategy="recursive")
[101]:
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[101]:
0.12887507224382988
在上面的示例中,我们使用了“recursive”(递归)降维策略。其他已实现的策略有:
“direct”,
“dirrec”,
“multioutput”。
参数可以使用与 scikit-learn 兼容的 get_params 功能进行检查(并使用 set_params 进行设置)。这提供了对 KNeighborsRegressor 参数(作为 estimator_etc)和降维策略的 window_length 的可调和嵌套访问。请注意,strategy 不可访问,因为在 utility 函数下面,它被映射到不同的算法类上。有关跨算法调优的信息,请参阅下面的“autoML”部分。
[102]:
forecaster.get_params()
[102]:
{'estimator__algorithm': 'auto',
'estimator__leaf_size': 30,
'estimator__metric': 'minkowski',
'estimator__metric_params': None,
'estimator__n_jobs': None,
'estimator__n_neighbors': 1,
'estimator__p': 2,
'estimator__weights': 'uniform',
'estimator': KNeighborsRegressor(n_neighbors=1),
'transformers': None,
'window_length': 15}
一种常见的组合模式是管道化:例如,先对数据进行去季节性或去趋势处理,然后对去趋势/去季节性后的序列进行预测。进行预测时,需要将趋势和季节性分量加回到数据中。
3.2.1 基本预测管道#
sktime 为这种组合建模提供了一个通用管道对象 TransformedTargetForecaster。它将任意数量的转换与预测器链式连接。转换可以是预处理转换,也可以是后处理转换。下面可以看到一个带有预处理转换的预测器示例。
[103]:
from sktime.forecasting.arima import ARIMA
from sktime.forecasting.compose import TransformedTargetForecaster
from sktime.transformations.series.detrend import Deseasonalizer
[104]:
forecaster = TransformedTargetForecaster(
[
("deseasonalize", Deseasonalizer(model="multiplicative", sp=12)),
("forecast", ARIMA()),
]
)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[104]:
0.13969973496344534
在上面的示例中,TransformedTargetForecaster 是用一个步骤列表构建的,每个步骤是一对名称和估计器,其中最后一个估计器是预测器科学类型。预处理转换器应该是具有 transform 和 inverse_transform 方法的序列到序列转换器。结果估计器是预测器科学类型,并具有所有接口定义方法。在 fit 中,所有转换器将 fit_transforms 应用于数据,然后是预测器的 fit;在 predict 中,首先应用预测器的 predict,然后按相反顺序应用转换器的 inverse_transform。
上面所示的相同管道,也可以使用乘法魔法方法 * 构建。
这将创建如上所示的 TransformedTargetForecaster,组件被赋予默认名称。
[105]:
forecaster = Deseasonalizer(model="multiplicative", sp=12) * ARIMA()
forecaster
[105]:
TransformedTargetForecaster(steps=[Deseasonalizer(model='multiplicative',
sp=12),
ARIMA()])
在使用魔法方法构建的管道中,名称会被唯一化,以防例如使用了两个去季节性转换器。
多重季节性模型示例
[106]:
forecaster = (
Deseasonalizer(model="multiplicative", sp=12)
* Deseasonalizer(model="multiplicative", sp=3)
* ARIMA()
)
forecaster.get_params()
[106]:
{'steps': [Deseasonalizer(model='multiplicative', sp=12),
Deseasonalizer(model='multiplicative', sp=3),
ARIMA()],
'Deseasonalizer_1': Deseasonalizer(model='multiplicative', sp=12),
'Deseasonalizer_2': Deseasonalizer(model='multiplicative', sp=3),
'ARIMA': ARIMA(),
'Deseasonalizer_1__model': 'multiplicative',
'Deseasonalizer_1__sp': 12,
'Deseasonalizer_2__model': 'multiplicative',
'Deseasonalizer_2__sp': 3,
'ARIMA__concentrate_scale': False,
'ARIMA__enforce_invertibility': True,
'ARIMA__enforce_stationarity': True,
'ARIMA__hamilton_representation': False,
'ARIMA__maxiter': 50,
'ARIMA__measurement_error': False,
'ARIMA__method': 'lbfgs',
'ARIMA__mle_regression': True,
'ARIMA__order': (1, 0, 0),
'ARIMA__out_of_sample_size': 0,
'ARIMA__scoring': 'mse',
'ARIMA__scoring_args': None,
'ARIMA__seasonal_order': (0, 0, 0, 0),
'ARIMA__simple_differencing': False,
'ARIMA__start_params': None,
'ARIMA__suppress_warnings': False,
'ARIMA__time_varying_regression': False,
'ARIMA__trend': None,
'ARIMA__with_intercept': True}
我们还可以创建一个带有后处理转换的管道,这些转换是在预测器之后进行的,可以在魔法方法管道或 TransformedTargetForecaster 中实现。
下面是一个多重季节性模型示例,预测结果经过整数舍入后处理。
[107]:
from sktime.transformations.series.func_transform import FunctionTransformer
forecaster = ARIMA() * FunctionTransformer(lambda y: y.round())
forecaster.fit_predict(y, fh=fh).head(3)
[107]:
1958-01 334.0
1958-02 338.0
1958-03 317.0
Freq: M, dtype: float64
预处理和后处理转换器都可以存在,在这种情况下,后处理转换将在预处理转换的 inverse-transform 之后应用。
[108]:
forecaster = (
Deseasonalizer(model="multiplicative", sp=12)
* Deseasonalizer(model="multiplicative", sp=3)
* ARIMA()
* FunctionTransformer(lambda y: y.round())
)
forecaster.fit_predict(y_train, fh=fh).head(3)
[108]:
1958-01 339.0
1958-02 334.0
1958-03 381.0
Freq: M, dtype: float64
3.2.2 Detrender 作为管道组件#
对于去趋势,我们可以使用 Detrender。这是一个序列到转换器科学类型的估计器,它封装了任意预测器。例如,对于线性去趋势,我们可以使用 PolynomialTrendForecaster 来拟合线性趋势,然后使用 TransformedTargetForecaster 中的 Detrender 转换器来减去/加上它。
为了更好地理解发生了什么,我们首先单独检查 Detrender。
[109]:
from sktime.forecasting.trend import PolynomialTrendForecaster
from sktime.transformations.series.detrend import Detrender
[110]:
# linear detrending
forecaster = PolynomialTrendForecaster(degree=1)
transformer = Detrender(forecaster=forecaster)
yt = transformer.fit_transform(y_train)
# internally, the Detrender uses the in-sample predictions
# of the PolynomialTrendForecaster
forecaster = PolynomialTrendForecaster(degree=1)
fh_ins = -np.arange(len(y_train)) # in-sample forecasting horizon
y_pred = forecaster.fit(y_train).predict(fh=fh_ins)
plot_series(
y_train, y_pred, yt, labels=["y_train", "fitted linear trend", "residuals"]
);
由于 Detrender 是序列到序列转换器科学类型,因此可以在 TransformedTargetForecaster 中用于对任何预测器进行去趋势。
[111]:
forecaster = TransformedTargetForecaster(
[
("deseasonalize", Deseasonalizer(model="multiplicative", sp=12)),
("detrend", Detrender(forecaster=PolynomialTrendForecaster(degree=1))),
("forecast", ARIMA()),
]
)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[111]:
0.05610168219854761
3.2.3 复杂管道组合和参数检查#
sktime 遵循 scikit-learn 的可组合性和嵌套参数检查理念。只要估计器具有正确的科学类型,就可以将其用作需要该科学类型的任何组合原则的一部分。上面,我们已经看到了 Detrender 中的预测器示例,它是一个序列到序列转换器科学类型的估计器,其中一个组件是预测器科学类型。类似地,在 TransformedTargetForecaster 中,我们可以使用第 3.1 节中的降维组合作为管道中的最后一个预测器元素,其内部有一个表格回归器科学类型的估计器,即 KNeighborsRegressor。
[112]:
from sklearn.neighbors import KNeighborsRegressor
from sktime.forecasting.compose import make_reduction
[113]:
forecaster = TransformedTargetForecaster(
[
("deseasonalize", Deseasonalizer(model="multiplicative", sp=12)),
("detrend", Detrender(forecaster=PolynomialTrendForecaster(degree=1))),
(
"forecast",
make_reduction(
KNeighborsRegressor(),
window_length=15,
strategy="recursive",
),
),
]
)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[113]:
0.058708387889316475
与 scikit-learn 模型一样,我们可以通过 get_params 和 set_params 检查和访问任何组件的参数。
[114]:
forecaster.get_params()
[114]:
{'steps': [('deseasonalize', Deseasonalizer(model='multiplicative', sp=12)),
('detrend', Detrender(forecaster=PolynomialTrendForecaster())),
('forecast',
RecursiveTabularRegressionForecaster(estimator=KNeighborsRegressor(),
window_length=15))],
'deseasonalize': Deseasonalizer(model='multiplicative', sp=12),
'detrend': Detrender(forecaster=PolynomialTrendForecaster()),
'forecast': RecursiveTabularRegressionForecaster(estimator=KNeighborsRegressor(),
window_length=15),
'deseasonalize__model': 'multiplicative',
'deseasonalize__sp': 12,
'detrend__forecaster__degree': 1,
'detrend__forecaster__regressor': None,
'detrend__forecaster__with_intercept': True,
'detrend__forecaster': PolynomialTrendForecaster(),
'forecast__estimator__algorithm': 'auto',
'forecast__estimator__leaf_size': 30,
'forecast__estimator__metric': 'minkowski',
'forecast__estimator__metric_params': None,
'forecast__estimator__n_jobs': None,
'forecast__estimator__n_neighbors': 5,
'forecast__estimator__p': 2,
'forecast__estimator__weights': 'uniform',
'forecast__estimator': KNeighborsRegressor(),
'forecast__transformers': None,
'forecast__window_length': 15}
sktime 提供了参数调优策略作为预测器科学类型的组合器,类似于 scikit-learn 的 GridSearchCV。
组合器 ForecastingGridSearchCV(及其他调优器)由要调优的预测器、交叉验证构造函数、scikit-learn 参数网格以及调优策略特定的参数构建。交叉验证构造函数遵循 scikit-learn 的重采样器接口,并且可以互换使用。
作为示例,我们展示了使用时间滑动窗口调优方法对第 3.1 节中降维组合器的窗口长度进行调优。
[115]:
from sklearn.neighbors import KNeighborsRegressor
from sktime.forecasting.compose import make_reduction
from sktime.forecasting.model_selection import ForecastingGridSearchCV
from sktime.split import SlidingWindowSplitter
[116]:
regressor = KNeighborsRegressor()
forecaster = make_reduction(regressor, window_length=15, strategy="recursive")
param_grid = {"window_length": [7, 12, 15]}
# We fit the forecaster on an initial window which is 80% of the historical data
# then use temporal sliding window cross-validation to find the optimal hyper-parameters
cv = SlidingWindowSplitter(initial_window=int(len(y_train) * 0.8), window_length=20)
gscv = ForecastingGridSearchCV(
forecaster, strategy="refit", cv=cv, param_grid=param_grid
)
与任何其他组合一样,生成的预测器提供了 sktime 预测器的统一接口 - 窗口分割、调优等无需手动操作,都在统一接口后面完成。
[117]:
gscv.fit(y_train)
y_pred = gscv.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[117]:
0.16607972017556033
可以访问 best_params_ 属性来获取调优后的参数。
[118]:
gscv.best_params_
[118]:
{'window_length': 7}
通过访问 best_forecaster_ 属性,可以检索到已设置超参数的最佳预测器实例。
[119]:
gscv.best_forecaster_
[119]:
RecursiveTabularRegressionForecaster(estimator=KNeighborsRegressor(),
window_length=7)
与 scikit-learn 中一样,可以通过访问其 get_params 键来调优嵌套组件的参数 - 默认情况下,如果 [estimatorname] 是组件的名称,而 [parametername] 是估计器 [estimatorname] 中的参数名称,则键为 [estimatorname]__[parametername]。
例如,下面我们除了调优 window_length 外,还调优 KNeighborsRegressor 组件的 n_neighbors。可以使用 forecaster.get_params() 轻松查询可调优参数。
[120]:
from sklearn.neighbors import KNeighborsRegressor
from sktime.forecasting.compose import make_reduction
from sktime.forecasting.model_selection import ForecastingGridSearchCV
from sktime.split import SlidingWindowSplitter
[121]:
param_grid = {"window_length": [7, 12, 15], "estimator__n_neighbors": np.arange(1, 10)}
regressor = KNeighborsRegressor()
forecaster = make_reduction(regressor, strategy="recursive")
cv = SlidingWindowSplitter(initial_window=int(len(y_train) * 0.8), window_length=30)
gscv = ForecastingGridSearchCV(forecaster, cv=cv, param_grid=param_grid)
[122]:
gscv.fit(y_train)
y_pred = gscv.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[122]:
0.13988948769413537
[123]:
gscv.best_params_
[123]:
{'estimator__n_neighbors': 2, 'window_length': 12}
上述方法的一种替代方案是使用 scikit-learn 的 GridSearchCV 和独立的参数网格单独调优回归器。由于这种方法没有使用“总体”性能指标来调优内部回归器,因此组合预测器的性能可能会有所不同。
[124]:
from sklearn.model_selection import GridSearchCV
# tuning the 'n_estimator' hyperparameter of RandomForestRegressor from scikit-learn
regressor_param_grid = {"n_neighbors": np.arange(1, 10)}
forecaster_param_grid = {"window_length": [7, 12, 15]}
# create a tunnable regressor with GridSearchCV
regressor = GridSearchCV(KNeighborsRegressor(), param_grid=regressor_param_grid)
forecaster = make_reduction(regressor, strategy="recursive")
cv = SlidingWindowSplitter(initial_window=int(len(y_train) * 0.8), window_length=30)
gscv = ForecastingGridSearchCV(forecaster, cv=cv, param_grid=forecaster_param_grid)
[125]:
gscv.fit(y_train)
y_pred = gscv.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[125]:
0.14493362646957736
注意:一个聪明的实现会使用缓存来保存内部调优的部分结果,从而显著减少运行时长 - 当前 sktime 不支持此功能。考虑帮助改进 sktime。
sktime 中的所有调优算法都允许用户设置评分指标;对于预测,默认是平均绝对百分比误差。可以使用 score 参数将评分设置为任何评分函数或类,如第 1.3 节所述。
重采样调优器会保留各个预测重采样折叠上的性能,这些性能可以在通过调用 fit 拟合预测器后从 cv_results_ 参数中检索。
在上面的示例中,如果使用均方误差而不是平均绝对百分比误差进行调优,则需要如下定义预测器:
[126]:
from sktime.performance_metrics.forecasting import MeanSquaredError
[127]:
mse = MeanSquaredError()
param_grid = {"window_length": [7, 12, 15]}
regressor = KNeighborsRegressor()
cv = SlidingWindowSplitter(initial_window=int(len(y_train) * 0.8), window_length=30)
gscv = ForecastingGridSearchCV(forecaster, cv=cv, param_grid=param_grid, scoring=mse)
拟合后,可以如下访问各个折叠上的性能:
[128]:
gscv.fit(y_train)
gscv.cv_results_
[128]:
| mean_test_MeanSquaredError | mean_fit_time | mean_pred_time | params | rank_test_MeanSquaredError | |
|---|---|---|---|---|---|
| 0 | 2600.750255 | 0.051403 | 0.002837 | {'window_length': 7} | 3.0 |
| 1 | 1134.999053 | 0.051353 | 0.002975 | {'window_length': 12} | 1.0 |
| 2 | 1285.133614 | 0.050748 | 0.003272 | {'window_length': 15} | 2.0 |
sktime 提供了许多用于集成和自动模型选择的组合器。与使用数据驱动策略为固定预测器寻找最优超参数的调优不同,本节中的策略是在估计器层面进行组合或选择,使用一组预测器进行组合或从中选择。
本节讨论的策略有:
autoML,即自动模型选择
简单集成
带有权重更新的预测加权集成,以及对冲策略
对预测器进行模型选择最灵活的方法是使用 MultiplexForecaster,它将从列表中选择预测器作为超参数暴露出来,可以通过通用的超参数调优策略(如第 3.3 节所示)进行调优。
独立来看,MultiplexForecaster 是用一个命名列表 forecasters(包含多个预测器)构建的。它有一个超参数 selected_forecaster,可以设置为 forecasters 中任何预测器的名称,其行为与 forecasters 中由 selected_forecaster 键控的预测器完全一致。
[129]:
from sktime.forecasting.compose import MultiplexForecaster
from sktime.forecasting.exp_smoothing import ExponentialSmoothing
from sktime.forecasting.naive import NaiveForecaster
[130]:
forecaster = MultiplexForecaster(
forecasters=[
("naive", NaiveForecaster(strategy="last")),
("ets", ExponentialSmoothing(trend="add", sp=12)),
],
)
[131]:
forecaster.set_params(**{"selected_forecaster": "naive"})
# now forecaster behaves like NaiveForecaster(strategy="last")
[131]:
MultiplexForecaster(forecasters=[('naive', NaiveForecaster()),
('ets',
ExponentialSmoothing(sp=12, trend='add'))],
selected_forecaster='naive')
[132]:
forecaster.set_params(**{"selected_forecaster": "ets"})
# now forecaster behaves like ExponentialSmoothing(trend="add", sp=12))
[132]:
MultiplexForecaster(forecasters=[('naive', NaiveForecaster()),
('ets',
ExponentialSmoothing(sp=12, trend='add'))],
selected_forecaster='ets')
MultiplexForecaster 独立使用时作用不大,但与调优包装器结合使用时,可以实现灵活的自动机器学习。下面定义了一个预测器,通过第 3.3 节中的滑动窗口调优方法从 NaiveForecaster 和 ExponentialSmoothing 中选择一个。
结合通过 update 功能(参见第 1.4 节)滚动使用预测器,调优后的多路复用器可以随着时间的推移,根据性能在 NaiveForecaster 和 ExponentialSmoothing 之间来回切换。
[133]:
from sktime.forecasting.model_selection import ForecastingGridSearchCV
from sktime.split import SlidingWindowSplitter
[134]:
forecaster = MultiplexForecaster(
forecasters=[
("naive", NaiveForecaster(strategy="last")),
("ets", ExponentialSmoothing(trend="add", sp=12)),
]
)
cv = SlidingWindowSplitter(initial_window=int(len(y_train) * 0.5), window_length=30)
forecaster_param_grid = {"selected_forecaster": ["ets", "naive"]}
gscv = ForecastingGridSearchCV(forecaster, cv=cv, param_grid=forecaster_param_grid)
[135]:
gscv.fit(y_train)
y_pred = gscv.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[135]:
0.19886711926999853
与任何调优后的预测器一样,可以使用 best_params_ 和 best_forecaster_ 检索最佳参数和调优后的预测器实例。
[136]:
gscv.best_params_
[136]:
{'selected_forecaster': 'naive'}
[137]:
gscv.best_forecaster_
[137]:
MultiplexForecaster(forecasters=[('naive', NaiveForecaster()),
('ets',
ExponentialSmoothing(sp=12, trend='add'))],
selected_forecaster='naive')
sktime 还提供了在管道内部自动选择管道组件(即管道结构)的功能。这可以通过 OptionalPassthrough 转换器实现。
OptionalPassthrough 转换器允许调优管道内的转换器是否应用于数据。例如,如果我们想调优 sklearn.StandardScaler 是否能为预测带来优势,我们就用 OptionalPassthrough 包装它。在内部,OptionalPassthrough 有一个超参数 passthrough: bool 是可调优的;当 False 时,组合的行为类似于包装的转换器,当 True 时,它会忽略内部的转换器。
为了有效使用 OptionalPasstrhough,请使用 scikit-learn 中熟悉的 __(双下划线)表示法定义合适的参数集。这允许访问和调优嵌套对象的属性,例如 TabularToSeriesAdaptor(StandardScaler())。如果我们有两层以上的嵌套,可以使用多个 __。
在下面的示例中,我们构建了一个去季节化/缩放管道,并对去季节化器和缩放器是否包含在管道中的四种可能组合(2 乘以 2 = 4)进行调优;同时还对预测器和缩放器的参数进行调优。
注意:这可以任意地与第 3.4.1 节中的 MultiplexForecaster 结合使用,以同时选择管道架构和管道结构。
注意:scikit-learn 和 sktime 目前不支持条件参数集(不像例如 mlr3 包)。这意味着即使 scaler 被跳过,网格搜索也会对其参数进行优化。设计/实现此功能将是一个有趣的贡献或研究领域。
[138]:
from sklearn.preprocessing import StandardScaler
from sktime.datasets import load_airline
from sktime.forecasting.compose import TransformedTargetForecaster
from sktime.forecasting.model_selection import ForecastingGridSearchCV
from sktime.forecasting.naive import NaiveForecaster
from sktime.split import SlidingWindowSplitter
from sktime.transformations.compose import OptionalPassthrough
from sktime.transformations.series.adapt import TabularToSeriesAdaptor
from sktime.transformations.series.detrend import Deseasonalizer
[139]:
# create pipeline
pipe = TransformedTargetForecaster(
steps=[
("deseasonalizer", OptionalPassthrough(Deseasonalizer())),
("scaler", OptionalPassthrough(TabularToSeriesAdaptor(StandardScaler()))),
("forecaster", NaiveForecaster()),
]
)
# putting it all together in a grid search
cv = SlidingWindowSplitter(
initial_window=60, window_length=24, start_with_window=True, step_length=24
)
param_grid = {
"deseasonalizer__passthrough": [True, False],
"scaler__transformer__transformer__with_mean": [True, False],
"scaler__passthrough": [True, False],
"forecaster__strategy": ["drift", "mean", "last"],
}
gscv = ForecastingGridSearchCV(forecaster=pipe, param_grid=param_grid, cv=cv)
[140]:
gscv.fit(y_train)
y_pred = gscv.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[140]:
0.1299046419013891
待办 - 欢迎对本节做出贡献
[141]:
from sktime.forecasting.compose import EnsembleForecaster
[142]:
ses = ExponentialSmoothing(sp=12)
holt = ExponentialSmoothing(trend="add", damped_trend=False, sp=12)
damped = ExponentialSmoothing(trend="add", damped_trend=True, sp=12)
forecaster = EnsembleForecaster(
[
("ses", ses),
("holt", holt),
("damped", damped),
]
)
forecaster.fit(y_train)
y_pred = forecaster.predict(fh)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[142]:
0.16617968035655875
对于模型评估,我们有时希望使用带有滑动窗口的时间交叉验证对测试数据上的多个预测进行评估。为此,我们可以利用 online_forecasting 模块中的预测器,它们使用组合预测器 PredictionWeightedEnsemble 来跟踪每个预测器累积的损失,并根据最“准确”预测器的预测来创建加权预测。
请注意,预测任务已更改:我们进行 35 次预测,因为我们需要第一次预测来帮助更新权重,我们不会预测提前 36 步。
[143]:
from sktime.forecasting.all import mean_squared_error
from sktime.forecasting.online_learning import (
NormalHedgeEnsemble,
OnlineEnsembleForecaster,
)
首先,我们需要初始化一个 PredictionWeightedEnsembler,它将跟踪每个预测器累积的损失,并定义我们希望使用的损失函数。
[144]:
hedge_expert = NormalHedgeEnsemble(n_estimators=3, loss_func=mean_squared_error)
然后,通过定义各个预测器并指定我们使用的 PredictionWeightedEnsembler 来创建预测器。接着通过拟合我们的预测器并使用 update_predict 函数执行更新和预测,我们可以得到:
[145]:
forecaster = OnlineEnsembleForecaster(
[
("ses", ses),
("holt", holt),
("damped", damped),
],
ensemble_algorithm=hedge_expert,
)
forecaster.fit(y=y_train, fh=fh)
y_pred = forecaster.update_predict_single(y_test)
plot_series(y_train, y_test, y_pred, labels=["y_train", "y_test", "y_pred"])
mean_absolute_percentage_error(y_test, y_pred, symmetric=False)
[145]:
0.0978975689038194
4. 扩展指南 - 实现您自己的预测器#
sktime 旨在易于扩展,既可以直接贡献到 sktime 中,也可以在本地/私有环境中通过自定义方法进行扩展。
入门方法
仔细阅读预测扩展模板 - 这是一个带有
todo块的python文件,标记了需要添加更改的位置。(可选)如果您计划对接口进行重大修改:查看基类架构 - 请注意,“普通”扩展(例如,新算法)应该无需此操作即可轻松完成。
将预测扩展模板复制到您自己的仓库的本地文件夹(本地/私有扩展),或者复制到您克隆的
sktime或附属仓库(如果是贡献的扩展)中sktime.forecasting内部的适当位置;重命名文件并相应地更新文件文档字符串。处理“todo”部分。通常,这意味着:更改类的名称,设置标签值,指定超参数,填写
__init__、_fit、_predict以及可选方法(如_update)(详细信息请参阅扩展模板)。只要不覆盖默认的公共接口,您就可以添加私有方法。有关更多详细信息,请参阅扩展模板。手动测试您的估计器:导入您的估计器,并在第 1 节的工作流程中运行它;然后在第 3 节的组合器中使用它。
自动测试您的估计器:在您的估计器上调用
sktime.utils.estimator_checks.check_estimator。您可以在类或对象实例上调用此方法。确保您已在get_test_params方法中按照扩展模板指定了测试参数。
如果直接贡献到 sktime 或其附属包之一,还需要
通过
"authors"和"maintainers"标签,将自己添加为新估计器文件(s)的作者和/或维护者。创建一个拉取请求,其中只包含新的估计器(如果不是单个类,则包含其继承树)以及上述自动化测试。
在拉取请求中,描述该估计器,最好提供其实现策略的出版物或其他技术参考。
在创建拉取请求之前,确保您拥有将代码贡献给宽松许可(BSD-3)开源项目的所有必要权限。
5. 总结#
sktime附带了几种预测算法(或预测器),它们都共享一个通用接口。该接口与scikit-learn接口完全互操作,并为批量和滚动模式下的预测提供了专用接口点。sktime附带了丰富的组合功能,可以轻松构建复杂的管道,并轻松与开源生态系统的其他部分连接,例如scikit-learn和各个算法库。sktime易于扩展,并附带用户友好的工具,方便实现和测试您自己的预测器和组合原则。
有用的资源#
更多详细信息,请参阅我们关于使用 sktime 进行预测的论文,其中我们更详细地讨论了预测 API,并使用它来复现和扩展 M4 研究。
关于预测的良好入门材料,请参阅Hyndman, Rob J., and George Athanasopoulos. Forecasting: principles and practice. OTexts, 2018。
sktime: sktime/sktime