Prophet模型預測2018京東訂單量

背景

最近,即將要實習的公司經理給了一個關於Prophet預測模型的案例,讓我去學習一下怎麼調參數。正好我早就想體驗一下傳說中「會一手調參數,就能夠在碩士圈混」的感覺了,🤣🤣🤣。本文主要經過簡單介紹Prophet模型及其重要參數,再結合京東訂單量的例子,加深對Prophet模型的瞭解。html

認識Prophet模型

簡介

Prophet模型,英文直譯爲「先知」模型,是Facebook公司於2017開源的一個基於Python和R語言的時間序列預測算法。它適用於具備趨勢性、多種週期性(每一年每個月每週每日每小時等)、節假日效應,以及部分異常值的時間序列,該模型不須要使用者掌握深厚的時間序列分析的統計學知識,Facebook 表示,默認配置的Prophet就能夠生成媲美經驗豐富的專業數據分析師的預測,即便不是時序分析專家,也能夠理解該模型的重要參數。python

模型結構

Prophet模型本質上是一個可加性迴歸模型,其基本形式以下:git

clipboard.png

其中:github

  • g(t) :趨勢項,表示非週期性的變化,如:飽和增加、分段線性兩種
  • s(t) :週期項,表示週期性的變化(傅立葉級數),如:每一年每個月每週每日每小時
  • h(t):節假日項,表示節假日或重大事件的變化,如春節、雙十一
  • ϵt:噪聲項,表示沒法建模和預測的隨即波動,服從高斯分佈,如:政府政策變更,世界末日

重要參數

下面分別爲Prophet模型(Python)中三大模型相關的主要參數,如下全部參數=等號後面的值均爲默認值,對歷史數據進行擬合和預測時能夠根據具體的業務狀況對這些參數進行調整。算法

趨勢項模型 g(t)
  • growth='linear' Prophet模型默認使用分段線性模型,若是使用飽和增加模型(growth='logistic'),必須給出飽和最大值cap,飽和最小值floor默認爲0
  • changepoint_prior_scale=0.05趨勢模型擬合的靈活度,值越大,靈活度越高
  • changepoint_range=0.8表示突變點(即斜率突變的點)所在的範圍,如全部的突變點是基於前80%的歷史數據的
  • n_changepoints=25表示突變點的個數,如在前80%的歷史數據中,經過等分方法找到25個變點
  • changepoints=None手動設置突變點的位置,如changepoints=['2014-01-01']
  • interval_width=0.80 設置不肯定性區間的寬度
週期項模型 s(t)
  • seasonality_prior_scale=10.0週期性模型擬合的靈活度,值越大,靈活度越高
  • yearly_seasonality='auto'表示週期性年份的傅立葉級數,當變化頻率很高時,能夠增大傅立葉級數
  • weekly_seasonality='auto'表示週期性周份指定傅立葉級數
  • daily_seasonality='auto'表示週期性日期的傅立葉級數
  • period 表示須要預測的點數
  • fourier_order表示傅立葉項數
  • prior_scale表示個別週期影響的程度
  • seasonality_mode='additive' 表示週期性模型使用的擬合模型,默認使用加法模型,可經過設置seasonality_mode='multiplicative'設置爲乘法模型
節假日項模型 h(t)
  • holidays_prior_scale=10.0表示節假日模型擬合的靈活度,值越大,靈活度越高
  • lower_window=0/ upper_window=1表示節假日影響的先後天數,注意:lower_window取值範圍爲0或負整數
  • prior_scale表示個別節假日影響的程度

Prophet模型的應用

如今有京東2015.1.1——2018.3.13的訂單量數據,以下圖,用Prophet模型對此數據集進行擬合,而且預測將來一年的訂單量。api

clipboard.png

....工具

clipboard.png

拿到一個數據集時,首先對其進行數據清洗,剔除掉數據的異常值,提升數據的質量,這樣才更有利於數據的分析。數據處理以後,大體觀察此數據集,能夠對此數據集作簡單的圖表分析,以下圖爲這三年京東的訂單量的趨勢變化。學習

clipboard.png

經過此折線圖能夠觀察到,每一年都有四個時期,訂單量出現的巨大的波動(三個波峯一個波谷)。接着,再仔細觀察某一年中這四個具體的時段,以下圖所示,網站

clipboard.png

得知,這四個時期分別對應着春節、京東618購物節、雙11、雙十二,從而能夠在擬合和預測時,增長節假日模型的成分。
以下圖爲直接利用python進行擬合做圖的結果(源碼在最後附錄):
clipboard.png
能夠看出,擬合的效果總體上仍是挺不錯的嘛 😄
若是想查看預測的各成分分析,可使用 Prophet.plot_components 方法。默認狀況下,將展現趨勢、時間序列的年度季節性和周季節性,若是包含了節假日,也會展現出來,以下圖所示:
clipboard.pngui

結束語

  1. 簡單友好。Prophet模型,只須要簡單的步驟和懂得一些重要參數的調整,就能夠獲得很好的擬合和預測,對於統計學知識不太深厚的我,非常友好了,一開始覺得要先補一下時間序列分析相關的統計學知識。不過還得感謝Facebook的大佬們開發出了這麼牛逼的算法,而且開源了出來。
  2. 參數的理解。參數對模型的結果影響是很大的,通常理解了一個模型的參數,基本上就可使用這個模型了。
  3. 何時使用?當帶有周期性和趨勢性很強的時間序列,而且能夠預先知道異常日期的場景下,Prophet模型是個不錯的分析工具。

參考文獻

  1. Prophet的官方網站
  2. Prophet的中文翻譯版的官方網站
  3. FACEBOOK 時間序列預測算法 PROPHET 的研究 ——張戎 2018.11.30
  4. Prophet的英文版論文
  5. 京東訂單量數據來源
  6. 其餘Prophet實戰例子

附錄

Prophet模型的算法在python中不是prophet,而是叫fbprophet,它在python的安裝方法,在Github上的介紹已經很詳細了:
https://github.com/facebook/p...

本文案例的python源碼

import pandas as pd
from fbprophet import Prophet
import matplotlib.pyplot as plt
%matplotlib inline
# 節假日數據

# 由於春節法定節日有一個星期,因此將春節的先後假日擴大至7天
# Spring Festival
# 春節
TF_Spring=pd.DataFrame({
    'holiday':'Spring Festival',
    'ds':pd.to_datetime(['2015-2-19','2016-2-8','2017-1-28','2018-2-16','2019-2-5']),
      'lower_window': -3,
  'upper_window': 4,
})
# E-commerce festival 618
ECF_618 = pd.DataFrame({
  'holiday': 'ECF_618',
  'ds': pd.to_datetime(['2015-6-18','2016-6-18','2017-6-18','2018-6-18']),
  'lower_window': 0,
  'upper_window': 1,
})
# E-commerce festival 1111
ECF_1111 = pd.DataFrame({
  'holiday': 'ECF_1111',
  'ds': pd.to_datetime(['2015-11-11','2016-11-11','2017-11-11','2018-11-11']),
  'lower_window': 0,
  'upper_window': 1,
})
# E-commerce festival 1212
ECF_1212 = pd.DataFrame({
  'holiday': 'ECF_1212',
  'ds': pd.to_datetime(['2015-12-12','2016-12-12','2017-12-12','2018-12-12']),
  'lower_window': 0,
  'upper_window': 1,
})
# 合併全部節假日,做爲Prophet的形參
holidays=pd.concat((TF_Spring,ECF_618,ECF_1111,ECF_1212))
# 導入數據集,用pandas庫來讀取excel數據
df=pd.read_excel('./data.xlsx')
# 轉換訂單量的數據類型
df['y']=df['y'].astype(float)
# 初始化模型,設定Prophet模型的參數
m=Prophet(holidays=holidays,holidays_prior_scale=10.0,changepoint_prior_scale=0.15,daily_seasonality=True)
# 進行擬合
m.fit(df)
# 構建待預測的日期數據,periods=365表示從歷史數據的最後一天再日後推365天
future=m.make_future_dataframe(periods=365)
future.tail()
# 預測結果
forecast=m.predict(future)
# 繪製預測結果
m.plot(forecast)
# 預測的成分分析繪圖,展現時間序列的份量
m.plot_components(forecast);
x1=forecast['ds']
y1=forecast['yhat']
plt.plot(x1,y1)
plt.show()
相關文章
相關標籤/搜索