宋 楠,劉際鑫,李 林,仇道霞
(山東省煙草專賣局(公司),山東 濟南 250101)
通過分析多個地市的卷煙銷量數(shù)量發(fā)現(xiàn),卷煙的銷量存在季節(jié)性的變化規(guī)律,卷煙銷量和卷煙銷量增長率在時間序列上存在著一段周期的與下一個周期的關(guān)聯(lián)。
Holt和Winters將Holt方法進行拓展用來捕獲季節(jié)因素。Holt-Winters季節(jié)性方法包括預(yù)測方程和三個平滑方程:一個用于水平lt,一個用于趨勢bt,另一個用于季節(jié)性分量st,相應(yīng)的平滑參數(shù)分別為2α β和γ。我們用m來表示季節(jié)頻率,即一年中包含的季節(jié)數(shù)。例如,季度數(shù)據(jù)的m=4,月度數(shù)據(jù)的m=12這種方法有兩種不同的季節(jié)性組成部分。當(dāng)季節(jié)變化在該時間序列中大致保持不變時,通常選擇加法模型;而當(dāng)季節(jié)變化與時間序列的水平成比例變化時,通常選擇乘法模型。
在加法模型中,季節(jié)性分量在觀測序列的尺度上以絕對值表示,在水平方程中,時間序列通過減去季節(jié)分量進行季節(jié)性調(diào)整,并且每年的季節(jié)性分量加起來大約為零。在乘法模型中,季節(jié)性分量用相對數(shù)(百分比)表示,時間序列通過除以季節(jié)性分量來進行季節(jié)性調(diào)整,并且每年的季節(jié)性分量加起來約為m。
加法模型的分量形式為:
水平方程表示在 t時刻,季節(jié)性調(diào)整的觀察值 (yt - st-m)與非季節(jié)性預(yù)測值 ( lt-1+ bt-1)之間的加權(quán)平均值。趨勢方程與Holt線性方法相同。季節(jié)性方程表示當(dāng)前季節(jié)性指數(shù), ( yt- lt-1- bt-1),和去年同一季節(jié)(即m個時間段前)的季節(jié)性指數(shù)之間的加權(quán)平均值。季節(jié)性分量的方程通常表示為:
如果用平滑方程中的lt代替上述分量形式中的水平,可以得到:
2.1 兩組女性血清中AsAb抗體水平檢測結(jié)果比較 在AsAb-T檢測水平方面,不孕不育組總陽性率(65.8%)與健康對照組總陽性率(5.4%)相比明顯提高(P<0.05);其中不孕不育組女性血清IgG-AsAb、IgM- AsAb、IgA- AsAb的總陽性率均明顯高于健康對照組(均P<0.05)。見表1。
與規(guī)定的季節(jié)性分量的平滑方程相同,其中γ = γ*( 1 - α )。通常的參數(shù)限制是 0 ≤ γ*≤ 1,將其轉(zhuǎn)換為0 ≤ γ ≤ 1 -α。
乘法模型的分量形式為:
以一個卷煙單品為例,從日銷量圖可以看出,單品的每日銷量有周期性的規(guī)律,日銷量數(shù)據(jù)也可以保持一段時間的趨勢性。holt-winters算法主要考慮的是趨勢性和周期性,因此可以使用holt-winters算法對單品的銷量數(shù)據(jù)進行推斷。但是我們從日銷量圖中也可以看出,銷量數(shù)據(jù)也會出現(xiàn)較大的波動,這些波動很難捕捉到,而且會對基于holt-winters的銷量推斷產(chǎn)生影響,由于這些銷量數(shù)據(jù)是真實的,不是由于數(shù)據(jù)填充錯誤導(dǎo)致的,因此后面我們引入prophet算法。
圖1 卷煙銷量波動圖Fig.1 Fluctuation chart of cigarette sales
prophet算法模型不僅可以處理時間序列存在一些異常值的情況,也可以處理部分缺失值的情形,還能夠幾乎全自動地預(yù)測時間序列未來的走勢。prophet算法模型是基于時間序列分解和機器學(xué)習(xí)的擬合來做的,其中在擬合模型的時候使用了pyStan這個開源工具,因此能夠在較快的時間內(nèi)得到需要預(yù)測的結(jié)果。使用prophet模型可以構(gòu)建趨勢項模型、構(gòu)建季節(jié)性趨勢、對節(jié)假日效應(yīng)進行預(yù)估。
在Prophet算法里面,趨勢項有兩個重要的函數(shù),一個是基于邏輯回歸函數(shù)(logistic function)的,另一個是基于分段線性函數(shù)(piecewise linear function)的。
如果回顧邏輯回歸函數(shù)的話,一般都會想起這樣的形式:
式(6)中C稱為曲線的最大漸近值,k表示曲線的增長率,m表示曲線的中點。當(dāng)C=1,k=1,m=0時,恰好是常見的 sigmoid函數(shù)的形式。從sigmoid的函數(shù)表達式來看,它滿足的微分方程為:
那么,使用分離變量法來求解微分方程y′=y(1-y),可以得到:
在Prophet里面,是需要設(shè)置變點的位置的,而每一段的趨勢和走勢也是會根據(jù)變點的情況而改變的。在程序里面有兩種方法,一種是通過人工指定的方式指定變點的位置;另外一種是通過算法來自動選擇。在默認的函數(shù)里面,Prophet 會選擇n_changepoints = 25個變點,然后設(shè)置變點的范圍是前80%(changepoint_range),也就是在時間序列的前 80%的區(qū)間內(nèi)會設(shè)置變點。通過forecaster.py里面的set_changepoints函數(shù)可以知道,首先要看一些邊界條件是否合理,例如時間序列的點數(shù)是否少于n_changepoints 等內(nèi)容;其次如果邊界條件符合,那變點的位置就是均勻分布的,這一點可以通過np.linspace這個函數(shù)看出來。
假設(shè)已經(jīng)放置了S個變點了,并且變點的位置是在時間戳 sj,1≤j≤s上,那么在這些時間戳上,需要給出增長率的變化,也就是在時間戳sj上發(fā)生的 change in rate。可以假設(shè)有這樣一個向量: δ ∈Rs,其中δj表示在時間戳sj上的增長率的變化量。如果一開始的增長率使用k來代替,則在時間戳t上的增長率是:
以實際的煙草銷量數(shù)據(jù)為例,通過銷量數(shù)據(jù)可以得出,銷量數(shù)據(jù)是存在分段線性銷量趨勢的,因此可以通過設(shè)置趨勢來捕獲銷量的走勢。
圖2 卷煙銷量趨勢項模型分析圖Fig.2 Analysis diagram of cigarette sales trend item model
幾乎所有的時間序列預(yù)測模型都會考慮這個因素,因為時間序列通常會隨著天,周,月,年等季節(jié)性的變化而呈現(xiàn)季節(jié)性的變化,也稱為周期性的變化。卷煙的銷售同樣會受季節(jié)的影響。對于周期函數(shù)而言,大家能夠馬上聯(lián)想到的就是正弦余弦函數(shù)。而在數(shù)學(xué)分析中,區(qū)間內(nèi)的周期性函數(shù)是可以通過正弦和余弦的函數(shù)來表示的:假設(shè)f(x)是以2π為周期的函數(shù),那么它的傅立葉級數(shù)為:
使用傅立葉級數(shù)來模擬時間序列的周期性。假設(shè) P表示時間序列的周期,p=365.25,表示以年為周期,p=7,表示以周為周期。它的傅立葉級數(shù)的形式為:
對于以年為周期的序列(P=365.25)而言,N=10;對于以周為周期的序列(p=7)而言,N=3。參數(shù)可以形成列向量:
我們以一個單品為例,拆分prophet模型的趨勢項與周期項得到如下圖所示,改單品整體的銷量為下降趨勢,有周期性的銷量波動。
圖3 卷煙銷量季節(jié)性趨勢分析圖Fig.3 Seasonal trend analysis of cigarette sales
通過對時間序列的深度分析,我們發(fā)現(xiàn)卷煙的銷量除了季節(jié)性的變化趨勢外,還會受節(jié)假日的影響,如春節(jié)、中秋等節(jié)假日會使卷煙的銷量發(fā)生比較大的波動,所以我們又結(jié)合節(jié)假日的特征對模型進行了進一步訓(xùn)練。
在 Prophet算法模型里面,通過對節(jié)假日的特征分析,訓(xùn)練得到節(jié)假日對卷煙銷售的影響和關(guān)系。由于每個節(jié)假日對時間序列的影響程度不同,例如春節(jié)、國慶節(jié)是七天的假期,勞動節(jié)等假期則較短。因此,不同的節(jié)假日可以看成相互獨立的模型,并且可以為不同的節(jié)假日設(shè)置不同的前后窗口值,表示該節(jié)假日會影響前后一段時間的時間序列。用數(shù)學(xué)語言來說,對于第 i個節(jié)假日來說,Di表示該節(jié)假日的前后一段時間。為了表示節(jié)假日效應(yīng),需要一個相應(yīng)的指示函數(shù)(indicator function),同時需要一個參數(shù)ki來表示節(jié)假日的影響范圍。假設(shè)有L個節(jié)假日,那么:
按照以上的解釋,時間序列已經(jīng)可以通過增長項、季節(jié)項、節(jié)假日項來構(gòu)建:
下一步則需要擬合函數(shù),以下以30天卷煙銷量預(yù)測為例。
根據(jù)卷煙日銷量數(shù)據(jù)匯聚成 30天的銷量數(shù)據(jù),當(dāng)前的銷量為30天的歷史銷量的總和,使用prophet算法的預(yù)測共得到三條銷量的曲線,最上面一條為銷量預(yù)測的上界即最大的銷量,中間一條曲線為預(yù)測的銷量,最下面一條曲線為銷量預(yù)測的下界,散點為實際的銷量,通過圖4可以看出,雖然30天總的銷量相比于日銷量來說數(shù)據(jù)的分布更穩(wěn)定,但是依然會數(shù)據(jù)波動非常大,而且只用銷量的數(shù)據(jù),算法在預(yù)測結(jié)果的穩(wěn)定性方面沒有考慮更多的因素,因此引入機器學(xué)習(xí)與時間序列模型融合的方法,在機器學(xué)習(xí)特征設(shè)計的時候使用了時間序列預(yù)測的特征,同時加入了非時間序列的特征。
圖4 卷煙銷量模型擬合分析圖Fig.4 Fitting analysis diagram of cigarette sales model
XGBoost是 boosting算法的其中一種。Boosting算法的思想是將許多弱分類器集成在一起形成一個強分類器。因為XGBoost是一種提升樹模型,所以它是將許多樹模型集成在一起,形成一個很強的分類器,而所用到的樹模型則是CART回歸樹模型。該算法思想就是不斷地添加樹,不斷地進行特征分裂來生長一棵樹,每次添加一個樹,其實是學(xué)習(xí)一個新函數(shù),去擬合上次預(yù)測的殘差。當(dāng)訓(xùn)練完成得到k棵樹,則需預(yù)測一個樣本的分?jǐn)?shù),根據(jù)樣本的特征,在每棵樹中會落到對應(yīng)的一個葉子節(jié)點,每個葉子節(jié)點就對應(yīng)一個分?jǐn)?shù),最后只需要將每棵樹對應(yīng)的分?jǐn)?shù)加起來就是該樣本的預(yù)測值:
式(21)中,wq(x)為葉子節(jié)點的分?jǐn)?shù),f(x)為其中一棵回歸樹。
由于時間序列預(yù)測銷量只能使用歷史的銷量數(shù)據(jù),不能使用其它數(shù)據(jù),因此我們采用時間序列模型與機器學(xué)習(xí)模型融合的方法,模型的設(shè)計既使用來時間序列銷量特征,又考慮了用戶特征等非時間序列銷量特征。prophet和 holt-winters時間序列方法作為 xgboost預(yù)測的高級特征,目標(biāo)預(yù)測不是直接預(yù)測未來的銷量,而是預(yù)測未來的增長率,這樣目標(biāo)變量的波動范圍會小,而且更穩(wěn)定。通過增長率與當(dāng)前30天歷史的銷量就可以計算出未來的 30天銷量,7天銷量的方法是一致的,只是特征構(gòu)建不同。
圖5 卷煙銷量預(yù)測流程圖Fig.5 Flow chart of cigarette sales forecast
表1 30天銷量預(yù)測的特征表Tab.1 Feature table for 30-day sales forecast
表2 7天銷量的預(yù)測特征表Tab.2 7-day sales forecast feature table
使用2017年1月1日到2020年7月1日,某省三個地市的六種規(guī)格的卷煙銷量數(shù)據(jù),根據(jù)MAPE進行驗證銷量預(yù)測的準(zhǔn)確率,結(jié)果如表3。
表3 卷煙銷量預(yù)測表Tab.3 Cigarette sales forecast table
6901028315012規(guī)格編號的卷煙在使用 2020年5月29號之前的歷史數(shù)據(jù)預(yù)測2020年5月30號到6月28號周期30天的銷量數(shù)據(jù)時,從銷量數(shù)據(jù)來看,5月30號到6月28號的銷量數(shù)據(jù)忽然下降很多,導(dǎo)致預(yù)測結(jié)果有一定的偏差, 與銷售部門確認其原因是貨源不足等因素干擾。
圖6 卷煙銷量異常波動圖Fig.6 Abnormal fluctuations in cigarette sales
為科學(xué)的制定市級煙草商業(yè)企業(yè)的卷煙投放策略,采用基于prophet、Holt-Winters和xgboost模型構(gòu)成的混合模型,對基于地市鄉(xiāng)鎮(zhèn)為單位的銷量前十的單品卷煙銷量進行預(yù)測,提高了單品卷煙預(yù)測的精確度,在卷煙單品銷量預(yù)測中取得了較好的結(jié)果,但文中的混合模型僅以歷史銷售數(shù)據(jù)為輸入,相關(guān)結(jié)論在數(shù)據(jù)存在政策因素影響時并不適用。