基于Holt-Winters方法对资源进行预测

Posted _雪辉_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Holt-Winters方法对资源进行预测相关的知识,希望对你有一定的参考价值。

文章目录


  Holt-Winters方法是一种时间序列分析和预报方法。该方法对含有线性趋势和周期波动的非平稳序列适用,利用指数平滑法(EMA)让模型参数不断适应非平稳序列的变化,并对未来趋势进行短期预报。现实场景中如国家GDP历年数据,机器cpu利用率,内存数据等都是时间序列。对未来时间的观测值进行预测是有意义的工作,提前预知未来的数据的走势,可以提前做出行动,如预测cpu使用率,如果cpu飙高,可以及早进行调整,避免机器负载过高而宕机,这个在AIOPS是很常见的一个应用场景。
代码示例

# import needed packages
#-----------------------

import math
import numpy  as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn        import linear_model
from scipy.optimize import fmin_l_bfgs_b

sdata = open('data.csv')
tsA = sdata.read().split('\\n')
tsA.remove("")
tsA = list(map(int, tsA))
source_len = len(tsA)

def holtWinters(ts, p, sp, ahead, mtype, alpha = None, beta = None, gamma = None):

    a, b, s = _initValues(mtype, ts, p, sp)

    if alpha == None or beta == None or gamma == None:
        ituning   = [0.1, 0.1, 0.1]
        ibounds   = [(0,1), (0,1), (0,1)]
        optimized = fmin_l_bfgs_b(_MSD, ituning, args = (mtype, ts, p, a, b, s[:]), bounds = ibounds, approx_grad = True)
        alpha, beta, gamma = optimized[0]

    MSD, params, smoothed = _expSmooth(mtype, ts, p, a, b, s[:], alpha, beta, gamma)
    predicted = _predictValues(mtype, p, ahead, params)

    return 'alpha': alpha, 'beta': beta, 'gamma': gamma, 'MSD': MSD, 'params': params, 'smoothed': smoothed, 'predicted': predicted

def _initValues(mtype, ts, p, sp):

    initSeries = pd.Series(ts[:p*sp])
    if mtype == 'additive':
        rawSeason = initSeries - initSeries.rolling(window=p, min_periods=p, center=True).mean()
        initSeason = [np.nanmean(rawSeason[i::p]) for i in range(p)]
        initSeason = pd.Series(initSeason) - np.mean(initSeason)
        deSeasoned = [initSeries[v] - initSeason[v % p] for v in range(len(initSeries))]
    else:
        rawSeason  = initSeries / initSeries.rolling(window = p, min_periods = p, center = True).mean()
        initSeason = [np.nanmean(rawSeason[i::p]) for i in range(p)]
        initSeason = pd.Series(initSeason) / math.pow(np.prod(np.array(initSeason)), 1/p)
        deSeasoned = [initSeries[v] / initSeason[v % p] for v in range(len(initSeries))]

    lm = linear_model.LinearRegression()
    lm.fit(pd.DataFrame('time': [t+1 for t in range(len(initSeries))]), pd.Series(deSeasoned))
    return float(lm.intercept_), float(lm.coef_), list(initSeason)

def _MSD(tuning, *args):

    predicted = []
    mtype     = args[0]
    ts, p     = args[1:3]
    Lt1, Tt1  = args[3:5]
    St1       = args[5][:]
    alpha, beta, gamma = tuning[:]

    for t in range(len(ts)):

        if mtype == 'additive':
            Lt = alpha * (ts[t] - St1[t % p]) + (1 - alpha) * (Lt1 + Tt1)
            Tt = beta  * (Lt - Lt1)           + (1 - beta)  * (Tt1)
            St = gamma * (ts[t] - Lt)         + (1 - gamma) * (St1[t % p])
            predicted.append(Lt1 + Tt1 + St1[t % p])
        else:
            Lt = alpha * (ts[t] / St1[t % p]) + (1 - alpha) * (Lt1 + Tt1)
            Tt = beta  * (Lt - Lt1)           + (1 - beta)  * (Tt1)
            St = gamma * (ts[t] / Lt)         + (1 - gamma) * (St1[t % p])
            predicted.append((Lt1 + Tt1) * St1[t % p])

        Lt1, Tt1, St1[t % p] = Lt, Tt, St

    return sum([(ts[t] - predicted[t])**2 for t in range(len(predicted))])/len(predicted)

def _expSmooth(mtype, ts, p, a, b, s, alpha, beta, gamma):

    smoothed = []
    Lt1, Tt1, St1 = a, b, s[:]

    for t in range(len(ts)):

        if mtype == 'additive':
            Lt = alpha * (ts[t] - St1[t % p]) + (1 - alpha) * (Lt1 + Tt1)
            Tt = beta  * (Lt - Lt1)           + (1 - beta)  * (Tt1)
            St = gamma * (ts[t] - Lt)         + (1 - gamma) * (St1[t % p])
            smoothed.append(Lt1 + Tt1 + St1[t % p])
        else:
            Lt = alpha * (ts[t] / St1[t % p]) + (1 - alpha) * (Lt1 + Tt1)
            Tt = beta  * (Lt - Lt1)           + (1 - beta)  * (Tt1)
            St = gamma * (ts[t] / Lt)         + (1 - gamma) * (St1[t % p])
            smoothed.append((Lt1 + Tt1) * St1[t % p])

        Lt1, Tt1, St1[t % p] = Lt, Tt, St

    MSD = sum([(ts[t] - smoothed[t])**2 for t in range(len(smoothed))])/len(smoothed)
    return MSD, (Lt1, Tt1, St1), smoothed

def _predictValues(mtype, p, ahead, params):
    '''subroutine to generate predicted values @ahead periods into the future'''

    Lt, Tt, St = params
    if mtype == 'additive':
        return [Lt + (t+1)*Tt + St[t % p] for t in range(ahead)]
    else:
        return [(Lt + (t+1)*Tt) * St[t % p] for t in range(ahead)]


results = holtWinters(tsA, 12, 4, 24, mtype = 'additive')
results = holtWinters(tsA, 12, 4, 24, mtype = 'multiplicative')

print("TUNING: ", results['alpha'], results['beta'], results['gamma'], results['MSD'])
print("FINAL PARAMETERS: ", results['params'])
print("PREDICTED VALUES: ", results['predicted'])
last_len =len(results['predicted'])
x1 = range(0, source_len)
x2 = range(source_len, source_len + last_len)
y1 = tsA
y2 = results['predicted']
fig = plt.figure()
plt.plot(x1, y1, marker=r'', color=u'blue', linestyle='-', label='Initial value')
plt.plot(x2, y2, marker=r'', color=u'red', linestyle='-', label='Estimate value')
plt.xlabel('time')
plt.ylabel('value')
plt.legend(loc='best')
plt.savefig('line_plot.png', dpi=400, bbox_inches='tight')
plt.show()

以上是关于基于Holt-Winters方法对资源进行预测的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 statsmodels 库实现 Holt-Winters 方法

使用 statsmodels 进行 Holt-Winters 时间序列预测

推荐收藏基于趋势和季节性的时间序列预测实战

时间序列挖掘-预测算法-三次指数平滑法(Holt-Winters)——三次指数平滑算法可以很好的保存时间序列数据的趋势和季节性信息

Holt-Winters模型原理分析及代码实现(python)

Holt-Winters模型原理分析