這是官網的quickstart的內容,csv文件也能夠下到,這個入門之後後面調試加入其它參數就很簡單了.css
import pandas as pd import numpy as np from fbprophet import Prophet import matplotlib.pyplot as plt df = pd.read_csv('prophet2.csv') df['y'] = np.log(df['y']) df.head() m = Prophet() m.fit(df); future = m.make_future_dataframe(periods=365) future.tail() forecast = m.predict(future) print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']]) m.plot(forecast) x1 = forecast['ds'] y1 = forecast['yhat'] plt.plot(x1,y1) plt.show()
運行結果以下圖
java
在今年三月prophet剛發佈的時候就簡單用過,但最近纔想起去讀paper……python
首先,prophet是一個工業級應用,而不是說在時間序列預測的模型上有很是大的創新。git
記得今年在參加一次貓眼電影票房預測的內部分享時,旁邊坐了一個外賣的PM。結束時對方問我,有什麼方法能夠預測外賣的訂單量。我當時想了想,諸如Holt-Winters指數平滑、ARIMA、或者deep learning的LSTM,彷佛都不是那麼容易解釋。github
時間序列預測對大部分公司而言都存在必要的需求,好比電商預測GMV,外賣O2O預測成交量波動以便於運力分配,酒店預測間夜量來調整訂價與銷售,等等。但一般而言,時間序列預測對很多公司來講是一個難題。主要緣由除了時間序列預測自己就是玄學(大霧)以外,還要求分析師同時具有深厚的專業領域知識(domain knowledge)和時間序列建模的統計學知識。此外,時間序列模型的調參也是一個比較複雜而繁瑣的工做。bash
prophet就是在這樣的背景下的產物,將一些時間序列建模常見的流程與參數default化,來使不太懂統計的業務分析師也可以針對需求快速創建一個相對可用的模型。app
不少商業行爲是存在必定的時間相依的模式的。做者以Facebook上用戶創造「事件」(events)來舉例:框架
能夠看到用戶創造事件的數量有很明顯的時間序列特徵:多種週期性、趨勢性、節假日效應,以及部分異常值。dom
而後做者用R的forecast包裏的幾種常見的時間序列預測技術(ARIMA, 指數平滑等等)來建模,效果慘不忍睹:函數
圖1是ARIMA,圖2是指數平滑,圖3是snaive,圖4是tbats。
Prophet的本質是一個可加模型,基本形式以下:
其中 是趨勢項, 是週期項, 是節假日項, 是偏差項而且服從正態分佈。
趨勢模型
prophet裏使用了兩種趨勢模型:飽和增加模型(saturating growth model)和分段線性模型(piecewise linear model)。兩種模型都包含了不一樣程度的假設和一些調節光滑度的參數,並經過選擇變化點(changepoints)來預測趨勢變化。具體推導就不寫了,只寫下最終形式:
saturating growth model:
piecewise linear model:
週期模型
prophet用傅里葉級數(Fourier series)來創建週期模型:
對N的調節起到了低通濾波(low-pass filter)的做用。做者說對於年週期與星期週期,N分別選取爲10和3的效果比較好。
節假日與突發事件模型
節假日須要用戶事先指定,每個節假日都包含其先後的若干天。模型形式以下(感受就是一個虛擬變量):
仍是使用上面Facebook的例子,做者給出了Prophet的模型擬合與預測能力:
看起來比前面用R的forecast作的效果好了不少,而且不須要使用者具備很強的統計背景就可以輕鬆進行建模。
同時prophet支持將模型分解爲單獨的各項組成部分,而且實現起來很容易,只須要調用一行代碼prophet_plot_components:
很明顯,Prophet只適用於具備明顯的內在規律(或者說,模式)的商業行爲數據。
雖然官方案例裏一般使用日數據的序列,但對於更短期頻段,好比小時數據,也是支持的。
但對於不具備明顯趨勢性、週期性的時間序列,使用Prophet進行預測就不適合了。好比前面有同窗用Prophet來預測滬深300……先不說有效市場假說(EMH)否認了歷史數據對將來價格擬合的可能性,就算市場存在模式,也不是可以被一個通用模型簡單的線性分解成趨勢和週期的。
我本身最先是基於內部歷史數據,嘗試公司風控的潛在損失作一個簡單預測,但很明顯,沒有任何證據能說明過去的序列特徵(好比風險集中趨勢,外部環境影響,公司層面的合併等等)會在2017年重演。因此充其量就是拿來寫寫週報,以及爲2017年風控預算作一點微小的貢獻……
Prophet是一個比較好用的預測工具,特別是對我這種拿着forecast的ets和auto.arima也懶到自動定階和模型選擇的人來講(逃……
對業務分析師很友好,由於原理很簡單,有R和python的基礎上手也很容易。
一般可以給出一個還不錯的預測結果。好比我就對某些業務線的交易數據跑了下預測,發現大部分都能work,諸如「春節效應」這種中國特點也能抓得比較準。
from:https://blog.csdn.net/sinat_26917383/article/details/57419862
比較讚的功能點:
prophet應該就是我一直在找的,目前看到最好的營銷活動分析的預測工具,是網站分析、廣告活動分析的福音,若是您看到本篇文章內的方法,您在使用中發現什麼心得,還請您儘可能分享出來~
# install.packages('prophet') library(prophet) library(dplyr)
.
history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'), y = sin(1:366/200) + rnorm(366)/10) m <- prophet(history,growth = "linear")
其中,生成數據的時候注意,最好用ds(時間項)、y(必定要numeric)這兩個命名你的變量,本案例是單序列+時間項。數據長這樣:
prophet是生成模型階段,m中有不少參數,有待後來人慢慢研究。
#時間函數 future <- make_future_dataframe(m, periods = 365) tail(future) #預測 forecast <- predict(m, future) tail(forecast[c('ds', 'yhat', 'yhat_lower', 'yhat_upper')]) #直線預測 plot(m, forecast) #趨勢分解 prophet_plot_components(m, forecast)
make_future_dataframe:有趣的時間生成函數,以前的ds數據是2015-1-1到2016-1-1,如今生成了一個2015-1-1到2016-12-30序列,多增長了一年,以備預測。並且能夠靈活的調控是預測天,仍是周,freq參數。
predict,預測那麼ds是時間,yhat是預測值,lower和upper是置信區間。
感覺一下plot:
prophet_plot_components函數是趨勢分解函數,將趨勢分紅了趨勢項、星期、年份,這是默認配置。
.
logitics是啥? 不懂煩請百度。
#數據生成階段 history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'), y = sin(1:366/200) + rnorm(366)/10, cap=sin(1:366/200) + rnorm(366)/10+rep(0.3,366)) #最大增加趨勢,cap設置cap,就是這個規模的頂點,y當時頂點 #模型生成 m <- prophet(history,growth = "logistic") future <- make_future_dataframe(m, periods = 1826) future$cap <- sin(1:2192/200) + rnorm(2192)/10+rep(0.3,2192) #預測階段 fcst <- predict(m, future) plot(m, fcst)
prophet這裏若是是要擬合logitics趨勢,就須要一個cap變量,這個變量是y變量的上限(譬如最大市場規模),由於y若是服從logitics趨勢不給範圍的話,很容易一下預測就到頂點了,因此cap來讓預測變得不那麼「脆弱」…
下面來看一個失敗擬合logitics案例:
.
.
能夠考察節中、節後效應。來看看paper中如何解釋節日效應的(論文地址):
也就是說,節日效應能量函數h(t)由兩部分組成,Z(t)是一個示性函數的集合(indicator function),而參數K服從(0,v)正態分佈。能夠說,將節日當作是一個正態分佈,把活動期間當作波峯,lower_window 以及upper_window 的窗口做爲擴散。
#數據生成:常規數據 history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'), y = sin(1:366/200) + rnorm(366)/10, cap=sin(1:366/200) + rnorm(366)/10+rep(0.3,366)) #數據生成:節假日數據 library(dplyr) playoffs <- data_frame( holiday = 'playoff', ds = as.Date(c('2008-01-13', '2009-01-03', '2010-01-16', '2010-01-24', '2010-02-07', '2011-01-08', '2013-01-12', '2014-01-12', '2014-01-19', '2014-02-02', '2015-01-11', '2016-01-17', '2016-01-24', '2016-02-07')), lower_window = 0, upper_window = 1 ) superbowls <- data_frame( holiday = 'superbowl', ds = as.Date(c('2010-02-07', '2014-02-02', '2016-02-07')), lower_window = 0, upper_window = 1 ) holidays <- bind_rows(playoffs, superbowls) #預測 m <- prophet(history, holidays = holidays) forecast <- predict(m, future) #影響效應 forecast %>% select(ds, playoff, superbowl) %>% filter(abs(playoff + superbowl) > 0) %>% tail(10) #趨勢組件 prophet_plot_components(m, forecast);
數據生成環節有兩個數據集要生成,一批數據是常規的數據(譬如流量),還有一個是節假日的時間數據
其中lower_window,upper_window 能夠理解爲假日延長時限,國慶和元旦確定休息時間不一致,設置地很人性化,譬如聖誕節的平安夜+聖誕節兩天,那麼就要設置(lower_window = -1, upper_window = 1)。這個lower_window 的尺度爲天,因此若是你的數據是星期/季度,須要設置-7/+7,比較合理。舉一個python中的設置方式(時序是by week):
c3_4 = pd.DataFrame({ 'holiday': 'c1', 'ds': pd.to_datetime(['2017/2/26', '2017/3/5'), 'lower_window': -7, 'upper_window': 7, })
lower_window,upper_window 是節日效應的精髓,通常狀況下,在-7 / +7 的時間跟活動期的數值不同,恰好能夠不少表示出節日的正態效應。
數據長這樣:
holiday ds lower_window upper_window <chr> <date> <dbl> <dbl> 1 playoff 2008-01-13 0 1 2 playoff 2009-01-03 0 1 3 playoff 2010-01-16 0 1 4 playoff 2010-01-24 0 1 5 playoff 2010-02-07 0 1
預測階段,記得要開啓prophet(history, holidays = holidays)中的holidays。如今能夠來看看節假日效應:
ds playoff superbowl 1 2015-01-11 0.012300004 0 2 2015-01-12 -0.008805914 0 3 2016-01-17 0.012300004 0 4 2016-01-18 -0.008805914 0 5 2016-01-24 0.012300004 0 6 2016-01-25 -0.008805914 0 7 2016-02-07 0.012300004 0 8 2016-02-08 -0.008805914 0
從數據來看,能夠看到有一個日期是重疊的,超級碗+季後賽在同一天,那麼這樣就會出現節日效應累加的狀況。
能夠看到季後賽當日的影響比較明顯,超級碗當日基本沒啥影響,固然了,這些數據都是我瞎編的,要是有效應就見xxx。
趨勢分解這裏,除了趨勢項、星期、年份,多了一個節假日影響,看到了嗎?
.
一些狀況下節假日會發生過擬合,那麼可使用holidays.prior.scale參數來進行調節,使其平滑過渡。(不知道翻譯地對不對,原本剛開始覺得是節後效應…)
#節後效應 holidays.prior.scale m <- prophet(history, holidays = holidays, holidays.prior.scale = 1) forecast <- predict(m, future) forecast %>% select(ds, playoff, superbowl) %>% filter(abs(playoff + superbowl) > 0) %>% tail(10)
主要經過holidays.prior.scale來實現,默認是10。因爲筆者亂整數據,這裏顯示出效應,因此粘貼官網數據。官網的案例裏面,經過調節,使得當晚超級碗的效應減弱,兼顧了節前的狀況對當日的影響。
同時除了節前,還有季節前的效應,經過參數seasonality_prior_scale 調整
DS PLAYOFF SUPERBOWL 2190 2014-02-02 1.362312 0.693425 2191 2014-02-03 2.033471 0.542254 2532 2015-01-11 1.362312 0.000000 2533 2015-01-12 2.033471 0.000000 2901 2016-01-17 1.362312 0.000000 2902 2016-01-18 2.033471 0.000000 2908 2016-01-24 1.362312 0.00000
.
.
本節以後主要就是玩案例裏面的數據,案例數據若是R包中沒有,能夠從這裏下載。
.
時間序列裏面的極可能存在突變點,譬如一些節假日的衝擊。Prophet會自動檢測這些突變點,並進行適當的調整,可是機器判斷會出現:沒有對突變點進行調整、突變點過分調整兩種狀況,若是真的突變點出現,也能夠經過函數中的參數進行調節。
Prophet本身會檢測一些突變點,如下的圖就是Prophet本身檢測出來的,虛縱向表明突變點。檢測到了25個,那麼Prophet的作法跟L1正則同樣,「僞裝」/刪掉看不見這些突變。
Prophet經過首先指定大量的變化點來檢測轉換點,在這些變化點上容許改變速率。而後對速率變化的幅度進行稀疏優先(至關於L1正則化)-這實質上意味着先知有不少可能改變速率的地方,可是會盡量少地使用它們。從快速入門考慮Peyton Manning預測。默認狀況下,先知指定了25個潛在的變化點,它們被均勻地放置在時間序列的前80%個。
By default changepoints are only inferred for the first 80% of the time series in order to have plenty of runway for projecting the trend forward and to avoid overfitting fluctuations at the end of the time series. This default works in many situations but not all, and can be change using the changepoint_range argument. For example, m = Prophet(changepoint_range=0.9) in Python or m <- prophet(changepoint.range = 0.9) in R will place potential changepoints in the first 90% of the time series.
能夠參考 trend_changepoints.ipynb 繪圖看。貌似是經過變化率來檢測change point。
If the trend changes are being overfit (too much flexibility) or underfit (not enough flexibility), you can adjust the strength of the sparse prior using the input argument changepoint_prior_scale. By default, this parameter is set to 0.05. Increasing it will make the trend more flexible
從這段話能夠看到,change point的參數:changepoint.prior.scale
會影響對趨勢的判斷,設置大些表示趨勢受這些change point影響較大,過大固然可能致使過擬合。例如,我從0.01修改成0.1,就致使過擬合。以下圖:
其本身檢驗突變點的方式,相似觀察ARIMA的自相關/偏相關係數截尾、拖尾:
.
經過changepoint_prior_scale進行人爲干預。
df = pd.read_csv('../examples/example_wp_peyton_manning.csv') m <- prophet(df, changepoint.prior.scale = 0.5) forecast <- predict(m, future) plot(m, forecast)
來感覺一下changepoint.prior.scale=0.05和0.5的區別:
能夠把changepoint.prior.scale當作一個彈性尺度,值越大,受異常值影響越大,那麼波動越大,如0.5這樣的。
.
當你知道數據中,存在某一個肯定的突變點,且知道時間。能夠用changepoints 函數。不po圖了。
df = pd.read_csv('../examples/example_wp_peyton_manning.csv') m <- prophet(df, changepoints = c(as.Date('2014-01-01'))) forecast <- predict(m, future) plot(m, forecast)
.
標題取了這麼一個名字,也是夠嚇人的,哈哈~ 第三節的前3點都是如何消除突變點並進行預測。
可是! 現實是,突變點是真實存在,且有些是有意義的,譬如雙十一、雙12這樣的節日。不能去掉這些突變點,可是不去掉又會影響真實預測,這時候Prophet新奇的來了一招:序列生成模型中,多少受異常值些影響(相似前面的changepoint_prior_scale,可是這裏是從生成模型階段就給一個彈性值)。
這裏從生成模型中能夠進行三個角度的調節:
(1)調節趨勢;
(2)季節性調節
df = pd.read_csv('../examples/example_wp_peyton_manning.csv') m <- prophet(df, interval.width = 0.95) forecast <- predict(m, future)
在prophet生成模型階段,加入interval.width,就是表明生成模型時,整個序列趨勢,還有5%受異常值影響。
補充:在繪圖看來就是上下界的曲線更寬了!!!!——本質上是更多考慮了趨勢不肯定性以及隨機擾動的不肯定性!!!若是是季節不肯定性的話,就要用到MCMC了!
對於生產廠家來講,季節性波動是確定有的,那麼又想保留季節性突變狀況,又要預測。並且季節性適應又是一個比較麻煩的事情,prophet裏面須要先進行全貝葉斯抽樣,mcmc.samples參數,默認爲0.
m <- prophet(df, mcmc.samples = 500) forecast <- predict(m, future) prophet_plot_components(m, forecast);
打開mcmc.samples按鈕,會把MAP估計改變爲MCMC採樣,訓練時間很長,多是以前的10倍。最終結果,官網DAO圖:
.
補充:如上面所說,本質上就是引入了季節不肯定性!
季節性的不肯定性
默認狀況下,先知只會返回不肯定性的趨勢和觀測噪聲。要得到季節性的不肯定性,你必須作徹底貝葉斯抽樣。這是使用參數'MCMC_samples'(默認爲0)來完成的。
這用MCMC採樣代替了典型的MAP估計,而且可能須要更長的時間,這取決於有多少觀測——指望幾分鐘而不是幾秒鐘。若是你作了完整的採樣,那麼當你繪製它們時,你會看到季節性成分的不肯定性!
例子見:uncertainty_intervals.ipynb
關於MCMC,參考:https://blog.csdn.net/google19890102/article/details/51755242,我我的感受本質上是在用HMM的思路來求解t+1時刻生成的樣本問題。或許季節性的規律正是能夠經過它來學習(需看fb prophet論文)
MCMC(Markov Chain Monte Carlo)是一種經典的機率分佈採樣方法。解決什麼問題?
咱們經常遇到這樣的問題:模型構建好以後,有一個機率p(x(稱爲目標分佈),不能顯式的給出其表達,只能生成一系列符合這個分佈的x。這種問題稱爲「採樣」。
異常值與突變點是有區別的,離羣值對預測影響尤爲大。
df <- read.csv('../examples/example_wp_R_outliers1.csv') df$y <- log(df$y) m <- prophet(df) future <- make_future_dataframe(m, periods = 1096) forecast <- predict(m, future) plot(m, forecast);
對結果的影響很大,並且致使預測置信區間擴大多倍不止。prophet的優點體現出來了,prophet是能夠接受空缺值NA的,因此這些異常點刪掉或者NA掉,都是能夠的。
#異常點變爲NA+進行預測 outliers <- (as.Date(df$ds) > as.Date('2010-01-01') & as.Date(df$ds) < as.Date('2011-01-01')) df$y[outliers] = NA m <- prophet(df) forecast <- predict(m, future) plot(m, forecast);
固然啦,你也能夠刪掉整一段影響數據,特別是天災人禍的影響是永久存在的,那麼能夠刪掉這一整段。下圖就是這樣的狀況,2015年6月份左右的一批數據,都是離羣值。
.
.
前面第三章後面就提過,prophet是能夠處理缺失值。那麼這裏就能夠實現這麼一個操做,若是你的數據不完整,且是間斷的,譬如你有一個月20天的數據,那麼你也能夠根據prophet預測,同時給予你天天的數據結果。實現瞭如下的功能:
prophet=缺失值預測+插值
df <- read.csv('../examples/example_retail_sales.csv') m <- prophet(df) future <- make_future_dataframe(m, periods = 3652) fcst <- predict(m, future) plot(m, fcst);
源數據長這樣:
ds y 1 1992-01-01 146376 2 1992-02-01 147079 3 1992-03-01 159336 4 1992-04-01 163669 5 1992-05-01 170068
也就是你只有一年的每月的數據,上面是預測接下來每一天的數據,也能預測,可是後面天天預測的偏差有點大。因此你能夠設置make_future_dataframe中的freq,後面預測的是每月的:
future <- make_future_dataframe(m, periods = 120, freq = 'm') fcst <- predict(m, future) plot(m, fcst)
prophet = Prophet()
傳入參數說明:(打開forecaster.py文件,查看它的__init__方法)
growth = 'linear':fbporphet有兩種模式,線性增加模式和邏輯增加模式(growth='logistic')
changepoints:指定潛在改變點,若是不指定,將會自動選擇潛在改變點例如:
changepoints=['2014-01-01']
指定2014-01-01這一天是潛在的changepoints
n_changepoints:默認值爲25,表示changepoints的數量大小,若是changepoints指定,該傳入參數將不會被使用。若是changepoints不指定,將會從輸入的歷史數據前80%中選取25個(個數由n_changepoints傳入參數決定)潛在改變點。
yearly_seasonality:指定是否分析數據的年季節性,若是爲True,最後會輸出,yearly_trend,yearly_upper,yearly_lower等數據。
weekly_seasonality:指定是否分析數據的周季節性,若是爲True,最後會輸出,weekly_trend,weekly_upper,weekly_lower等數據。
daily_seasonality:xxxxx,以下圖,若是設置爲false,則預測的時候表現不出數據天天類似的規律性。
holidays:傳入pd.dataframe格式的數據。這個數據包含有holiday列 (string)和ds(date類型)和可選列lower_window和upper_window來指定該日期的lower_window或者upper_window範圍內都被列爲假期。lower_window=-2將包括前2天的日期做爲假期,例如:(這個是官方的quick start中的季後賽和超級盃兩個假期的指定)
seasonality_prior_scale:季節性模型的調節強度,較大的值容許模型以適應更大的季節性波動,較小的值抑制季節性。
holidays_prior_scale:假期組件模型的調節強度。
changepoints_prior_scale:自動的潛在改變點的靈活性調節參數,較大值將容許更多的潛在改變點,較小值將容許更少的潛在改變點。
mcmc_samples:整數,若大於0,將作mcmc樣本的全貝葉斯推理,若是爲0,將作最大後驗估計。
指定貝葉斯抽樣,例如mcmc_samples=20,
Iteration: 1 / 20 [ 5%] (Warmup) (Chain 0) Iteration: 2 / 20 [ 10%] (Warmup) (Chain 0) Iteration: 4 / 20 [ 20%] (Warmup) (Chain 0) Iteration: 6 / 20 [ 30%] (Warmup) (Chain 0) Iteration: 8 / 20 [ 40%] (Warmup) (Chain 0) Iteration: 10 / 20 [ 50%] (Warmup) (Chain 0) Iteration: 11 / 20 [ 55%] (Sampling) (Chain 0) Iteration: 12 / 20 [ 60%] (Sampling) (Chain 0) Iteration: 14 / 20 [ 70%] (Sampling) (Chain 0) Iteration: 16 / 20 [ 80%] (Sampling) (Chain 0) Iteration: 18 / 20 [ 90%] (Sampling) (Chain 0) Iteration: 20 / 20 [100%] (Sampling) (Chain 0)
預測時會打印出這些。
interval_width:浮點數,給預測提供不肯定性區間寬度,若是mcmc_samples=0,這將是預測的惟一不肯定性,若是mcmc_samples>0,這將會被集成在全部的模型參數中,其中包括季節性不肯定性
uncertainty_samples:模擬繪製數,用於估計不肯定的時間間隔
make_future_dataframe()準備預測的數據框架,該函數的定義以下:
periods:指定要預測的時長,要根據freq這個參數去設置。假如freq='D',那麼粒度爲天,periods則指定要預測將來多少天的數據。若是freq='H‘,則periods指定要預測將來多少小時的數據(固然,要在框架支持粒度爲小時的前提下才能運用)。
include_history:是否包含歷史數據,保持默認就好。
畫圖:
說明:圖中淺藍色表示yhat_upper和yhat_lower,受到interval_width這個參數的影響,固然,從forecasts的keys中能夠看到,還有其餘的_upper和_lower,一樣也會受到這個參數的影響。
'
下面這個時間序列中,季節性不是先知所假設的常數加性因子,而是隨趨勢而增加。這是乘法季節性。此時要使用:seasonality_mode='multiplicative'
對於季節性趨勢變化不大的情形,使用的話容易過擬合: