如何通过 Prophet 交叉验证获得更好的预测结果?

Posted

技术标签:

【中文标题】如何通过 Prophet 交叉验证获得更好的预测结果?【英文标题】:How can I get better forecasting results with Prophet cross validation? 【发布时间】:2020-05-07 15:31:38 【问题描述】:

我有 10 年的每日需求数据,趋势是积极的。 https://gofile.io/?c=PS3YCO

在一年的最后三个月中,1-2 日总是会出现需求冲击。和 15-16。本月(促销)。

我尝试使用以下方法对其进行预测:

future = m.make_future_dataframe(periods=365)

预测 = m.predict(未来)

但结果不是我所期望的。我能得到的最好的 MSE 是 6681。但是当我尝试交叉验证时,结果几乎与 6690 相同。

我可以通过设置更改什么以获得更好的结果吗? 获取更大的数据集(假设是 50 年)是否会有所帮助? 总的来说:我是否理解正确,您要么使用“forecast = m.predict(future)”,要么使用交叉验证选项?

另外:当我使用“from fbprophet.diagnostics import performance_metrics”来计算 MSE 时,它并没有给我测试数据的值,而是更长的时间。我如何才能计算去年的 MSE?

非常感谢您的帮助:)

import numpy as np
from fbprophet import Prophet
import matplotlib.pyplot as plt
from fbprophet.diagnostics import cross_validation

df = pd.read_excel('Dataset2.3_kurz.xls')   

promotions = pd.DataFrame( 
 'holiday': 'winter_promotion',
    'ds': pd.to_datetime(['2009-10-1','2009-10-2','2009-10-15','2009-10-16',
                          '2009-11-1','2009-11-2','2009-11-15','2009-11-16',
                          '2009-12-1','2009-12-2','2009-12-15','2009-12-16',
                          '2010-10-1','2010-10-2','2010-10-15','2010-10-16',
                          '2010-11-1','2010-11-2','2010-11-15','2010-11-16',
                          '2010-12-1','2010-12-2','2010-12-15','2010-12-16',
                          '2011-10-1','2011-10-2','2011-10-15','2011-10-16',
                          '2011-11-1','2011-11-2','2011-11-15','2011-11-16',
                          '2011-12-1','2011-12-2','2011-12-15','2011-12-16',
                          '2012-10-1','2012-10-2','2012-10-15','2012-10-16',
                          '2012-11-1','2012-11-2','2012-11-15','2012-11-16',
                          '2012-12-1','2012-12-2','2012-12-15','2012-12-16',
                          '2013-10-1','2013-10-2','2013-10-15','2013-10-16',
                          '2013-11-1','2013-11-2','2013-11-15','2013-11-16',
                          '2013-12-1','2013-12-2','2013-12-15','2013-12-16',
                          '2014-10-1','2014-10-2','2014-10-15','2014-10-16',
                          '2014-11-1','2014-11-2','2014-11-15','2014-11-16',
                          '2014-12-1','2014-12-2','2014-12-15','2014-12-16',
                          '2015-10-1','2015-10-2','2015-10-15','2015-10-16',
                          '2015-11-1','2015-11-2','2015-11-15','2015-11-16',
                          '2015-12-1','2015-12-2','2015-12-15','2015-12-16',
                          '2016-10-1','2016-10-2','2016-10-15','2016-10-16',
                          '2016-11-1','2016-11-2','2016-11-15','2016-11-16',
                          '2016-12-1','2016-12-2','2016-12-15','2016-12-16',
                          '2017-10-1','2017-10-2','2017-10-15','2017-10-16',
                          '2017-11-1','2017-11-2','2017-11-15','2017-11-16',
                          '2017-12-1','2017-12-2','2017-12-15','2017-12-16',
                          '2018-10-1','2018-10-2','2018-10-15','2018-10-16',
                          '2018-11-1','2018-11-2','2018-11-15','2018-11-16',
                          '2018-12-1','2018-12-2','2018-12-15','2018-12-16',
                          '2019-10-1','2019-10-2','2019-10-15','2019-10-16',
                          '2019-11-1','2019-11-2','2019-11-15','2019-11-16',
                          '2019-12-1','2019-12-2','2019-12-15','2019-12-16']),
    'lower_window': 0, 
    'upper_window': 0, 
)

#model
m = Prophet( growth='linear',
           holidays=promotions,
           seasonality_mode='multiplicative',

           holidays_prior_scale=10,  
           seasonality_prior_scale=10,            
            yearly_seasonality=True,
           )

m.fit(df)  

df_cv = cross_validation(m, initial='732 days', period='365 days', horizon = '366 days')

from fbprophet.diagnostics import performance_metrics
df_p = performance_metrics(df_cv)
df_p = df_p[-365:]
df_p.tail()

【问题讨论】:

我认为您可以将您提到的特定日期(促销)设置为假期(参见先知指南上的Modeling Holidays and Special Events。第二点,拥有更多数据通常可以提供更好的概括。 @LuisBlanche 这就是我在模型中使用 holiday=promotions 所做的。效果只是不够好。当您绘制数据时,您可以更好地看到它 【参考方案1】:

尝试网格搜索并调整超参数。使用 changepoint_prior_scale 参数也可能会有所帮助。这只是个人意见,但将年度季节性设置为 False 并使用新的傅立叶顺序和优先级在外部添加它也可能会有所帮助。关于 cross_validation,请查看this link 以获得更好的理解。

【讨论】:

以上是关于如何通过 Prophet 交叉验证获得更好的预测结果?的主要内容,如果未能解决你的问题,请参考以下文章

第十届“泰迪杯”数据挖掘挑战赛B题:电力系统负荷预测分析 ARIMAAutoARIMALSTMProphet多元Prophet 实现

第十届“泰迪杯”数据挖掘挑战赛B题:电力系统负荷预测分析 ARIMAAutoARIMALSTMProphet多元Prophet 实现

使用交叉验证时如何使用测试数据集进行预测?

手把手教你用Prophet快速进行时间序列预测(附Prophet和R代码)

如何预测股票分析--先知(Prophet)

Prophet 时间序列预测算法