应用系统负载分析与磁盘容量预测

时间:2021-09-15 08:48:20

1 背景与目标分析

根据历史磁盘数据,采用时间序列分析法,来预测应用系统服务器磁盘已经使用空间的大小;为管理员提供定制化的预警提示。
实质:时间序列—回归
应用系统负载分析与磁盘容量预测

ARMA模型介绍
AR、MA、ARMA、ARIMA

2数据特征

# -*- coding: utf-8 -*-
""" Created on Fri Jun 08 19:59:53 2018 @author: llllllllllllllllllllllllllllllllllixu """

import pandas as pd

inputfile1 = 'eeeee/chapter11/demo/data/discdata.xls'

data = pd.read_excel(inputfile1)

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif']=['SimHei']  
plt.rcParams['axes.unicode_minus']= False 

pd.to_datetime(data['COLLECTTIME'])
data1 = data[(data['ENTITY'] == 'C:\\') & (data['TARGET_ID'] == 184)]
data1.set_index('COLLECTTIME', inplace=True)
data2 = data[(data['ENTITY'] == 'D:\\') & (data['TARGET_ID'] == 184)]
data2.set_index('COLLECTTIME', inplace=True)

print data.head()
print data1.head()
print data2.head()

plt.plot(data1.index, data1['VALUE'], 'ro-')
plt.title(u"C盘已使用空间的时序图")  
plt.xlabel(u'日期')
plt.ylabel(u'磁盘使用大小') 
plt.xticks(rotation=30) 
plt.show()

plt.plot(data2.index, data2['VALUE'], 'ko-')
plt.title(u"D盘已使用空间的时序图")  
plt.xlabel(u'日期')
plt.ylabel(u'磁盘使用大小') 
plt.xticks(rotation=30) 
plt.show()

应用系统负载分析与磁盘容量预测
应用系统负载分析与磁盘容量预测应用系统负载分析与磁盘容量预测
都不具有周期性,缓慢性增长,呈现趋势性。初步确认数据是非平稳的

3数据预处理

1 数据清洗

应用系统负载分析与磁盘容量预测
一般情况下默认磁盘容量是定值,所以需要剔除磁盘容量重复的数据

data.drop_duplicates(data.columns[:-1],inplace=True) 

2属性构造

应用系统负载分析与磁盘容量预测
自己的代码构造

data5 = pd.DataFrame(index = data1.index, columns=['SYS_NAME', 'CWXT_DB:184:C:\\', 'CWXT_DB:184:D:\\', 'COLLECTTIME'])
data5['SYS_NAME'] = data1['SYS_NAME']
data5['CWXT_DB:184:C:\\'] = data1['VALUE']
data5['CWXT_DB:184:D:\\'] = data2['VALUE']
data5['COLLECTTIME'] = data1.index

应用系统负载分析与磁盘容量预测
课本的代码构造

#读取数据
data4=pd.read_excel("eeeee/chapter11/demo/data/discdata.xls")
###数据预处理
#数据清洗,删除重复值(磁盘容量)
data4=data4.drop_duplicates(['DESCRIPTION','VALUE'])
data_size=data4[data4['DESCRIPTION']==u'磁盘容量']
#磁盘容量数据行可以不要
data4=data4[data4['DESCRIPTION']!=u'磁盘容量']
data_size.to_excel("eeeee/chapter11/demo/data/llllll.xls")
#属性构造
data_group=data4.groupby('COLLECTTIME')
def attr_trans(x):
    result=pd.Series(index=['SYS_NAME','CWXT_DB:184:C:\\','CWXT_DB:184:D:\\','COLLECTTIME'])
    result['SYS_NAME']=x['SYS_NAME'].iloc[0]
    result['CWXT_DB:184:C:\\']=x['VALUE'].iloc[0]
    result['CWXT_DB:184:D:\\']=x['VALUE'].iloc[1]
    result['COLLECTTIME']=x['COLLECTTIME'].iloc[0]
    return result
data_processed=data_group.apply(attr_trans)

应用系统负载分析与磁盘容量预测
显然两个结果一样,但是自己做的好理解一点

4模型构建

容量预测模型

应用系统负载分析与磁盘容量预测

模型选择

ARMA和ARIMA的区别?
网友回答:不管是ARMA还是ARIMA模型,都是对平稳数据建模。前者是直接针对平稳数据建模,无需进行差分变换;后者则需要先对数据进行差分,差分平稳后再建模。
由于ARIMA/ARMA 模型对时间序列的要求是平稳型,因此需要进行平稳性检验。
通过自相关和偏相关图判定平稳性,并确定所用模型

如果自相关是拖尾,偏相关截尾,则用 AR 算法
如果自相关截尾,偏相关拖尾,则用 MA 算法
如果自相关和偏相关都是拖尾,则用 ARMA 算法, ARIMA 是 ARMA 算法的扩展版,用法类似

import matplotlib.pyplot as plt  
import statsmodels.api as sm  
dta = data5['CWXT_DB:184:C:\\']  
 # 原数据的的自相关图与偏自相关图 
fig = plt.figure(figsize=(12,12))  
ax1=fig.add_subplot(411)# 自相关图 
fig = sm.graphics.tsa.plot_acf(dta,lags=40,ax=ax1)  
ax1.set_title(u'原始数据的自相关图')  

ax2 = fig.add_subplot(412)# 篇自相关图 
fig = sm.graphics.tsa.plot_pacf(dta,lags=40,ax=ax2)  
ax2.set_title(u'原始数据的偏相关图')  

# 一阶差分后的自相关图与偏自相关图 
dta= dta.diff(1).dropna() # 注意一定要将查分后的空值去掉再取自相关系数 
ax3=fig.add_subplot(413)# 自相关图 
fig = sm.graphics.tsa.plot_acf(dta,lags=40,ax=ax3)  
ax3.set_title(u'一阶差分后的自相关图')  

ax4 = fig.add_subplot(414)# 篇自相关图 
fig = sm.graphics.tsa.plot_pacf(dta,lags=40,ax=ax4)  
ax4.set_title(u'一阶差分后的偏相关图')  
plt.savefig('acf_pacf.jpg')  
plt.show()  

应用系统负载分析与磁盘容量预测

通过自相关图可以发现,该图自相关和偏相关都是拖尾,因此,确定是ARMA算法、ARIMA均可

平稳性检验

单位根检验ADF

p值小于0.05是稳定的

def stationarity_test(dataset,number):
  data = dataset.copy()
  data = data.iloc[: len(data)-number] #不检测最后number个数据
  #平稳性检测
  from statsmodels.tsa.stattools import adfuller as ADF
  diff = 0
  adf = ADF(data['CWXT_DB:184:D:\\'])
  while adf[1] >=0.05:
    diff = diff + 1
    adf = ADF(data['CWXT_DB:184:D:\\'].diff(diff).dropna())
  print adf
  print(u'原始序列经过%s阶差分后归于平稳,p值为%s' %(diff, adf[1]))

stationarity_test(data5, 5)

adf = (-5.446582568218853, 2.702061091530201e-06, 5, 40, {‘5%’: -2.937069375, ‘1%’: -3.6055648906249997, ‘10%’: -2.606985625}, 1080.1708857378069)
原始序列经过1阶差分后归于平稳,p值为2.702061091530201e-06

自相关图、偏自相关图

已给出

时间序列图法

已给出

白噪声检验

目的:验证序列中有用信息是否已经被提取完毕,需要进行白噪声检验。若序列是白噪声序列,说明序列中有用信息已经被提取完,只剩随机扰动
方法:采用LB统计量的方法进行白噪声检验
若没有通过白噪声检验,则需要进行模型识别,识别其模型属于AR、MA还是ARMA。
p值小于0.05是非白噪声

data1 = data5.iloc[:len(data5)-5]# 不使用最后五个数据(作为预测参考) 

from statsmodels.stats.diagnostic import acorr_ljungbox  

[[lb], [p]] = acorr_ljungbox(data1['CWXT_DB:184:C:\\'], lags = 1) ## lags是残差延迟个数 
if p < 0.05:  
    print (u'原始序列为非白噪声序列,对应的p值为:%s' % p)  
else:  
    print (u'原始序列为白噪声序列,对应的p值为:%s' % p)  

[[lb], [p]] = acorr_ljungbox(data1['CWXT_DB:184:C:\\'].diff(1).dropna(), lags = 1)  
if p < 0.05:  
    print (u'一阶差分序列为非白噪声序列,对应的p值为:%s' % p)  
else:  
    print (u'一阶差分序列为白噪声序列,对应的p值为:%s' % p) 

原始序列为非白噪声序列,对应的p值为:1.0609907508070775e-08
一阶差分序列为白噪声序列,对应的p值为:0.4745522552554281

模型识别

step1:采用极大似然比方法进行模型的参数估计,估计各个参数的值。
step2:然后针对各个不同模型,采用信息准则方法(有三种:BIC/AIC/HQ)对模型进行定阶,确定p,q参数,从而选择最优模型。
目前选择模型常用如下准则!!!!!
增加*参数的数目提高了拟合的优良性,AIC/BIC/HQ鼓励数据拟合的优良性但是尽量避免出现过度拟合(Overfitting)的情况。所以优先考虑的模型应是AIC/BIC/HQ值最小的那一个
* AIC = -2 ln(L) + 2 k 中文名字:赤池信息量 akaike information criterion (AIC)
* BIC = -2 ln(L) + ln(n)*k 中文名字:贝叶斯信息量 bayesian information criterion (BIC)
* HQ = -2 ln(L) + ln(ln(n))*k hannan-quinn criterion (HQ)
step3:注意,进行此步时,index需要为时间序列类型
step4:确定最佳p、d、q的值

#模型识别
#确定最佳p,d,q值
data6 = pd.read_excel('eeeee/chapter11/demo/data/discdata_processed.xls', index_col='COLLECTTIME')
data6 = data6.iloc[:len(data6)-5]# 不使用最后五个数据(作为预测参考) 
xdata=data6['CWXT_DB:184:D:\\']
from statsmodels.tsa.arima_model import ARIMA
#定阶
pmax = int(len(xdata)/10) #一般阶数不超过length/10
qmax = int(len(xdata)/10) #一般阶数不超过length/10
bic_matrix = [] #bic矩阵
for p in range(pmax+1):
    tmp = []
    for q in range(qmax+1):
        try: #存在部分报错,所以用try来跳过报错。
            tmp.append(ARIMA(xdata, (p,1,q)).fit().bic)
        except:
            tmp.append(None)
    bic_matrix.append(tmp)

bic_matrix = pd.DataFrame(bic_matrix) #从中可以找出最小值

p,q = bic_matrix.stack().astype('float64').idxmin() #先用stack展平,然后用idxmin找出最小值位置。
print (u'BIC最小的p值和q值为:%s、%s' %(p,q))
#(1,1)

########################################AIC###########################################

data66 = pd.read_excel('eeeee/chapter11/demo/data/discdata_processed.xls',index_col='COLLECTTIME')  
data66 = data66.iloc[:len(data66)-5]# 不使用最后五个数据(作为预测参考) 
xdata1 = data66['CWXT_DB:184:D:\\']  
# ARIMA(p,d,q)中,AR是自回归,p为自回归项数;MA为滑动平均,q为滑动平均项数,d为使之成为平稳序列所做的差分次数(阶数),由前一步骤知d=1 
# from statsmodels.tsa.arima_model import ARIMA#建立ARIMA(p,d,q)模型 
from statsmodels.tsa.arima_model import ARMA #建立ARMA(p,q)模型 

# AIC方式定信息准则 + ARMA --------!!!模型检验中也要对应修改!!!------------------------------ 

pmax = int(len(xdata1)/10) # 一般阶数不超过length/10 
qmax = int(len(xdata1)/10) # 一般阶数不超过length/10 

matrix = [] # aic矩阵 
for p in range(pmax+1):  
    tmp1 = []  
    for q in range(qmax+1):  
        try:#存在部分为空值,会报错 
# tmp.append(ARMA(xdata2, (p,q)).fit().bic) # BIC方式 
            tmp1.append(ARMA(xdata1, (p,q)).fit().aic) # AIC方式 
# tmp.append(ARMA(xdata2, (p,q)).fit().hq) # HQ方式 
        except:  
            tmp1.append(None)  

    matrix.append(tmp1)  

matrix = pd.DataFrame(matrix) # 从中可以找出最小值 
p,q = matrix.stack().astype('float64').idxmin() #先用stack展平,然后用idxmin找出最小值位置。
print (u'AIC最小的p值和q值为:%s、%s' %(p,q))
#(1,0)

BIC、AIC输出的p、q不同

模型检验

确定模型后,需要检验其残差序列是否是白噪声,若不是,说明,残差中还存在有用的信息,需要修改模型或者进一步提取。若其残差不是白噪声,重新更换p,q的值,重新确定

lagnum=12#残差延迟个数
from statsmodels.tsa.arima_model import ARIMA #建立ARIMA(p,1,q)模型

arima = ARIMA(xdata, (p, 1, q)).fit() #建立并训练模型
xdata_pred = arima.predict(typ = 'levels') #预测
pred_error = (xdata_pred - xdata).dropna() #计算残差

from statsmodels.stats.diagnostic import acorr_ljungbox #白噪声检验

lb, p_l= acorr_ljungbox(pred_error, lags = lagnum)
h = (p_l < 0.05).sum() #p值小于0.05,认为是非白噪声。
if h > 0:
    print (u'模型ARIMA(%s,1,%s)不符合白噪声检验'%(p,q))
else:
    print (u'模型ARIMA(%s,1,%s)符合白噪声检验' %(p,q))

模型ARIMA(1,1,1)符合白噪声检验

模型预测

#模型预测
test_predict=arima.forecast(5)[0]
print (test_predict)
#预测对比
test_data=pd.DataFrame(columns=[u'实际容量',u'预测容量'])
test_data[u'实际容量']=data6[(len(data6)-5):]['CWXT_DB:184:D:\\']
test_data[u'预测容量']=test_predict
test_data = test_data.applymap(lambda x: '%.2f' % x)

应用系统负载分析与磁盘容量预测

模型评价

为了评价时序预测模型效果的好坏,本章采用3个衡量模型预测精度的统计量指标:平均绝对误差、均方根误差、平均绝对百分误差

# 计算误差 
abs_ = (test_data[u'预测容量']-test_data[u'实际容量']).abs()/10**6
mae_ = abs_.mean() # mae平均绝对误差 
rmas_ = ((abs_**2).mean())**0.5 #rmas均方根误差 
mape_ = (abs_/test_data[u'实际容量']).mean()/10**6 #mape平均绝对百分误差 
print abs_  
print mae_  
print rmas_  
print mape_  
errors = 1.5  
print '误差阈值为%s' % errors  
if (mae_ < errors) & (rmas_ < errors) & (mape_ < errors):  
    print (u'平均绝对误差为:%.4f, \n均方根误差为:%.4f, \n平均绝对百分误差为:%.4f' % (mae_, rmas_, mape_))  
    print '误差检验通过!'  
else:  
    print '误差检验不通过!' 

COLLECTTIME
2014-11-07 2.109774
2014-11-08 0.805807
2014-11-09 0.783027
2014-11-10 0.640073
2014-11-11 0.207209
dtype: float64
0.909178019868
1.11051631577
1.04800949023e-14
误差阈值为1.5
平均绝对误差为:0.9092,
均方根误差为:1.1105,
平均绝对百分误差为:0.0000
误差检验通过!

可视化

import matplotlib.pyplot as plt  
import matplotlib.dates as mdates  
plt.rcParams['font.sans-serif']=['SimHei']  
plt.rcParams['axes.unicode_minus']= False  
df = data5[:len(data5)-5] 
fig  = plt.figure()  
fig.set(alpha=0.2)
ax = fig.add_subplot(1,1,1)  
ax.set_title(u"D盘空间时序预测图")  
ax.set(xlabel=u'日期',ylabel=u'磁盘使用大小')  
ax.xaxis.set_major_locator(mdates.DayLocator(bymonthday=range(1,32), interval=7))   
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))  
plt.subplots_adjust(bottom=0.13,top=0.95)  
ax.plot(df['COLLECTTIME'],df['CWXT_DB:184:D:\\'],'ro--',)  
ax.plot(test_data.index,test_data[u'实际容量'],'g+--',)  
ax.plot(test_data.index,test_data[u'预测容量'],'b*-',)  
ax.grid(axis='y',linestyle='--')  
ax.legend()  
fig.autofmt_xdate() 
plt.show()  

应用系统负载分析与磁盘容量预测

参考1
参考2