为了帮助评估分层预测系统,我们提供了一个evaluate函数,可以与来自utilsforecast.losses的损失函数结合使用。


来源

evaluate

 evaluate (df:~FrameT, metrics:list[typing.Callable],
           tags:dict[str,numpy.ndarray], models:Optional[list[str]]=None,
           train_df:Optional[~FrameT]=None,
           level:Optional[list[int]]=None, id_col:str='unique_id',
           time_col:str='ds', target_col:str='y',
           agg_fn:Optional[str]='mean', benchmark:Optional[str]=None)

使用不同的指标评估分层预测。

类型默认值详情
dfFrameT要评估的预测结果。
必须包含id_coltime_coltarget_col以及模型的预测结果。
metricslist参数为dfmodelsid_coltarget_col以及可选的train_df的函数。
tagsdict每个键表示层级中的一个级别,其值包含与该级别关联的标签。
models可选None要评估的模型名称。
如果为None,则将使用DataFrame中移除id、time和target后的所有列。
train_df可选None训练集。用于评估mase等指标。
level可选None预测区间级别。用于计算依赖于分位数的损失。
id_colstrunique_id标识每个序列的列。
time_colstrds标识每个时间步的列,其值可以是时间戳或整数。
target_colstry包含目标值的列。
agg_fn可选mean用于计算按id分组的分数以将其汇总为单个数字的统计量。
benchmark可选None如果传递,评估器将按此基准模型的误差进行缩放。
返回值FrameT指标结果,每行表示一个 (id, metric) 组合,每列表示一个模型。
如果agg_fn不是None,则每种指标只有一行。

示例

import pandas as pd

from hierarchicalforecast.core import HierarchicalReconciliation
from hierarchicalforecast.methods import BottomUp, MinTrace
from hierarchicalforecast.utils import aggregate
from hierarchicalforecast.evaluation import evaluate
from statsforecast.core import StatsForecast
from statsforecast.models import AutoETS
from utilsforecast.losses import mase, rmse
from functools import partial

# Load TourismSmall dataset
df = pd.read_csv('https://raw.githubusercontent.com/Nixtla/transfer-learning-time-series/main/datasets/tourism.csv')
df = df.rename({'Trips': 'y', 'Quarter': 'ds'}, axis=1)
df.insert(0, 'Country', 'Australia')
qs = df['ds'].str.replace(r'(\d+) (Q\d)', r'\1-\2', regex=True)
df['ds'] = pd.PeriodIndex(qs, freq='Q').to_timestamp()

# Create hierarchical seires based on geographic levels and purpose
# And Convert quarterly ds string to pd.datetime format
hierarchy_levels = [['Country'],
                    ['Country', 'State'], 
                    ['Country', 'Purpose'], 
                    ['Country', 'State', 'Region'], 
                    ['Country', 'State', 'Purpose'], 
                    ['Country', 'State', 'Region', 'Purpose']]

Y_df, S_df, tags = aggregate(df=df, spec=hierarchy_levels)

# Split train/test sets
Y_test_df  = Y_df.groupby('unique_id').tail(8)
Y_train_df = Y_df.drop(Y_test_df.index)

# Compute base auto-ETS predictions
# Careful identifying correct data freq, this data quarterly 'Q'
fcst = StatsForecast(models=[AutoETS(season_length=4, model='ZZA')], freq='QS', n_jobs=-1)
Y_hat_df = fcst.forecast(df=Y_train_df, h=8, fitted=True)
Y_fitted_df = fcst.forecast_fitted_values()

reconcilers = [
                BottomUp(),
                MinTrace(method='ols'),
                MinTrace(method='mint_shrink'),
               ]
hrec = HierarchicalReconciliation(reconcilers=reconcilers)
Y_rec_df = hrec.reconcile(Y_hat_df=Y_hat_df, 
                          Y_df=Y_fitted_df,
                          S=S_df, tags=tags)

# Evaluate
eval_tags = {}
eval_tags['Total'] = tags['Country']
eval_tags['Purpose'] = tags['Country/Purpose']
eval_tags['State'] = tags['Country/State']
eval_tags['Regions'] = tags['Country/State/Region']
eval_tags['Bottom'] = tags['Country/State/Region/Purpose']

Y_rec_df_with_y = Y_rec_df.merge(Y_test_df, on=['unique_id', 'ds'], how='left')
mase_p = partial(mase, seasonality=4)

evaluation = evaluate(Y_rec_df_with_y, 
         metrics=[mase_p, rmse], 
         tags=eval_tags, 
         train_df=Y_train_df)

numeric_cols = evaluation.select_dtypes(include="number").columns
evaluation[numeric_cols] = evaluation[numeric_cols].map('{:.2f}'.format)

参考文献