R 笔记 prophet
0 理論部分
?論文筆記:Forecasting at Scale(Prophet)_UQI-LIUWJ的博客-CSDN博客
Prophet 是一種基于加法模型預測時間序列數據的程序,其中非線性趨勢、季節性以及假日效應相匹配。
它最適用于具有強烈季節性和有幾個季節歷史數據的時間序列。
Prophet 對缺失數據和趨勢變化具有魯棒性,并且通常可以很好地處理異常值。
1 基本流程
???????在 R 中,我們使用正常的模型擬合 API。 我們提供了一個執行擬合并返回模型對象的Prophet函數。 然后,您可以在此模型對象上調用 predict 和 plot。
library(prophet)1.1 讀入數據?
????????首先,我們讀入數據并創建結果變量。 與 Python?中的dataframe一樣,這是一個包含 ds 和 y 列的數據框,分別包含日期和數值。
? ? ? ??ds 列對于日期應該是 YYYY-MM-DD,對于時刻應該是 YYYY-MM-DD HH:MM:SS。?
df<-read.csv('C:/Users/16000/example_wp_log_peyton_manning.csv')1.2 調用prophet函數?
?調用prophet函數來擬合模型(對之前部分進行時間序列分解)
m<-prophet(df)1.3 生成future dataframe?
預測是在dataframe上進行的,其中 ds 列包含要進行預測的日期。
make_future_dataframe 函數使用 模型對象和 預測區間長度 進行預測并生成相應的dataframe。
future <- make_future_dataframe(m, periods = 365)默認情況下,它還將包括歷史日期,因此我們可以評估樣本內擬合。
?
相比于df,多了365個數據,即預測區間
?1.4? 獲得預測結果
????????與 R 中的大多數預測任務一樣,我們使用通用 predict 函數來獲得我們的預測。????????
forecast <- predict(m, future)????????預測結果是一個dataframe,其中包含預測的列 yhat。 它具有用于不確定性區間和季節性成分的附加列。
tail(forecast)ds trend additive_terms 3265 2017-01-14 7.188345 0.6353367 3266 2017-01-15 7.187317 1.0181583 3267 2017-01-16 7.186289 1.3441746 3268 2017-01-17 7.185261 1.1326084 3269 2017-01-18 7.184232 0.9662578 3270 2017-01-19 7.183204 0.9791888additive_terms_lower additive_terms_upper 3265 0.6353367 0.6353367 3266 1.0181583 1.0181583 3267 1.3441746 1.3441746 3268 1.1326084 1.1326084 3269 0.9662578 0.9662578 3270 0.9791888 0.9791888weekly weekly_lower weekly_upper yearly 3265 -0.31171456 -0.31171456 -0.31171456 0.9470512 3266 0.04829728 0.04829728 0.04829728 0.9698610 3267 0.35228502 0.35228502 0.35228502 0.9918896 3268 0.11963367 0.11963367 0.11963367 1.0129747 3269 -0.06665548 -0.06665548 -0.06665548 1.0329133 3270 -0.07227149 -0.07227149 -0.07227149 1.0514603yearly_lower yearly_upper multiplicative_terms 3265 0.9470512 0.9470512 0 3266 0.9698610 0.9698610 0 3267 0.9918896 0.9918896 0 3268 1.0129747 1.0129747 0 3269 1.0329133 1.0329133 0 3270 1.0514603 1.0514603 0multiplicative_terms_lower 3265 0 3266 0 3267 0 3268 0 3269 0 3270 0multiplicative_terms_upper yhat_lower yhat_upper 3265 0 7.054971 8.545286 3266 0 7.443115 8.954531 3267 0 7.791419 9.265397 3268 0 7.664162 9.071099 3269 0 7.391583 8.871629 3270 0 7.428541 8.869961trend_lower trend_upper yhat 3265 6.826222 7.538852 7.823682 3266 6.823645 7.538624 8.205475 3267 6.821068 7.538397 8.530463 3268 6.818564 7.538169 8.317869 3269 6.816108 7.537942 8.150490 3270 6.813651 7.537714 8.162393選擇特定列的話,可以
tail(forecast[c('ds', 'yhat', 'yhat_lower', 'yhat_upper')])ds yhat yhat_lower yhat_upper 3265 2017-01-14 7.823682 7.054971 8.545286 3266 2017-01-15 8.205475 7.443115 8.954531 3267 2017-01-16 8.530463 7.791419 9.265397 3268 2017-01-17 8.317869 7.664162 9.071099 3269 2017-01-18 8.150490 7.391583 8.871629 3270 2017-01-19 8.162393 7.428541 8.8699611.5 繪制圖像
1.5.1 plot?
可以使用plot函數,通過傳入模型和預測數據框來繪制預測。
plot(m, forecast)1.5.2??prophet_plot_components函數
prophet_plot_components(m,forecast)?
2 趨勢為飽和增長模型
大體框架和之間是一樣的,有幾個小地方有區別
載入包和讀入數據是一樣的
library(prophet)df<-read.csv('C:/Users/16000/example_wp_log_peyton_manning.csv')我們這里要給數據集增加一列:承載能力C
論文筆記:Forecasting at Scale(Prophet)_UQI-LIUWJ的博客-CSDN博客
df['cap']=8調用prophet的時候,需要聲明飽和增長模型
m<-prophet(df,growth='logistic')?生成future_dataframe的時候,也需要增加承載能力這一列
future<-make_future_dataframe(m,period=365) future['cap']=8?之后的預測和畫圖是一樣的
f<-predict(m,future) plot(m,f) prophet_plot_components(m,f)2.1 設置承載能力下限
除了cap之外,我們還可以設置承載能力的下限:使用floor即可
df['floor']=6 future['floor']=63 趨勢的變化點
????????默認情況下,Prophet 會自動檢測趨勢變化點,并允許趨勢進行適當的調整。 但是,如果您希望更好地控制此過程(例如,Prophet 錯過了速率變化,或者在歷史中過擬合速率變化),那么可以使用如下幾個輸入參數
3.1 prophet中變化點的自動檢測
????????Prophet 通過首先指定大量潛在趨勢變化點來檢測變化點。 然后它對速率變化的幅度進行稀疏先驗(相當于 L1 正則化)——這實質上意味著 Prophet 有大量可能的地方可以改變速率,但會盡可能少地使用它們。
?????????以下圖為例。 默認情況下,Prophet 指定了 25 個潛在的變化點,它們均勻地放置在時間序列的前 80% 中。 此圖中的垂直線表示放置潛在變化點的位置:
????????
?????????盡管我們有很多地方可能會更改趨勢,但由于先驗稀疏,這些更改點中的大多數都未使用。 我們可以通過繪制每個變化點的速率變化幅度來看到這一點:
????????
? ? ? ? 顯著變化點的位置可以通過以下方式可視化:(這里是線性趨勢的prophet)?
plot(m,forecast)+add_changepoints_to_plot(m)????????默認情況下,僅為時間序列的前 80% 推斷變化點,以便有足夠的時間片段來預測未來趨勢并避免在時間序列結束時過擬合波動。
????????此默認值適用于許多情況,但不是全部。可以使用 changepoint_range 參數進行更改。
m <- prophet(changepoint.range = 0.9)?3.2 調整趨勢變動的靈活性
????????如果趨勢變化過擬合(靈活性太大)或欠擬合(靈活性不夠),可以使用輸入參數 changepoint_prior_scale 調整稀疏先驗的強度。
???????? 默認情況下,此參數設置為 0.05
?????????增加它將使趨勢更加靈活? ? ? ? ??
m <- prophet(df, changepoint.prior.scale = 0.5)? ? ? ? 可以發現,相比于上一個情況,這里變化點變多了,同時幅度也變大了?
減少之將會變得不靈活
m <- prophet(df, changepoint.prior.scale = 0.001)3.3 手動指定變更點的位置 ?
????????可以使用 changepoints 參數手動指定潛在變更點的位置,而不是使用自動變更點檢測。 然后將只允許在這些點處更改斜率,并使用與以前相同的稀疏正則化。
m <- prophet(df,changepoints = c('2014-01-01','2010-02-03'))?
?4?節假日
4.1 手動提供節假日
????????如果您有想要建模的假期或其他特殊事件,則必須為它們創建一個數據框。 它有兩列(holiday 和 ds),每出現一個節假日就有一行。
???????? 必須包括假期的所有事件,包括過去(就歷史數據而言)和未來(就預測而言)。
???????? 如果它們將來不會重復,Prophet 將對它們進行建模,然后不將它們包括在預測中。
????????還可以包含列 lower_window 和 upper_window ,它們將假期延長到日期前后的 [lower_window, upper_window] 天。? ? ? ? ??
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 = 1,upper_window = 0 ) #假期延長到日期前的一天holidays <- bind_rows(playoffs, superbowls)?創建holiday表后,通過使用holidays 參數將假期影響包含在預測中。
m <- prophet(df,holidays = holidays)forecast <- predict(m, future)prophet_plot_components(m,forecast)?相比于之前,這邊多出了holiday 的影響
可以用一種類似于sql的方式 查看 holiday的影響
forecast %>%select(ds, playoff, superbowl) %>%filter(abs(playoff + superbowl) > 0)ds playoff superbowl 1 2008-01-13 1.220577 0.000000 2 2008-01-14 1.909146 0.000000 3 2009-01-03 1.220577 0.000000 4 2009-01-04 1.909146 0.000000 5 2010-01-16 1.220577 0.000000 6 2010-01-17 1.909146 0.000000 7 2010-01-25 1.909146 0.000000 8 2010-02-07 1.220577 1.215571 9 2011-01-08 1.220577 0.000000 10 2011-01-09 1.909146 0.000000 11 2013-01-12 1.220577 0.000000 12 2013-01-13 1.909146 0.000000 13 2014-01-12 1.220577 0.000000 14 2014-01-13 1.909146 0.000000 15 2014-01-19 1.220577 0.000000 16 2014-01-20 1.909146 0.000000 17 2014-02-02 1.220577 1.215571 18 2014-02-03 1.909146 1.384333 19 2015-01-11 1.220577 0.000000 20 2015-01-12 1.909146 0.000000 21 2016-01-17 1.220577 0.000000 22 2016-01-18 1.909146 0.000000 23 2016-01-24 1.220577 0.000000 24 2016-01-25 1.909146 0.000000 25 2016-02-07 1.220577 1.215571 26 2016-02-08 1.909146 1.384333?4.2 提供國家節假日
????????您可以使用 add_country_holidays 方法使用內置的特定國家/地區假期集合。
???????? 指定國家/地區的名稱,然后除了通過4.1指定的任何假期外,還將包括該國家/地區的主要假期:
? ? ? ? 但是這里有一點需要說明,在add_country_holidays之前,不能fit model,比如下述代碼,就會報錯
m <- prophet(df,holidays = holidays)m<-add_country_holidays(m,'US')#Error in add_country_holidays(m, "China") : # Country holidays must be added prior to model fitting.??
m <- prophet(holidays = holidays)m<-add_country_holidays(m,'CN')m<-fit.prophet(m,df)forecast <- predict(m, future)prophet_plot_components(m,forecast)4.2.1?查看目前設置的節假日
加observed表示只有在觀察集里面有
m$train.holiday.names [1] "playoff" "superbowl" "New Year's Day" "Chinese New Year" [5] "Tomb-Sweeping Day" "Labor Day" "Dragon Boat Festival" "Mid-Autumn Festival" [9] "National Day"4.2.2 可以提供的國家假日
????????可用國家/地區列表和要使用的國家/地區名稱可在其頁面上找到:https://github.com/dr-prodigy/python-holidays。
????????除了這些國家/地區,Prophet 還包括以下國家/地區的假期:巴西 (BR)、印度尼西亞 (ID)、印度 (IN)、馬來西亞 (MY)、越南 (VN)、泰國 (TH)、菲律賓 (PH)、巴基斯坦 ( PK)、孟加拉國 (BD)、埃及 (EG)、中國 (CN)、俄羅斯 (RU)、韓國 (KR)、白俄羅斯 (BY) 和阿拉伯聯合酋長國 (AE)。
????????在 R 中,假日日期是從 1995 年到 2044 年計算的,并作為 data-raw/generated_holidays.csv 存儲在包中。
4.3 節假日尺度
????????如果您發現假期過擬合,您可以使用參數holiday_prior_scale 調整其先驗比例以使其平滑。
????????默認情況下,此參數為 10,它提供的正則化非常少。 減少這個參數會減弱假日效應,增大則會強調節假日的作用:
m <- prophet(df, holidays = holidays, holidays.prior.scale = 1000)5 季節性
5.1 季節性的傅里葉級數
????????使用部分傅里葉級數和來估計季節性
????????部分總和(順序)中的項數是決定季節性變化速度的參數。
????????年度季節性的默認傅里葉順序為 10
m <- prophet(df) prophet:::plot_yearly(m)????????默認值通常是合適的,但是當季節性需要適應更高頻率的變化時可以增加它們,并且通常不太平滑。 在實例化模型時,可以為每個內置的季節性指定傅里葉階數,這里增加到 20:
????????增加傅立葉項的數量可以使季節性適應更快的變化周期,但也可能導致過度擬合:N 個傅立葉項對應于用于對周期進行建模的 2N 個變量
m <- prophet(df, yearly.seasonality = 20) prophet:::plot_yearly(m)?5.2 指定自定義季節性
????????如果時間序列的長度超過兩個周期,Prophet 將默認擬合每周和每年的季節性。
????????可以使用 add_seasonality 方法、添加其他季節性(每月、每季度、每小時)。
????????
????????此函數的輸入是名稱、季節性周期(以天為單位)以及季節性的傅里葉階。 作為參考,Prophet 默認使用3階 傅里葉階數?表示每周季節性,10 表示年度季節性。
? ? ? ??
????????
? ? ? ? 這里和add_country_holidays一樣,不能先擬合
????????
m<-prophet()m<-add_seasonality(m, name='monthly', period=30.5, fourier.order=5)m<-fit.prophet(m,df)forecast <- predict(m, future)prophet_plot_components(m, forecast)????????
5.3 取消某一個的季節性?
m<-prophet(df,weekly.seasonality = FALSE) forecast <- predict(m, future) prophet_plot_components(m, forecast)?5.4?取決于其他因素的季節性
????????在某些情況下,季節性可能取決于其他因素,例如夏季與一年中其他時間不同的每周季節性模式,或周末與工作日不同的每日季節性模式。 這些類型的季節性可以使用條件季節性進行建模。
????????默認的每周季節性假設全年每周季節性的模式是相同的,但我們預計每周季節性的模式在旺季、和淡季是不同的。 我們可以使用條件季節性來構建單獨的旺季和淡季每周季節性。
????????首先,我們在數據框中添加一個布爾列,指示每個日期是在旺季還是淡季:
?
?????????然后我們禁用內置的每周季節性,并將其替換為兩個將這些列指定為條件的每周季節性。
???????? 這意味著季節性僅適用于 condition_name 列為 True 的日期。
???????? 我們還必須將該列添加到我們正在對其進行預測的未來數據幀中。
?
m <- prophet(weekly.seasonality=FALSE) m <- add_seasonality(m, name='weekly_on_season', period=7, fourier.order=3, condition.name='on_season') m <- add_seasonality(m, name='weekly_off_season', period=7, fourier.order=3, condition.name='off_season') m <- fit.prophet(m, df)future$on_season <- is_nfl_season(future$ds) future$off_season <- !is_nfl_season(future$ds) forecast <- predict(m, future) prophet_plot_components(m, forecast)?????????現在,這兩種季節性都顯示在上面的分量圖中。 我們可以看到,旺季期間,周日和周一都有大幅增加,而在淡季則完全沒有。
5.5 指定季節性尺度
? ? ? ? 和節假日一樣,季節性也有一個尺度 seasonality_prior_scale
????????
m <- add_seasonality(m, name='weekly', period=7, fourier.order=3, prior.scale=0.1)6 乘法季節性
????????默認情況下,Prophet 擬合加法季節性,這意味著將季節性的影響添加到趨勢中以獲得預測
? ? ? ? 我們看一種情況,如下圖所示,這個時間序列有一個明顯的年周期,但是預測的季節性在時間序列開始時太大而結束時太小。 在這個時間序列中,季節性并不是 Prophet 假設的恒定加法因子,而是隨趨勢增長。 這是乘法季節性。
????????
?????????Prophet 可以通過在輸入參數中設置seasonality_mode='multiplicative'來擬合乘法季節性:
m <- prophet(df, seasonality.mode = 'multiplicative')????????使用seasonality_mode='multiplicative',假日效應也將被建模為乘法。
???????? 默認情況下,任何添加的季節性將設置為seasonality_mode,但可以通過在添加季節性時指定 mode='additive' 或 mode='multiplicative' 作為參數來覆蓋
m <- prophet(seasonality.mode = 'multiplicative') m <- add_seasonality(m, 'quarterly', period = 91.25, fourier.order = 8, mode = 'additive')?7 不確定區間
????????默認情況下,Prophet 將返回預測 yhat 的不確定區間。?
????????預測中存在三個不確定性區間:趨勢的不確定性、季節性估計的不確定性和額外的觀測噪聲。
7.1 趨勢的不確定性
????????預測中最大的不確定性來源是未來趨勢變化的可能性。我們假設未來會看到與歷史相似的趨勢變化。 特別是,我們假設未來趨勢變化的平均頻率和幅度將與我們在歷史上觀察到的相同。 我們向前預測這些趨勢變化,并通過計算它們的分布,我們獲得不確定區間。
????????這種測量不確定性的方式的一個特性是,通過增加 changepoint_prior_scale 來允許預測具有更大的可取區間,增加預測的不確定性。
????????可以使用參數 interval_width 設置不確定區間的寬度(默認為 80%):
m <- prophet(df, interval.width = 0.95) forecast <- predict(m, future) plot(m,forecast)相比于之前,不確定區間更大了
7.2 季節性的不確定性?
????????默認情況下,Prophet 只會返回趨勢和觀察噪聲的不確定性。 要獲得季節性的不確定性,必須進行完整的貝葉斯抽樣。 這是使用參數 mcmc.samples(默認為 0)完成的。
m <- prophet(df, mcmc.samples = 300) forecast <- predict(m, future)?????????這用 MCMC 采樣代替了典型的 MAP 估計,并且可能需要更長的時間,具體取決于有多少觀察 - 預計幾分鐘而不是幾秒鐘。
????????當繪制季節性分量時,就會看到它們的不確定性:
prophet_plot_components(m,forecast)?
?
8 異常值
????????異常值可以通過兩種主要方式影響 Prophet 的預測。 在這里,我們對之前記錄的對 R 頁面的 Wikipedia 訪問進行了預測,但有一個壞數據塊:
df<-read.csv('C:/Users/16000/example_wp_log_R_outliers1.csv') m <- prophet(df) future <- make_future_dataframe(m, periods = 1096) forecast <- predict(m, future) plot(m, forecast)????????
?????????趨勢預測似乎合理,但不確定性區間似乎太寬了。 Prophet 能夠處理歷史中的異常值,但只能通過將它們與趨勢變化相匹配。 然后,不確定性模型預計類似幅度的未來趨勢變化。
????????處理異常值的最佳方法是刪除它們——Prophet 對丟失數據沒有任何問題。 如果您在歷史記錄中將它們的值設置為 NA 但將日期保留在未來,那么 Prophet 將為您提供對它們值的預測。
????????
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)? ? ? ? ? ? ? ? ?去掉異常值后,趨勢還是之前沒去掉異常值時差不多的趨勢,但是不確定區間小了很多
9 非每日數據
????????Prophet 可以通過在 ds 列中傳入帶有時間戳的數據框來對非每日數據的時間序列進行預測。 時間戳的格式應為 YYYY-MM-DD HH:MM:SS 。
????????
?
?????????在這里,我們將 Prophet 擬合到 5 分鐘為頻率的數據:
df<-read.csv('C:/Users/16000/example_yosemite_temps.csv')m <- prophet(df)future <- make_future_dataframe(m, periods = 300, freq = 60 * 60) #第一個60表示幾分鐘,第二個60表示秒 (乘積表示預測區間每兩個之間間隔多少秒)fcst <- predict(m, future) plot(m, fcst)(freq=這里也可以是字符串比如“month”這種)?
?此時我們畫出時間序列分解之后的圖,daily seasonality已經被成了不同時刻的季節性了
prophet_plot_components(m,fcst)?
總結
以上是生活随笔為你收集整理的R 笔记 prophet的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NTU 笔记 6422quiz 复习(1
- 下一篇: python 笔记 size-const