從時間序列ariam模型到Prophet模型的應用

2020-12-05 CDA數據分析師

所遇問題

前兩個星期,我的一個朋友(任職於上海的一家數據公司的機器學習崗位)在工作中有一個華為手機各價位銷售趨勢預測的項目,需要用到時間序列,找到我一起做一下協助。數據是2016年12月-2019年12月的脫敏數據,拿到的數據很簡單,我們的思路是按照價格段來分組,根據不同的價格段用前三年的數據劃分訓練集和測試集,預測2020年前6個月的趨勢走向。但是遇到的問題是數據中2017年整個6月份的數據是缺失的,各年的3月,5月,11月分別有零散缺失。其中每年份中6月18日,11月11日,12月12日等特殊日期的峰值特別的高。

了解完數據的特點,我首先想到的是用時間序列裡的arima模型,把2017年1月,2018年1月的數據作為訓練集,2019年1月的數據作為測試集,跑入模型,預測2020年1月的數據,同理用2017年2月,2018年2月的數據作為訓練集,2019年2月的數據作為測試集,預測2020年2月的數據,用這個思路分別來預測2020年1月,2月,3月,4月,5月,6月的數據,拋開缺失不談,這種思路預測效果偏差很大,直接原因是因為訓練數據量太少。第二種做法是直接把三年的數據全放進去,按七三比例拆分成訓練集和測試集,利用步長差分消除季節性去跑模型,一起預測出2020年前六個月的數據。但是arima模型不能很好的解決2017年6月份缺失的數據,針對節假日數據也沒辦法很好的控制,我們採取的方法是把屬於6月18日,11月11日,12月12日等購物節假日的數據剔除,零散缺失值用-1填充,但是最後結果也是不盡人意。

探索新方法

通過查找資料和交流,最終確定了處理時間序列的另外一種非常實用的模型Prophet模型。Prophet模型可以很好的解決異常的節假日級別的數據,在這裡使數據和代碼簡單的介紹一下Prophet模型的使用。

Prophet 遵循 sklearn 庫建模的應用程式接口。我們創建了一個 Prophet 類的實例,其中使用了「擬合模型」 fit 和「預測」 predict 方法。

# Python import pandas as pdimport numpy as npfrom fbprophet import Prophetimport matplotlib.pyplot as pltimport warningswarnings.filterwarnings("ignore")data = pd.read_csv('原版市場價格段.csv',encoding='gbk')data['y'] = np.log(data['1200元~2400元'])data['ds'] = data['時間']df = data[['ds','y']]df# 擬合模型m = Prophet()m.fit(df)# 構建待預測日期數據框,periods = 365 代表除歷史數據的日期外再往後推 365 天future = m.make_future_dataframe(periods=365)future.tail()# 預測數據集forecast = m.predict(future)forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()# 展示預測結果m.plot(forecast)# 預測的成分分析繪圖,展示預測中的趨勢、周效應和年度效應m.plot_components(forecast)

forecast[['ds','yhat_1']]forecast['y1'] = data['1200元~2400元']forecast[['ds','yhat_1','y1']].describe(percentiles= [0.1,0.9,0.95,0.99,0.999])forecast.loc[forecast['y1'] > 3.492611e+07,'y1'] = 8.811842e+06forecast[['ds', 'yhat']] forecast['yhat_1'] = np.exp(forecast[ 'yhat'])forecast[['ds', 'yhat','yhat_1']]plt.figure(figsize=(15,6))plt.plot(forecast['ds'],forecast[['yhat_1','y1']])# plt.xticks(np.arange(57)[0::6], train.時間[0::6])#plt.xticks(np.arange(57)[0::12], train.時間[0::12],rotation=90)plt.xlabel('時間')plt.ylabel('1200元~2400元')plt.title('手機1200元~2400元價格段')plt.show()

飽和預測

data = pd.read_csv('原版市場價格段.csv',encoding='gbk')data['y'] = np.log(data['1200元~2400元'])data['ds'] = data['時間']df = data[['ds','y']]df['cap'] = 1.5dfm = Prophet(growth='logistic')m.fit(df)future = m.make_future_dataframe(periods=365)future['cap'] = 1.5fcst = m.predict(future)fig = m.plot(fcst)

df['y'] = 10 - df['y']df['cap'] = 6df['floor'] = 1.5future['cap'] = 6future['floor'] = 1.5m = Prophet(growth='logistic')m.fit(df)fcst = m.predict(future)fig = m.plot(fcst)

趨勢突變點

在之前的部分,我們可以發現真實的時間序列數據往往在趨勢中存在一些突變點。默認情況下, Prophet 將自動監測到這些點,並對趨勢做適當地調整。不過,要是對趨勢建模時發生了一些問題,例如:Prophet 不小心忽略了一個趨勢速率的變化或者對歷史數據趨勢變化存在過擬合現象。如果我們希望對趨勢的調整過程做更好地控制的話,那麼下面將會介紹幾種可以使用的方法。

Prophet 中的自動監測突變點

data = pd.read_csv('原版市場價格段.csv',encoding='gbk')data['y'] = np.log(data['1200元~2400元'])data['ds'] = data['時間']df = data[['ds','y']]# 擬合模型m = Prophet()m.fit(df)# 構建待預測日期數據框,periods = 365 代表除歷史數據的日期外再往後推 365 天future = m.make_future_dataframe(periods=365)future.tail()# 預測數據集forecast = m.predict(future)forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()from fbprophet.plot import add_changepoints_to_plotfig = m.plot(forecast)a = add_changepoints_to_plot(fig.gca(), m, forecast)

調整趨勢的靈活性

如果趨勢的變化被過度擬合(即過於靈活)或者擬合不足(即靈活性不夠),可以利用輸入參數 changepoint_prior_scale 來調整稀疏先驗的程度。默認下,這個參數被指定為 0.05 。增加這個值,會導致趨勢擬合得更加靈活。代碼和圖如下所示:

data = pd.read_csv('原版市場價格段.csv',encoding='gbk')

data['y'] = np.log(data['1200元~2400元'])

data['ds'] = data['時間']df = data[['ds','y']]# 擬合模型

m = Prophet(changepoint_prior_scale=0.5)m.fit(df)# 構建待預測日期數據框,

periods = 365 代表除歷史數據的日期外再往後推 365 天

future = m.make_future_dataframe(periods=365)

forecast = m.predict(future)fig = m.plot(forecast)

指定突變點的位置

如果你希望手動指定潛在突變點的位置而不是利用自動的突變點監測,可以使用 changepoints 參數。

m = Prophet(changepoints=['2017-06-18', '2017-11-11', '2017-12-12' ])m.fit(df)future = m.make_future_dataframe(periods=365)forecast = m.predict(future)m.plot(forecast)

季節性,假期效果和回歸量

對假期和特徵事件建模

playoffs = pd.DataFrame({ 'holiday': 'playoff', 'ds': pd.to_datetime(['2016-12-12','2017-06-18', '2017-11-11', '2017-12-12', '2018-06-18', '2018-11-11', '2018-12-12', '2019-06-18', '2019-11-11', '2019-12-12', '2020-06-18', '2020-11-11', '2020-12-12']), 'lower_window': 0, 'upper_window': 1,})superbowls = pd.DataFrame({ 'holiday': 'superbowl', 'ds': pd.to_datetime(['2017-11-11', '2018-11-11', '2019-11-11', '2020-11-11']), 'lower_window': 0, 'upper_window': 1,})holidays = pd.concat((playoffs, superbowls))m = Prophet(changepoint_prior_scale=0.005,holidays=holidays,yearly_seasonality=80)m.fit(df)future = m.make_future_dataframe(periods=365)forecast = m.predict(future)# 可通過 forecast 數據框,來展示節假日效應:# 看一下假期的最後10行數據forecast[(forecast['playoff'] + forecast['superbowl']).abs() > 0][ ['ds', 'playoff', 'superbowl']][-10:]# 在成分分析的圖中,如下所示,也可以看到節假日效應。我們可以發現,在節日日期附近有一個穿透,而在超級碗日期時穿透則更為明顯。 fig = m.plot_components(forecast)m.plot(forecast)forecast['y'] = df['y']forecast[['ds', 'yhat']]forecast[['ds', 'yhat','y']]plt.figure(figsize=(15,6))plt.plot(forecast['ds'],forecast[['yhat','y']])# plt.xticks(np.arange(57)[0::6], train.時間[0::6])#plt.xticks(np.arange(57)[0::12], train.時間[0::12],rotation=90)plt.xlabel('時間')plt.ylabel('1200元~2400元')plt.title('手機1200元~2400元價格段')plt.show()

季節性的傅立葉級數

季節性是用部分傅立葉和估計的。有關完整的細節,請參閱論文,以及維基百科上的這個圖,以說明部分傅立葉和如何近似於一個線性周期信號。部分和(order)中的項數是一個參數,它決定了季節性的變化有多快。為了說明這一點, 我們仍似乎用第一部分中佩頓 · 曼寧的數據。每年季節性的默認傅立葉級數是10,這就產生了這樣的擬合:

from fbprophet.plot import plot_yearlym = Prophet().fit(df)a = plot_yearly(m)

默認值10通常是合適的,但是當季節性需要適應更高頻率的變化時,它們可以增加,並且通常不那麼平滑。在實例化模型時,可以為每個內置季節性指定傅立葉級數,這裡增加到20:

from fbprophet.plot import plot_yearlym = Prophet(yearly_seasonality=20).fit(df)a = plot_yearly(m)

可以看到,曲線更加的多變了。增加傅立葉項的數量可以使季節性適應更快的變化周期,但也可能導致過度擬合:N個傅立葉項對應於用於建模周期的2N個變量。

相關焦點

  • 時間序列模型
    ARMA-GARCH模型名字貌似長了點,看著暈,其實他是兩個模型的合體,一個叫ARMA,一個叫GARCH。別著急,我們來各個擊破。ARMA模型這個模型是時間序列模型中的一個重要模型,不僅在金融領域,在其他領域都有廣泛的應用。
  • 時間序列模型(三)——馬爾可夫模型
    很多教材都會單獨介紹馬爾可夫模型,但它是一種時間序列模型,可以用時間序列模型的思維來學習,並和其它時間序列模型做比較。       狀態空間指的是序列數據的狀態。(最少要有兩種狀態)理論上來說,這個空間可以是離散的,或者是連續的。本文主要討論最重要的離散狀態的情況。
  • 如何使用XGBoost模型進行時間序列預測
    XGBoost也可以被用於時間序列預測,儘管它需要將時間序列數據集先轉換成監督學習問題。它需要用到一種被稱為前進式驗證的特殊方法來評估模型,因為使用k折驗證來評估模型容易導致偏向樂觀的結果。本教程中,你將探索如何為時間序列預測開發一個XGBoost模型。
  • SAS時間序列模型預測未來航班數量
    時間序列模型利用歷史資料進行延伸預測,也稱歷史引伸預測法。
  • 時間序列的LSTM模型預測——基於Keras
    一、問題背景    現實生活中,在一系列時間點上觀測數據是司空見慣的活動,在農業、商業、氣象軍事和醫療等研究領域都包含大量的時間序列數據。時間序列的預測指的是基於序列的歷史數據,以及可能對結果產生影響的其他相關序列,對序列未來的可能取值做出預測。
  • 序列模型的實現細節
    介紹了變長序列 attention 的常見實現錯誤,並分享了一個簡單的數值穩定實現介紹了對長句的處理方案。討論了長句導致的內存溢出問題以及解決方案。介紹了 使用 TBPTT 對序列任務進行加速的方案,並對其與 BPTT 的區別進行了分析。前言序列模型組件如 RNN 和 Attention 在自然語言處理中有廣泛的應用。
  • 時間序列深度學習:狀態 LSTM 模型預測太陽黑子(上)
    由於數據科學機器學習和深度學習的發展,時間序列預測在預測準確性方面取得了顯著進展。隨著這些 ML/DL 工具的發展,企業和金融機構現在可以通過應用這些新技術來解決舊問題,從而更好地進行預測。本教程中,你將會學到:用 keras 包開發一個狀態 LSTM 模型,該 R 包將 R TensorFlow 作為後端。將狀態 LSTM 模型應用到著名的太陽黑子數據集上。藉助 rsample 包在初始抽樣上滾動預測,實現時間序列的交叉檢驗。
  • R語言ARIMA集成模型預測時間序列分析
    p=18493 本文我們使用4個時間序列模型對每周的溫度序列建模。第一個是通過auto.arima獲得的,然後兩個是SARIMA模型,最後一個是Buys-Ballot方法。我們使用以下數據k=620n=nrow(elec)futu=(k+1):ny=electricite$Load[1:k]plot(y,type="l")我們開始對溫度序列進行建模(溫度序列對電力負荷的影響很大)
  • 如何讓神經聲碼器高效地用於序列到序列聲學模型
    如何讓神經聲碼器高效地用於序列到序列聲學模型 IT創事記 發表於 2021-01-07 16:01:32 往往在放下手機之後你才會意識到,電話那頭的客服其實是個機器人;或者準確地說,是「一位」智能客服。
  • 自動化所提出基於腦功能影像時間序列的多尺度卷積循環神經網絡模型
    功能連接矩陣可以視作是一種對原始fMRI序列便捷的人工特徵提取方法,而其中的時序動態變化信息並沒有被充分地利用到分類中,如能將此部分損失信息加以有效利用,則對於提高fMRI的分類診斷能力具有重要意義。隨著深度學習技術的發展,循環神經網絡模型(LSTM, GRU等)以其優秀的非線性隱狀態建模能力,在序列分析領域的性能普遍超過了傳統的線性模型。
  • ...大學——醫學統計預測模型、數理統計醫學應用模型和生物數學模型
    所在院校: 山東大學       所在院系: 公共衛生學院 職稱: 副教授       招生專業: 研究領域: 醫學統計預測模型
  • 馬爾可夫模型學習
    馬爾可夫鏈的在很多應用中發揮了重要作用,例如,谷歌所使用的網頁排序算法(PageRank)就是由馬爾可夫鏈定義的1.3馬爾可夫模型      馬爾可夫模型(Markov Model)是一種統計模型,廣泛應用在語音識別,詞性自動標註,音字轉換,概率文法等各個自然語言處理等應用領域
  • 時間序列分析(三):平穩時間序列分析之數據準備
    平穩時間序列是時間序列中一類重要的時間序列,對於該時間序列,有一套非常成熟的平穩序列建模方法,這也是本節中將重點介紹的部分。對於非平穩序列,可以通過差分、提取確定性成分等方法,將轉化成平穩序列,再運用平穩序列建模方法進行建模。在實際操作中,由於樣本數據的匱乏,要根據樣本數據要找到生成樣本的真實隨機過程基本是不太可能的。
  • 常見概率模型在金融市場中的應用
    下表中列出了利用 S&P500 校正該 HMM 模型的參 數值,其中1和2分別是牛市和熊市的期望收益,1和2是從牛市轉移到熊市和熊市轉移 到牛市的轉換強度。從表中可以看出這些參數在 2008 年以前都比較穩定,2009年達到峰值,之後開始回落,這跟 2008-2009年間美股出現的大幅下滑表現一致,尤其是1達到最大值,說明市場有強趨勢向熊市轉換。由此可見該HMM模型對市場有一定的描述能力。
  • 時間序列基本概念
    平穩時間序列是時間序列中一類重要的時間序列,對於該時間序列,有一套非常成熟的平穩序列建模方法,這也是本節中將重點介紹的部分。對於非平穩序列,可以通過差分、提取確定性成分等方法,將轉化成平穩序列,再運用平穩序列建模方法進行建模。在實際操作中,由於樣本數據的匱乏,要根據樣本數據要找到生成樣本的真實隨機過程基本是不太可能的。
  • 風險模型方法研究——基於A股市場的應用
    (具體的討論可參考文集)最後,之前的每一步修正,其實都是針對橫截面方向上的修正,當出現金融危機等特殊時期,使用過去一段時間的信息來估計方差會出現明顯的低估。因此,在時間序列方向上也需對估計的波動做一個修正。基本的思路即是觀察近期的風險數據與預測數據的高低估程度,如在時間序列上有系統性偏差,則對其進行修正。
  • 使用LSTM深度學習模型進行溫度的時間序列單步和多步預測
    本文的目的是提供代碼示例,並解釋使用python和TensorFlow建模時間序列數據的思路。本文展示了如何進行多步預測並在模型中使用多個特徵。本文的簡單版本是,使用過去48小時的數據和對未來1小時的預測(一步),我獲得了溫度誤差的平均絕對誤差0.48(中值0.34)度。
  • 「八鬥之才」HMM模型在地址分詞中的應用
    首先,不管序列多長,要從序列長度為1算起,算序列長度為1時取到每個天氣的最大概率。然後,逐漸增加長度,每增加一次長度,重新算一遍在這個長度下最後一個位置取到每個天氣的最大概率。因為上一個長度下的取到每個天氣的最大概率都算過了,重新計算的話其實不難。當我們算到最後一位時,就知道最後一位是哪個天氣的概率最大了。然後,我們要把對應這個最大概率的序列從後往前推出來。
  • 賽爾筆記 | 隱馬爾可夫模型
    作者:哈工大SCIR碩士生 樂遠隱馬爾可夫模型(HMM)是可用於標註問題的統計學習模型,描述由隱藏的馬爾可夫鏈隨機生成觀測序列的過程
  • 從字符級的語言建模開始,了解語言模型與序列建模的基本概念
    任意語言模型的主要目的都是學習訓練文本中字符/單詞序列的聯合概率分布,即嘗試學習聯合概率函數。例如,如果我們試圖預測一個包含 T 個詞的單詞序列,那麼我們試圖獲取令聯合概率 P(w_1, w_2, …, w_T) 最大的詞序列,等價於所有時間步 (t) 上條件概率的累乘:。