如何在Facebook Prophet中获取周频率的performance_metrics结果
问题:Prophet交叉验证后
performance_metrics返回日频率结果,如何获取周频率? 我出于学习目的,使用prophet库处理经典航空乘客数据集(月度频率)。相关讨论指出该数据集无法按Prophet标准频率执行交叉验证,于是我调用cross_validation()时传入周频率参数:
model = Prophet() model.fit(df) future_dates = model.make_future_dataframe(periods=36, freq='MS') df_cv = cross_validation(model, initial='300 W', period='5 W', horizon = '52 W') df_cv.head()
但调用performance_metrics函数后,返回的horizon列却是日频率:
df_p = performance_metrics(df_cv) df_p.head()
我查阅文档和函数说明后仍未解决,请问如何获取周频率的performance_metrics结果?
解决方案
1. 先将交叉验证结果聚合为周频率
performance_metrics的输出粒度依赖于输入df_cv的时间粒度,由于Prophet在处理非标准频率时会生成日级别的预测记录,因此需要先将df_cv按周聚合,再传入函数计算指标。
示例代码:
import pandas as pd # 按周分组,以周日作为周结束节点,聚合相关字段 df_cv_weekly = df_cv.groupby(pd.Grouper(key='ds', freq='W')).agg({ 'y': 'mean', # 原始值取周均值 'yhat': 'mean', # 预测值取周均值 'yhat_lower': 'mean', # 预测下限取周均值 'yhat_upper': 'mean', # 预测上限取周均值 'cutoff': 'last' # 每组保留最后一个划分时间点 }).reset_index() # 计算周级别的horizon:将日期间隔转换为周数 df_cv_weekly['horizon'] = (df_cv_weekly['ds'] - df_cv_weekly['cutoff']).dt.days // 7 # 传入performance_metrics获取周频率结果 df_p_weekly = performance_metrics(df_cv_weekly) df_p_weekly.head()
2. 手动按周分组计算性能指标
如果需要更灵活的指标计算逻辑,可以直接对df_cv按周级horizon分组,手动统计各项指标:
import numpy as np # 将原始日级horizon转换为周数 df_cv['horizon_weeks'] = df_cv['horizon'].dt.days // 7 # 按周数分组计算性能指标 df_p_weekly = df_cv.groupby('horizon_weeks').agg( mse=('y', lambda x: np.mean((x - df_cv.loc[x.index, 'yhat'])**2)), mae=('y', lambda x: np.mean(np.abs(x - df_cv.loc[x.index, 'yhat']))), mape=('y', lambda x: np.mean(np.abs((x - df_cv.loc[x.index, 'yhat'])/x)) * 100) ).reset_index()
注意事项
- 原始数据集为月度频率,周级预测属于对月度数据的拆分,选择均值作为聚合统计量是合理的(代表每周平均乘客数量);若原始数据为月度总量,也可根据需求选择求和等其他统计量。
- 聚合后
horizon列会以整数形式表示周数(如1代表第1周,52代表第52周),此时performance_metrics返回的结果即为周频率粒度。
内容的提问来源于stack exchange,提问作者Andrea Ciufo
相关产品推荐
相关产品推荐

