TimeGPT 需要没有缺失值的时间序列数据。可以有多个时间序列,它们开始和结束日期不同,但关键是每个时间序列在其给定时间范围内必须包含不间断的数据。

在本教程中,我们将向您展示如何在 TimeGPT 中处理缺失值。

大纲

  1. 加载数据

  2. TimeGPT 入门

  3. 可视化数据

  4. 填充缺失值

  5. 使用 TimeGPT 进行预测

  6. 重要注意事项

  7. 参考资料

本文基于 skforecast 的 缺失值时间序列预测 教程。

加载数据

我们首先使用 pandas 加载数据。该数据集表示一个城市中每日自行车租赁数量。列名是西班牙语,因此我们将它们重命名,用 ds 表示日期,用 y 表示自行车租赁数量。

import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/JoaquinAmatRodrigo/Estadistica-machine-learning-python/master/data/usuarios_diarios_bicimad.csv')
df = df[['fecha', 'Usos bicis total día']] # select date and target variable 
df.rename(columns={'fecha': 'ds', 'Usos bicis total día': 'y'}, inplace=True) 
df.head()
dsy
02014-06-2399
12014-06-2472
22014-06-25119
32014-06-26135
42014-06-27149

为了方便,我们将日期转换为时间戳并为该系列分配一个唯一 ID。尽管在此示例中我们只有一个系列,但在处理多个系列时,需要为每个系列分配一个唯一 ID。

df['ds'] = pd.to_datetime(df['ds']) 
df['unique_id'] = 'id1'
df = df[['unique_id', 'ds', 'y']]

现在我们将数据分为训练集和测试集。我们将最后 93 天用作测试集。

train_df = df[:-93] 
test_df = df[-93:]

现在我们将在训练集中引入一些缺失值,以演示如何处理它们。这将按照 skforecast 教程中的方法进行。

mask = ~((train_df['ds'] >= '2020-09-01') & (train_df['ds'] <= '2020-10-10')) &  ~((train_df['ds'] >= '2020-11-08') & (train_df['ds'] <= '2020-12-15'))

train_df_gaps = train_df[mask]

TimeGPT 入门

在继续之前,我们将实例化 NixtlaClient 类,该类提供了访问 TimeGPT 所有方法的接口。为此,您需要一个 Nixtla API 密钥。

from nixtla import NixtlaClient
nixtla_client = NixtlaClient(
    # defaults to os.environ.get("NIXTLA_API_KEY")
    api_key = 'my_api_key_provided_by_nixtla'
)

👍 使用 Azure AI 端点

要使用 Azure AI 端点,请设置 base_url 参数

nixtla_client = NixtlaClient(base_url="you azure ai endpoint", api_key="your api_key")

要了解有关如何设置 API 密钥的更多信息,请参阅 设置 API 密钥 教程。

可视化数据

我们可以使用 NixtlaClient 类中的 plot 方法可视化数据。此方法有一个 engine 参数,允许您在不同的绘图库之间进行选择。默认是 matplotlib,但您也可以使用 plotly 进行交互式绘图。

nixtla_client.plot(train_df_gaps)

请注意,数据中有两个缺失区间:2020 年 9 月 1 日至 2020 年 10 月 10 日,以及 2020 年 11 月 8 日至 2020 年 12 月 15 日。为了更好地可视化这些缺失,您可以使用 plot 方法的 max_insample_length 参数,或者直接放大图表。

nixtla_client.plot(train_df_gaps, max_insample_length=800)

此外,请注意 2020 年 3 月 16 日至 2020 年 4 月 21 日期间的数据显示租赁数量为零。这些不是缺失值,而是城市因 COVID-19 封锁而导致的实际零值。

填充缺失值

在使用 TimeGPT 之前,我们需要确保

  1. 数据中存在从开始日期到结束日期的所有时间戳。

  2. 目标列不包含缺失值。

为了解决第一个问题,我们将使用 utilsforecast 中的 fill_gaps 函数,这是一个来自 Nixtla 的 Python 包,它提供了时间序列预测所需的基本实用工具,例如数据预处理、绘图和评估函数。

fill_gaps 函数将填充数据中的缺失日期。为此,它需要以下参数

  • df:包含时间序列数据的 DataFrame。

  • freq (str 或 int):数据的频率。

from utilsforecast.preprocessing import fill_gaps
print('Number of rows before filling gaps:', len(train_df_gaps))
train_df_complete = fill_gaps(train_df_gaps, freq='D')
print('Number of rows after filling gaps:', len(train_df_complete))
Number of rows before filling gaps: 2851
Number of rows after filling gaps: 2929

注意

在本教程中,数据仅包含一个时间序列。但是,TimeGPT 支持向模型传递多个序列。在这种情况下,任何时间序列从其各自最早的时间戳到最晚的时间戳都不能有缺失值。如果这些单个时间序列有缺失值,用户必须决定如何填充这些单个时间序列的缺失。 fill_gaps 函数提供了一些额外的参数来帮助完成此操作(有关完整详细信息,请参阅文档),即 startend


来源

fill_gaps

 fill_gaps (df:~DFType, freq:Union[str,int],
            start:Union[str,int,datetime.date,datetime.datetime]='per_seri
            e',
            end:Union[str,int,datetime.date,datetime.datetime]='global',
            id_col:str='unique_id', time_col:str='ds')

强制设置 DataFrame 的开始和结束日期时间。

类型默认值详情
dfDFType输入数据
freqUnion序列的频率
startUnionper_serie序列的初始时间戳。
* ‘per_serie’ 使用每个序列的第一个时间戳
* ‘global’ 使用数据中看到的第一个时间戳
* 也可以是特定的时间戳或整数,例如 ‘2000-01-01’、2000 或 datetime(2000, 1, 1)
endUnionglobal序列的初始时间戳。
* ‘per_serie’ 使用每个序列的最后一个时间戳
* ‘global’ 使用数据中看到的最后一个时间戳
* 也可以是特定的时间戳或整数,例如 ‘2000-01-01’、2000 或 datetime(2000, 1, 1)
id_colstrunique_id标识每个序列的列。
time_colstrds标识每个时间戳的列。
返回值DFType填充了缺失值的 DataFrame。

现在我们需要决定如何填充目标列中的缺失值。在本教程中,我们将使用插值法,但在选择填充策略时考虑数据的具体上下文非常重要。例如,如果您处理的是每日零售数据,缺失值很可能表示当天没有销售,您可以将其填充为零。相反,如果您处理的是每小时温度数据,缺失值可能意味着传感器未正常工作,您可能更倾向于使用插值法填充缺失值。

train_df_complete['y'] = train_df_complete['y'].interpolate(method='linear', limit_direction='both')

train_df_complete.isna().sum() # check if there are any missing values
unique_id    0
ds           0
y            0
dtype: int64

使用 TimeGPT 进行预测

现在我们可以使用 NixtlaClient 类中的 forecast 方法了。此方法需要以下参数

  • df:包含时间序列数据的 DataFrame

  • h:(int) 预测范围。在此示例中,为 93 天。

  • model (str):要使用的模型。默认是 timegpt-1,但由于预测范围超过了数据的频率(每日),我们将使用 timegpt-1-long-horizon。要了解更多信息,请参阅 长期预测 教程。

fcst = nixtla_client.forecast(train_df_complete, h=len(test_df), model='timegpt-1-long-horizon')
INFO:nixtla.nixtla_client:Validating inputs...
INFO:nixtla.nixtla_client:Inferred freq: D
INFO:nixtla.nixtla_client:Preprocessing dataframes...
INFO:nixtla.nixtla_client:Querying model metadata...
WARNING:nixtla.nixtla_client:The specified horizon "h" exceeds the model horizon, this may lead to less accurate forecasts. Please consider using a smaller horizon.
INFO:nixtla.nixtla_client:Restricting input...
INFO:nixtla.nixtla_client:Calling Forecast Endpoint...

📘 Azure AI 中可用的模型

如果您使用的是 Azure AI 端点,请务必设置 model="azureai"

nixtla_client.forecast(..., model="azureai")

对于公共 API,我们支持两种模型:timegpt-1timegpt-1-long-horizon

默认使用 timegpt-1。请参阅 本教程,了解如何以及何时使用 timegpt-1-long-horizon

我们可以使用 plot 方法可视化 TimeGPT 预测结果和测试集。

nixtla_client.plot(test_df, fcst)

接下来,我们将使用 utilsforecast 中的 evaluate 函数计算 TimeGPT 预测结果的平均绝对误差 (MAE)。在继续之前,我们需要将预测结果中的日期转换为时间戳,以便将其与测试集合并。

evaluate 函数需要以下参数

  • df:包含预测结果和实际值(在 y 列中)的 DataFrame。

  • metrics (list):要计算的指标。

from utilsforecast.evaluation import evaluate 
from utilsforecast.losses import mae
fcst['ds'] = pd.to_datetime(fcst['ds'])

result = test_df.merge(fcst, on=['ds', 'unique_id'], how='left')
result.head()
unique_iddsyTimeGPT
0id12022-06-301346813357.357
1id12022-07-011293212390.052
2id12022-07-0299189778.649
3id12022-07-0389678846.637
4id12022-07-041286911589.071
evaluate(result, metrics=[mae])
unique_idmetricTimeGPT
0id1mae1824.693059

重要注意事项

本教程的关键要点是,TimeGPT 需要没有缺失值的时间序列数据。这意味着

  1. 考虑到数据的频率,时间戳必须是连续的,开始日期和结束日期之间没有间隙。

  2. 数据不得包含缺失值 (NaN)。

我们还展示了 utilsforecast 提供了一个方便的函数来填充缺失日期,并且您需要决定如何处理缺失值。这个决定取决于您数据的具体上下文,因此在选择填充策略时要仔细考虑,并选择您认为最能反映实际情况的策略。

最后,我们还演示了 utilsforecast 提供了一个函数,可以使用常用的准确性指标评估 TimeGPT 的预测结果。

参考资料