Python 時間序列預(yù)測:Hot-winters

1. 什么是Holt-Winters
時間序列是非常常見的數(shù)據(jù)格式,以[時間,觀測值]形式表現(xiàn),如下圖。

現(xiàn)實場景中如股票走勢圖,國家GDP歷年數(shù)據(jù),機(jī)器cpu利用率,內(nèi)存數(shù)據(jù)等都是時間序列。對未來時間的觀測值進(jìn)行預(yù)測是有意義的工作,提前預(yù)知未來的數(shù)據(jù)的走勢,可以提前做出行動,如預(yù)測cpu使用率,如果cpu飆高,可以及早進(jìn)行調(diào)整,避免機(jī)器負(fù)載過高而宕機(jī),這個在AIOPS是很常見的一個應(yīng)用場景。
今天要說到Holt-Winters是利用三次指數(shù)平滑來做時間序列預(yù)測的方法。Holt-Winters是綜合了1957年Holt和1960年Winters兩個人的思路的一種方法。
一次指數(shù)平滑
我們來看下,一次指數(shù)平滑如下圖:

可知,si表示第i時刻的平滑估計,si可以表示為當(dāng)前實際值xi和上一時刻平滑估計值得加權(quán)組合,權(quán)重由alpha來決定。那為什么稱為指數(shù)平滑呢?我們來把式子展開,如下:

有點類似泰勒展開式的味道

alpha 屬于[0, 1], 越大表示近期的數(shù)據(jù)影響更大
二次指數(shù)平滑:加上趨勢的因素
一次指數(shù)平滑,沒有考慮時間序列的趨勢和季節(jié)性,二次指數(shù)平滑加上趨勢因素。

從公式可知,一個時間序列的時刻值分解為baseline部分和趨勢部分,t表示趨勢,可以表示為連續(xù)兩個時刻的差值;可知,ti也是一次的指數(shù)平滑。
Holt-Winters三次指數(shù)平滑:加上季節(jié)性因素
在二次指數(shù)平滑基礎(chǔ)上,考慮季節(jié)性因素,就是三次指數(shù)平滑,也就是Holt-Winters。由此,一個時間序列的時刻值分解為baseline部分和趨勢部分以及季節(jié)部分。由于季節(jié)性,存在周期,比如按周,按月等。pi季節(jié)性為當(dāng)前季節(jié)性值和上一個周期季節(jié)性估計值的加權(quán)組合,周期在公式中以k來表示。如下:

2. Holt-Winters的實現(xiàn)
從第一部分可知,要實現(xiàn)Holt-Winters,只要知道:
?初始值:s0,t0和p0?合適的參數(shù):alpha,beta, gamma?套入公式即可完成預(yù)測
三個重要參數(shù):alpha,beta, gamma都屬于[0, 1]之間,要么人為的搜索,要么通過數(shù)據(jù)來估計,通常采用L-BFGS優(yōu)化算法來擬合數(shù)據(jù)。優(yōu)化算法來自包scipy.optimize的fmin_l_bfgs_b。
from __future__ import divisionfrom sys importexitfrom math import sqrtfrom numpy import arrayfrom scipy.optimize import fmin_l_bfgs_b# 優(yōu)化算法的loss function,即判斷擬合效果,由RMSE MAE等def RMSE(params, *args):Y = args[0]type = args[1]rmse = 0alpha, beta, gamma = paramsm = args[2]a = [sum(Y[0:m]) / float(m)]b = [(sum(Y[m:2* m]) - sum(Y[0:m])) / m ** 2]if type == 'additive':s = [Y[i] - a[0] for i in range(m)]y = [a[0] + b[0] + s[0]]for i in range(len(Y)):a.append(alpha * (Y[i] - s[i]) + (1- alpha) * (a[i] + b[i]))b.append(beta * (a[i + 1] - a[i]) + (1- beta) * b[i])s.append(gamma * (Y[i] - a[i] - b[i]) + (1- gamma) * s[i])y.append(a[i + 1] + b[i + 1] + s[i + 1])rmse = sqrt(sum([(m - n) ** 2for m, n in zip(Y, y[:-1])]) / len(Y))return rmse# 加性的時間序列def additive(x, m, fc, alpha = None, beta = None, gamma = None):Y = x[:]# 利用fmin_l_bfgs_b來估計參數(shù)alpha beta和gammaif(alpha == Noneor beta == Noneor gamma == None):initial_values = array([0.3, 0.1, 0.1])boundaries = [(0, 1), (0, 1), (0, 1)]type = 'additive'parameters = fmin_l_bfgs_b(RMSE, x0 = initial_values, args = (Y, type, m), bounds = boundaries, approx_grad = True)alpha, beta, gamma = parameters[0]# 初始值 a表示baseline, b表示趨勢,s表示季節(jié)性,y表示預(yù)測值, 分別取第一個周期的統(tǒng)計數(shù)據(jù)為初始值a = [sum(Y[0:m]) / float(m)]b = [(sum(Y[m:2* m]) - sum(Y[0:m])) / m ** 2]s = [Y[i] - a[0] for i in range(m)]y = [a[0] + b[0] + s[0]]rmse = 0# 套用上面公式,從0開始,fc表示預(yù)測的數(shù)量,如已知前7天,預(yù)測接下來的一個小時的數(shù)據(jù),如果數(shù)據(jù)粒度是5分鐘,fc為12。for i in range(len(Y) + fc):if i == len(Y):# 預(yù)測值為Y.append(a[-1] + b[-1] + s[-m])a.append(alpha * (Y[i] - s[i]) + (1- alpha) * (a[i] + b[i]))b.append(beta * (a[i + 1] - a[i]) + (1- beta) * b[i])s.append(gamma * (Y[i] - a[i] - b[i]) + (1- gamma) * s[i])y.append(a[i + 1] + b[i + 1] + s[i + 1])# 計算rmse值rmse = sqrt(sum([(m - n) ** 2for m, n in zip(Y[:-fc], y[:-fc - 1])]) / len(Y[:-fc]))return y[-fc:], alpha, beta, gamma, rmse
另外,statsmodels包中也提供的實現(xiàn)的方法
from statsmodels.tsa.holtwinters importExponentialSmoothing3. Holt-Winters參數(shù)
從上面實現(xiàn)可知,holt-winters通過預(yù)估alpha,beta和gamma來預(yù)測。算法的關(guān)鍵就是這三個參數(shù)和初始化值。三個參數(shù)可以通過優(yōu)化算法來預(yù)估,但有可能并不是最優(yōu)的。初始值的設(shè)置除了上面統(tǒng)計值外,還可以通過時序的分解的趨勢和季節(jié)部分來初始。
import numpy as npfrom pandas import read_csvimport matplotlib.pyplot as pltfrom statsmodels.tsa.seasonal import seasonal_decomposedecomposition = seasonal_decompose(df_clean.bw, model='additive', period=288)decomposition.plot()

Holt-Winters針對波形比較穩(wěn)定,沒有突刺的情況下,效果會比較好。

對于存在突刺,統(tǒng)一的alpha,beta,gamma不能很好擬合,預(yù)測可能會滯后。
4. 總結(jié)
本文分享了時間序列預(yù)測算法Holt-Winters以及重要參數(shù)的選擇,希望對你有幫助??偨Y(jié)如下:
?Holt-Winters是三次指數(shù)平滑,分別為baseline,趨勢和季節(jié)性;?alpha、beta和gamma分別為baseline,趨勢和季節(jié)性的指數(shù)加權(quán)參數(shù),一般通過優(yōu)化算法L-BFGS估計?初始化可通過平均值,也可通過時間序列分解得到?周期m或者k的選擇要根據(jù)實際數(shù)據(jù)來選擇?Holt-Winters針對波形比較穩(wěn)定,沒有突刺的情況下,效果會比較好
作者簡介:wedo實驗君, 數(shù)據(jù)分析師;熱愛生活,熱愛寫作
贊 賞 作 者





點擊下方閱讀原文加入社區(qū)會員
