Prophet调参

article/2025/9/20 4:05:07

本篇主要讲解实际运用中Prophet调参的主要步骤以及一些本人实际经验。

一 参数理解篇

class Prophet(object):def __init__(self,growth='linear',changepoints=None,n_changepoints=25,changepoint_range=0.8,yearly_seasonality='auto',weekly_seasonality='auto',daily_seasonality='auto',holidays=None,seasonality_mode='additive',seasonality_prior_scale=10.0,holidays_prior_scale=10.0,changepoint_prior_scale=0.05,mcmc_samples=0,interval_width=0.80,uncertainty_samples=1000,stan_backend=None):

1.1 趋势参数

参数描述
growthgrowth是指模型的趋势函数,目前取值有2种,linear和logistic
changepointsChangepoint是指一个特殊的日期,在这个日期,模型的趋势将发生改变。而changepoints是指潜在changepoint的所有日期,如果不指明则模型将自动识别。
n_changepoints最大的Changepoint的数量。如果changepoints不为None,则本参数不生效。
changepoint_range是指changepoint在历史数据中出现的时间范围,与n_changeponits配合使用,changepoint_range决定了changepoint能出现在离当前时间最近的时间点,changepont_range越大,changepoint可以出现的距离现在越近。当指定changepoints时,本参数不生效
changepoint_prior_scale设定自动突变点选择的灵活性,值越大越容易出现changepoint

1.1.1 growth

growth是指模型的趋势函数,目前取值有2种,linear和logistic,分别如图1-1图1-2所示。趋势会在changepoint处出现突变点。

图1-1 linear趋势
图1-2 logistic趋势

细心的同学可能会问,可不可能出现同一个模型既有linear趋势,又有logistic趋势,就像下面这样:

图1-3

在这里福布湿要给大家纠正下这个错觉,请大家记住Prophet的趋势模型要么是linear要么是logistic。而上图之所以像是两种的叠加,是因为prophet的设计师为了让趋势函数可微(连续,就理解成连续吧)做了平滑处理,

上面这货就是论文中做平滑处理的公式。

1.1.2 Changepoints

Changeponits形状如[‘2013-01-01’,’2013-09-01’,’2017-02-5’],是changepoint的列表。

Changepoints是一个非常重要的参数,但用户在决定设置此值时必须要注意,这个参数设置之后模型将不会自动寻找changepoints(同时n_changepoints和changepoint_range均不会生效),这就意味着手动设置的changeponits必须准确且完整,否则福布湿不建议大家设置此项。

1.1.3 n_changeponits、changepoint_range

这2个参数是模型自动识别changepoint时需要的,n_changepoints限制了changepoint的最大数量,changepoint_range限制了changepoint在历史数据中出现的时间范围。例如图1-1中changepoint_range福布湿设置的是0.5,而图1-3中福布湿设置的是0.8,如果福布湿把图1-3中的changepoint_range设置为0.2,那么所有的changpoint均只能出现在2020-01-01至2020-02-01的范围内。

1.2 周期性性参数

参数描述
yearly_seasonality年周期性,True为启用,false为关闭,如果设置为自然数n,则n代表傅里叶级数的项数,项数越多,模型将拟合的越好,但是也越容易过拟合,因此论文中推荐年周期性的项数取10,而周的(weekly_seasonality)取3。 一般来讲当历史数据大于1年时模型默认为True(项数默认为10),否则默认为False
weekly_seasonality周周期性,True为启用,false为关闭,如果设置为自然数n,则n代表傅里叶级数的项数,项数越多,模型将拟合的越好,但是也越容易过拟合,因此论文中推荐取3。 一般来讲当历史数据大于1周时模型默认为True(项数默认为3),否则默认为False
daily_seasonality天周期性,当时间序列为小时级别序列时才会开启。
seasonality_mode季节模型方式,'additive'(加法模型) (默认) 或者 'multiplicative'(乘法模型)
seasonality_prior_scale改变周期性影响因素的强度,值越大,周期性因素在预测值中占比越大

周期性参数设置相对较为固化,除了seasonality_mode和seasonality_prior_scale可能需要手动调整外其余各项一般情况下保持为默认值即可(当然具体问题具体分析,傅里叶项数在某些特殊情况下也可能需要调整)。

傅里叶级数跟泰勒展开式一样,都是用特定的级数形式拟合某个函数,傅里叶级数是专门为周期性函数设计的,也就是说只要某个函数是周期函数就能使用傅里叶级数拟合。有兴趣的同学可以看下知乎上的这个文章:

https://zhuanlan.zhihu.com/p/41455378?from_voters_page=true

seasonality_mode的季节模型类型如果大家不深究按字面意思理解即可。

1.3 节假日参数

参数描述
holidays节假日或特殊日期,商业活动中活动日期是这类日期的典型代表
holiday_prior_scale改变假日模型的强度

1.3.1 holidays

Holidays参数是一个pd.DataFrame:

holidaydsupper_windowlower_window
元旦2019/1/11-1
元旦2018/1/11-1

holiday是特殊日期的时间,ds是时间(pd.Timestamp类型),upper_window和lower_window分别指特殊日期的影响上下限。

在Prophet中,认为holiday服从正态分布,正态分布的轴为ds。因此,prophet在预测节假日时会以正态分布作为来估计预测值,但这个过程只是一个先验估计的过程,如果模型后面发现这个holiday期间内不服从正态分布,那么模型将生硬的拟合该节假日。如图1-4中所示,大家可以自行体会。

图1-4

holidays这个参数非常重要,对整个模型的影响极大,因此大家在构建这个参数时一定要给予相当的重视。

holidays在模型中是一个广义的概念,不仅指节假日,也指活动日期,特殊事件日期等,因此大家在设置holidays时一定要确保完整,同时对于upper_window和lower_window的设置也应符合实际情况。

值得注意的是holidays的数量应尽量少,过多的holidays会对模型的过拟合现象加重,如果holidays的数量超过了整体数据的30%,工程师就应该考虑是否去掉一些影响较小的节假日。

1.4 其他参数

参数描述
mcmc_samples概率估计方式。如果为0将会采用最大后验概率估计(MAP),如果为n(n>0)将会以n个马尔科夫采样样本做全贝叶斯推断。 估计有同学有疑问,这些个概率估计的东西跟本模型有毛关系?大家仔细看下图1-4中的蓝色曲线和淡蓝色区域,这其实就是预测结果,而采样估计就是用来给出淡蓝色区域的(uncertainty intervals),大家可以理解为置信区间或者是预测结果的上下限(虽然外国佬叫它‘不确定区间’)。 当mcmc_samples=0的时候,只有趋势因素会存在这种估计,当mcmc_samples>0时,周期性因素才会存在这种估计。
interval_widthuncertainty intervals 的宽度,是一个浮点数,越大允许的uncertainty intervals范围越大
uncertainty_samples用来估计uncertainty intervals的采样次数,如果设置为0或者False,就不会进行uncertainty intervals的估计,从而加快模型的训练速度。
stan_backendCMDSTANPY或者PYSTAN。一般PYSTAN在linux上使用,cmdstanpy在微软操作系统上使用。提示下在微软操作系统上使用的同学,最好不要开启马尔科夫采样(就是不要把mcmc_samples设成大于0),因为微软操作系统上马尔科夫采样非常慢。

二 参数调优实战

目前实际生产中,时序模型的训练往往是数量惊人,因此如果依靠以往的指标和经验调参以不大可行,所以只能采用机器寻参的方式。福布湿在这里给大家介绍下常用的网格寻参。

在调参之前,最重要的是要确定好模型的评价指标。Prophet中内置的评价指标有传统的mse、rmse、mae、mape、coverage。但这些不一定满足在座各位的胃口,比如福布湿在部分模型中就使用了相对误差的0.8分位数作为评价指标。

废话不多说,直接上代码。

class ProphetTrain(ABC):def __init__(self, name=None):self.name = nameself.data: pd.DataFrame = Noneself.params = {'holidays': holidays}self.mape = np.infself.model = Noneself.grid_search_params_path = Noneself.predict_freq_num = 7self.freq = 'd'
    @abstractmethoddef _load_data(self):"""加载训练及测试数据:param rule: DataFrame.resample 中的rule:return: 训练及测试数据集,类型是pd.DataFrame"""pass
    @propertydef data_size(self):if self.data is None:self.data = self._load_data()return self.data.shape[0] if self.data is not None else 0def _cv_run(self):if self.data_size < 14:raise Exception("数据量不足,请保证数据航速大于14条")self.model = Prophet(**self.params)self.model.fit(self.data)cv_result = cross_validation(self.model, f'{self.predict_freq_num}{self.freq}',f'{self.predict_freq_num}{self.freq}')return performance_metrics(cv_result, metrics=['mape'])['mape'][0]def run(self, show: int = 0, retrain=False):"""根据当前参数生成模型:param retrain: 是否根据当前参数重新生成模型:param show:0:  不保存图片及预测结果 也 不展示图片1: 展示图片2: 保存图片及预测结果3: 保存图片及预测结果 也 展示图片:return:"""if self.data_size < 14:raise Exception("数据量不足,请保证数据航速大于14条")if retrain or self.model is None:self.model = Prophet(**self.params)self.model.fit(self.data)future = self.model.make_future_dataframe(freq=self.freq,periods=self.predict_freq_num)  # 建立数据预测框架,数据粒度为天,预测步长为一年forecast = self.model.predict(future)if show & 0b01:self.model.plot(forecast).show()  # 绘制预测效果图self.model.plot_components(forecast).show()  # 绘制成分趋势图if show & 0b10:y = forecast[['ds', 'yhat_lower', 'yhat_upper', 'yhat']].iloc[-self.predict_freq_num:]y.to_csv(f'csv/{self.name}.csv', index=False)self.model.plot(forecast).savefig(f"img/{self.name}-scatter.png")  # 绘制预测效果图self.model.plot_components(forecast).savefig(f"img/{self.name}-trend.png")  # 绘制成分趋势图mape_score = np.abs(1 - forecast['yhat'].iloc[:self.data.shape[0]] / self.data['y'].values)return np.quantile(mape_score, 0.8)
    @propertydef get_predict_df(self):future = self.model.make_future_dataframe(freq=self.freq,periods=self.predict_freq_num)  # 建立数据预测框架,数据粒度为天,预测步长为一年forecast = self.model.predict(future)return forecastdef grid_search(self, use_cv=True, save_result=True):"""结合cv进行网格寻参,cv方式网格寻参很慢,一般建议先使用非网格方式,待参数调整完毕再使用cv验证。:param save_result::return:"""changepoint_range = [i / 10 for i in range(3, 10)]seasonality_mode = ['additive', 'multiplicative']seasonality_prior_scale = [0.05, 0.1, 0.5, 1, 5, 10, 15]holidays_prior_scale = [0.05, 0.1, 0.5, 1, 5, 10, 15]for sm in seasonality_mode:for cp in changepoint_range:for sp in seasonality_prior_scale:for hp in holidays_prior_scale:params = {"seasonality_mode": sm,"changepoint_range": cp,"seasonality_prior_scale": sp,"holidays_prior_scale": hp,"holidays": holidays}score = self._cv_run() if use_cv else self.run()if self.mape > score:self.mape = scoreself.params = paramsif save_result:future = self.model.make_future_dataframe(freq=self.freq,periods=self.predict_freq_num)  forecast = self.model.predict(future)forecast[['ds', 'yhat_lower', 'yhat_upper', 'yhat']].iloc[-self.predict_freq_num:].to_csv(f'csv/{self.name}.csv', index=False)self.model.plot(forecast).savefig(f"img/{self.name}-scatter.png")  # 绘制预测效果图self.model.plot_components(forecast).savefig(f"img/{self.name}-trend.png")  # 绘制成分趋势图self.save_model()print(f'score:{self.mape}\nparams:{self.params}')return selfdef save_model(self):with open(f'model/{self.name}.pkl', 'wb') as fp:pickle.dump(self, fp)
    @staticmethoddef load_model(name):with open(f'model/{name}.pkl', 'rb') as fp:return pickle.load(fp)

在这里主要给大家介绍2点:

  1. 网格寻参很耗CPU,对于CPU性能不好的同学福布湿只能给你一个大大的拥抱。(当然如果使用2分法一组组参数调,麻烦是麻烦了点,但是速度肯定快不少)。

  2. 网格寻参的参数可以是所有的参数,不仅仅是福布湿给出的这几个

changepoint_range = [i / 10 for i in range(3, 10)]
seasonality_mode = ['additive', 'multiplicative']
seasonality_prior_scale = [0.05, 0.1, 0.5, 1, 5, 10, 15]
holidays_prior_scale = [0.05, 0.1, 0.5, 1, 5, 10, 15]

而这些参数的取值范围则需要同学们根据每个参数固有的取值范围和时间序列的特点自己研究决定。

  1. Prophet自带的交叉验证(cross_validation)函数

def cross_validation(model, horizon, period=None, initial=None):

model: model是已经训练的Prophet模型

horizon: horizon是每次预测所使用的数据的时间长度,比如‘30d’(30天)

period:period是触发预测动作的时间周期。如果设置为‘7d’,01-07、01-14、01-21等等,而这些预测的数据为前面定义的horizon。这个值的默认值为horizon*0.5

Initial:整个交叉验证的数据范围,结束点是昨天的点,开始点是(昨天-initial),initial的默认值是3*horizon。当然同学们也可根据实际情况手动设置,比如“110d”。

语言总是苍白的,那么福布湿就直接上图了。

图1-5

图中的horizon为‘30d’,其他的均为默认值(period=‘15d’,initial=‘90d’)。

三 结尾

任何一种算法不可能适合所有情况,所有大家要做的是理解算法原理,针对实际情况优化算法。比如福布湿在研究双十一这个节假日的时候发现实际的分布并不是对称的,而正态分布是一个对称的分布,明显不符合实际情况,因此福布湿将这个先验分布改为了F分布,就这一个小小的改动就让模型的准确率上升了大约5%左右。因此如果想训练出一个好的模型,数据和调参很重要,但更重要的对算法原理的充分理解并根据实际情况改进算法,从而让模型效果达到一个新的台阶。

参考文献:

【1】Prophet官方文档:https://facebook.github.io/prophet/

【2】Prophet论文:https://peerj.com/preprints/3190/

【3】Prophet-github:https://github.com/facebook/prophet


http://chatgpt.dhexx.cn/article/XSasqgOF.shtml

相关文章

Python实现Prophet时间序列数据建模与异常值检测(Prophet算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 Prophet由facebook开源的基于python和R语言的数据预测工具&#xff0c;基于时间和变量值结合时间序列分…

结合 Prophet 的原理理解 Prophet 的使用

结合 Prophet 的原理理解 Prophet 的使用 前言 本文也是时序领域工作学习过程中的一些学习笔记&#xff0c;将会结合 Prophet 的原理&#xff0c;讲一讲如何成为一个合格的 Prophet 调包侠 使用者。如果有任何理解不到位的地方&#xff0c;请多多指正。 Why Prophet? Prop…

大白话Prophet模型以及简单的应用(一)

Prophet 是基于加法模型预测时间序列数据。适合于具有季节性影响的时间序列和具有多个季节的历史数据。Prophet对数据中的异常值和缺失值以及趋势的强烈变化有着较好的鲁棒性&#xff08;耐操性&#xff09;&#xff0c;所以通常情况下都不需要对数据进行处理。 优点&#xff1…

Prophet算法

Prophet简介 Prophet是FaceBook公司在2017年开源的一款时间序列建模工具。Prophet的方法是将时间序列看成是关于t的一个函数&#xff0c;用你和函数曲线的方法进行预测&#xff0c;所以这和传统的时间序列模型有本质上的区别&#xff0c;他更倾向于机器学习的建模方式。 Prop…

时间序列模型Prophet使用详细讲解

之前我们已经讲过了如何在Windows系统下安装Python版本的Prophet。详细见这里。 接下来的几个部分&#xff0c;我们说下如何使用Prophet&#xff0c;以此来体验下Prophet的丰富内容。内容会比较多&#xff0c;主要翻译自官方文档。教程中使用的数据集可在 Prophet 的 github 主…

Prophet拟合模型入门学习

先展示效果&#xff1a; Facebook 时间序列预测算法 Prophet 的研究 Prophet 简介 Facebook 去年开源了一个时间序列预测的算法&#xff0c;叫做 fbprophet&#xff0c;它的官方网址与基本介绍来自于以下几个网站&#xff1a; Github&#xff1a;https://github.com/facebo…

时间序列预测——Prophet模型

文章链接&#xff1a; 时间序列预测——ARIMA模型https://blog.csdn.net/beiye_/article/details/123317316?spm1001.2014.3001.5502 1、Propht模型概述 Prophet模型是Facebook于2017年发布开源的时间序列预测框架。Prophet适用于各种具有潜在特殊特征的预测问题包括广泛的业…

Prophet 时间序列预测框架入门实践笔记

1. Prophet时间序列预测框架概述 Prophet是Facebook开源的一种时间序列预测框架&#xff0c;旨在使时间序列分析更加容易和快速。Prophet可以处理具有多个季节性和突发事件的时间序列数据&#xff0c;并且在数据缺失或异常情况下仍然能够进行良好的预测。Prophet采用了一种基于…

Prophet的原理知识

目录 1、Prophet 简介 2、Prophet 适用场景 3、Prophet 算法的输入输出 4、Prophet 算法原理 5、Prophet 使用时可设置的参数 6、Prophet 学习资料参考 7、Prophet 模型应用 7.0 背景描述7.1 导入数据7.2 拟合模型7.3 预测&#xff08;使用默认参数&#xff09;7.4 趋势…

Prophet:一种大规模时间序列预测模型

前言 Prophet是由facebook开发的开源时间序列预测程序&#xff0c;擅长处理具有季节性特征大规模商业时间序列数据。本文主要介绍了Prophet模型的设计原理&#xff0c;并与经典的时间序列模型ARIMA进行了对比。 1. Prophet模型原理 Prophet模型把一个时间序列看做由3种主要成分…

Prophet模型的简介以及案例分析

目录 前言一、Prophet安装以及简介二、适用场景三、算法的输入输出四、算法原理五、使用时可以设置的参数六、学习资料参考七、模型应用7-1、股票收盘价格预测7-1-1、导入相关库7-1-2、读取数据7-1-3、数据预处理以及进行训练集和测试集的划分。7-1-4、实例化Prophet对象&#…

时序预测工具库(Prophet)介绍+代码

时序预测工具库&#xff08;Prophet&#xff09; 一、Prophet 简介二、Prophet 适用场景三、Prophet 算法的输入输出四、Prophet 算法原理五、与机器学习算法的对比六、代码6.1 依赖安装6.2 预测demo6.3 效果图 七、参考资料八、官方链接&#xff1a;九、案例链接&#xff1a; …

图的顺序存储及其深度优先遍历和广度优先遍历

图的基本概念 在线性表中&#xff0c;数据元素之间是被串起来的&#xff0c;仅有线性关系&#xff0c;每个数据元素只有一个直接前驱和一个直接后继。在树形结构中&#xff0c;数据元素之间有着明显的层次关系&#xff0c;并且每一层上的数据元素可能和下一层中多个元素相关&am…

算法模板-深度优先遍历

简介 深度优先遍历&#xff0c;顾名思义对于树或者图中的某个节点&#xff0c;尽可能往一个方向深入搜索下去。具体而言&#xff0c;从某个节点v出发开始进行搜索&#xff0c;不断搜索直到该节点的所有边都被遍历完。对于很多树、图和矩阵地搜索问题&#xff0c;深度优先遍历是…

图的深度优先遍历java代码详解

代码是根据矩阵来实现深度优先遍历的 邻接结点就是按照vertex中的顺序来一个一个来找的 if(edges[i][j]>0&&!isVisited[j]) { return j; } 就很好的说明了 如果没找到就return -1 回到dfs&#xff08;i&#xff09;这一层 再retur…

图(深度优先遍历、广度优先遍历)

文章目录 一、图的概述1.1 什么是图1.2 图对比线性表和树1.3 图的常见概念 二、图的存储方式2.1 邻接矩阵2.2 邻接表 三、图的遍历3.1 图的深度优先遍历3.1.1 什么是深度优先遍历3.1.2 深度优先遍历的步骤3.1.3 深度优先遍历代码实现 3.2 图的广度优先遍历3.2.1 什么是广度优先…

树与图的深度优先遍历

目录 一、概念 二、操作说明 1.树与图的深度优先遍历 2.树的DFS序 3.树的深度 4.树的重心 5.图的连通块划分 三、例题实践 1.树的重心例题实战 a.题目描述 b.解题思路 c.代码实现 一、概念 树与图的深度优先遍历&#xff1a;深度优先遍历&#xff0c;就是在每一个…

算法总结-深度优先遍历和广度优先遍历

深度优先遍历(Depth First Search&#xff0c;简称DFS) 与广度优先遍历(Breath First Search&#xff0c;简称BFS)是图论中两种非常重要的算法&#xff0c;生产上广泛用于拓扑排序&#xff0c;寻路(走迷宫)&#xff0c;搜索引擎&#xff0c;爬虫等。 一、深度优先遍历 深度优先…

图的两种遍历:深度优先遍历+广度优先遍历

一、深度优先遍历 1、简介 深度优先遍历是指按照深度方向搜索&#xff0c;它类似于树的先根遍历&#xff0c;是树的先根遍历的推广。 基本思想&#xff08;通俗&#xff09; 选一条路走到 底&#xff0c;直到 走不通&#xff0c;就 原路返回看看 是否还有路可走&#xff0c;如…

C++实现图的深度优先遍历和广度优先遍历

图的深度和广度优先遍历 图的深度优先遍历1、算法思想2、邻接矩阵构造图3、邻接表构造图 图的广度优先遍历1、算法思想2、邻接矩阵构造图 参考 图的深度优先遍历 1、算法思想 &#xff08;1&#xff09;从图中的某个初始点 v 出发&#xff0c;首先访问初始点 v.&#xff08;…