完整代码和分析

实验介绍

实验背景

大型企业都会有自己的办公自动化系统,应用系统在日常运行时,会对底层软、硬件造成负荷,显著影响应用系统性能。底层任何一种资源负载过大,都可能会引起应用系统性能下降甚至瘫痪。因此需要关注服务器、数据库、中间件和存储设备的运行状态,及时了解当前应用系统的负载情况,以便提前预防,确保系统安全稳定运行。

实验目的

  • 针对历史磁盘数据,采用时间序列分析方法,预测应用系统服务器磁盘已使用空间大小。

  • 根据用户需求设置不同的预警等级,将预测值与容量值进行比较,对其结果进行预警判断,为系统管理员提供定制化的预警提示。

分析方法与过程

由于存储空间随时间变化存在很强的关联性,且历史数据对未来的发展存在一定的影响。故本实验采用时间序列分析法对磁盘已使用空间进行预测分析。

模型介绍

本次实验我们将使用时间序列分析法来数据进行构造。
首先来认识一下ARIMA模型。ARIMA,差分自回归滑动平均模型,又称求合自回归滑动平均模型。是时间序列预测分析方法之一。
ARIMA(p,d,q)中,AR是“自回归”,p为自回归项数;MA是“滑动平均”,q为滑动平均项数,d是使之成为平稳序列所做的差分次数(阶数)。

ARIMA模型运用的流程:
- 根据时间序列的散点图、自相关函数和偏自相关函数图识别其平稳性。
- 对非平稳的时间序列数据进行平稳化处理。直到处理后的自相关函数和偏自相关函数的数值非显著非零。
- 根据所识别出来的特征建立相应的时间序列模型。平稳化处理后,若偏自相关函数是截尾的,而自相关函数是拖尾的,则建立AR模型;若偏自相关函数是拖尾的,而自相关函数是截尾的,则建立MA模型;若偏自相关函数和自相关函数均是拖尾的,则序列适合ARMA模型。
- 利用已通过检验的模型进行预测。

那么,如何识别时间序列的平稳性?

平稳性检验

识别序列是否平稳,一般有三种方法:看图法、自相关系数和偏相关系数、单位根检验(ADF)。

我们先来简单介绍一下看图法:

看图法
应用系统负载分析与磁盘容量预测-LMLPHP

这里的“图”指的是时序图,即某指随时间变化的时序图。平稳序列的图a是围绕一个常数上下波动。而不平稳的图b,则是用明显的增长或减少的趋势。

自相关系数和偏相关系数

这里会涉及到两个定义——截尾和拖尾。

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

平稳序列的自相关图和偏相关图要么都是拖尾要么都是截尾。截尾就是在某阶之后,系数都为 0 ,怎么理解呢,看上面偏相关的图,当阶数为 1 的时候,系数值还是很大, 0.914. 二阶长的时候突然就变成了 0.050. 后面的值都很小,认为是趋于 0 ,这种状况就是截尾。再就是拖尾,拖尾就是有一个衰减的趋势,但是不都为 0 。自相关图既不是拖尾也不是截尾。以上的图的自相关是一个三角对称的形式,这种趋势是单调趋势的典型图形。

c. 单位根检验(ADF)
若单位根检验p值小于0.05则认为是平稳的。

对于不平稳的序列又该如何处理呢?
2. 差分处理
差分即取相邻项值差替代当前值,以此来消除一些波动,使数据趋于平稳。

数据抽取

为了抽取出磁盘数据,以属性的标识号(TARGET_ID)与采集指标的时间(COLLECTTIME)为条件,对性能数据进行抽取。本实验抽取2014-10-1至2014-11-16财务管理系统中某一台数据库服务器的磁盘的相关数据。
应用系统负载分析与磁盘容量预测-LMLPHP

数据探索分析

本实验采用时序分析法来进行建模。为了建模的需要,需要探索数据的平稳性。

通过时序图可以初步发现数据的平稳性。针对服务器磁盘的使用大小,以天为单位,进行周期性分析。

新建文件,添加如下代码:

import pandas as pd

dataPath = './data/discdata.xls'
data = pd.read_excel(dataPath,encoding='utf-8')

#绘制C、D盘的使用情况时序图
import matplotlib.pyplot as plt
import matplotlib

#配置matplotlib参数
#坐标轴字体
matplotlib.rc('font', **{'family': 'serif', 'serif': ['SimHei']})
#plt.rcParams['front.sans-serif'] = ['SimHei']
#坐标轴负号
#plt.rcParams['axes.unicode-minus'] = False

pd.to_datetime(data['COLLECTTIME'])
data1 = data[(data['ENTITY'] == 'C:\\') & (data['TARGET_ID'] == 184)]
#设置dataframe索引,修改dataframe,不创建新对象
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())

运行后,可以看到我们将在这些数据上进行可视化操作:

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

在源文件中添加如下代码:

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

运行后可以看到C盘容量的时序图:

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

继续添加如下代码:

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

运行后可以看到D盘容量的时序图:
应用系统负载分析与磁盘容量预测-LMLPHP

根据上图可以得知,磁盘的使用情况都不具备有周期性,它们表现出缓慢性增长,呈现趋势线。

初步判断,数据是非平稳的。

数据清洗

在实际业务中,监控系统会每天定时对磁盘的信息进行收集。但是一般情况下,磁盘的容量属性是一个定值,因此磁盘原始数据中会存在磁盘容量的重复数据。

在数据清洗过程中,剔除磁盘容量的重复数据,并且将所有服务器的磁盘容量作为一个固定值,方便模型预警。

打开文件,添加如下代码:

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

将原始数据中重复数据剔除。

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

属性构造

在数据存储中,磁盘容量以KB为单位。因为每台服务器的磁盘信息可以通过表中NAME、TARGET_ID、ENTITY三个属性进行区分,且每台服务器的上述三个属性是不变的,所以可以将这个三个属性值合并,构造新的属性。

打开文件,添加如下代码:

data3 = pd.DataFrame(index = data1.index,columns=['SYS_NAME','CWXT_DB:184:C:\\','CWXT_DB:184:D:\\','COLLECTTIME'])
data3['SYS_NAME'] = data1['SYS_NAME']
data3['CWXT_DB:184:C:\\'] = data1['VALUE']
data3['CWXT_DB:184:D:\\'] = data2['VALUE']
data3['COLLECTTIME'] = data1.index
data3.to_excel('./data/data_processed.xls')
print(data3.head())

运行后可以看到,属性构造后的数据内容为:

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

容量预测模型

将处理后的数据分为两部分,一部分是建模样本数据,一部分是模型验证数据。选取建模数据的最后5条数据为验证数据,其他数据为建模样本数据。

(1)我们首先要做的是对观测值进行平稳性检验,如果不平稳需要进行差分运算直到差分后的数据平稳

(2)在数据平稳后进行白噪声检验,如果没有通过白噪声检验,就进行模型识别,识别模型属于AR,MA和ARMA中的哪一种模型,并通过贝叶斯信息准则对模型进行定阶,确定ARIMA模型的p、q参数 。

(3)在模型识别后需要进行模型检验,检测模型残差序列是否为白噪声序列,如果没有通过检验,需要对其进行重新识别,对已经通过检验的模型采用极大似然估计方法进行模型参数估计。

(4)应用模型进行预测,将实际值与预测值进行误差分析。如果误差比较小,表明模型拟合效果较好,则模型可以结束,反之需要重新估计参数。

平稳性检验

为了确定原始数据序列中没有随机趋势或确定趋势,需要对数据进行平稳性检验,否则将会产生“伪回归”的现象。本节采用ADF方法来进行平稳性检验。

需要注意的是,本次实验我们只使用C盘容量来进行模型的构建和预测。学生可自行使用D盘容量进行模型构建和预测。
新建文件 model.py,添加如下代码:

#-*- coding:utf-8 -*-
import pandas as pd
#ADF检验
#参数初始化
discfile = './data/data_processed.xls'

data4 = pd.read_excel(discfile)
#不使用最后5个数据
data = data4.iloc[:len(data)-5]

#平稳性测试
from statsmodels.tsa.stattools import adfuller as ADF
diff = 0 
adf = ADF(data['CWXT_DB:184:C:\\'])
#print(adf)
#adf[1]为p值,p值小于0.05认为是平稳的
while adf[1] >= 0.05:
    diff = diff + 1
    adf = ADF(data['CWXT_DB:184:C:\\'].diff(diff).dropna())
    #print(adf)
    
print(u'原始序列经过%s阶差分后归于平稳,p值为%s'%(diff,adf[1]))

运行后可以看到:

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

此时将d值确定为1。

白噪声检验

为了验证序列中有用的信息是否已被提取完毕,需要对序列进行白噪声检验。如果序列检验为白噪声序列,就说明序列中有用的信息已经被提取完毕了,剩下的全是随机扰动,无法进行预测和使用。本实验采用LB统计量的方法进行白噪声检验。

打开文件model.py,添加如下代码:

#白噪声检验
#LB统计量
from statsmodels.stats.diagnostic import acorr_ljungbox

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

运行后可以看到:

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

同样需要一阶差分将原始数据的非平稳性消除。

模型识别

本节采用极大似然法进行模型的参数估计,估计各个参数的值。针对各个不同模型,采用BIC信息准则对模型进行定阶,确定p,q参数,从而选择最优模型。

目前我们已经确定ARIMA模型中d=1。

打开model.py文件,添加如下代码:

#模型识别
#确定最佳p、d、q值
#xdata = data['CWXT_DB:184:D:\\']
xdata = data['CWXT_DB:184:C:\\']
from statsmodels.tsa.arima_model import ARIMA

#定阶
pmax = int(len(xdata)/10) #一般阶数不超过length/10
qmax = int(len(xdata)/10)
bic_matrix = [] #bic矩阵
for p in range(pmax+1):
    tmp = []
    for q in range(qmax+1):
        try:
            tmp.append(ARIMA(xdata,(p,1,q)).fit().bic)
        except:
            tmp.append(None)
    bic_matrix.append(tmp)
bic_matrix = pd.DataFrame(bic_matrix) #取值区域
#stack()将数据from columns to indexs
p,q = bic_matrix.stack().astype('float64').idxmin()
print(u'BIC最小的p值和q值为:%s、%s'%(p,q))
#D:1,1
#C:0,0

运行后,可以看到针对C盘容量的最优模型为ARIMA(0,1,0)。
针对D盘容量的最优模型为ARIMA(1,1,1)。

模型检验

模型确定后,检验其残差序列是否为白噪声。如果不是白噪声,说明残差中还存在有用信息,需要修改模型或者进一步提取。

打开文件model.py,添加如下代码:

#模型检验
lagnum = 12
from statsmodels.tsa.arima_model import ARIMA

arima = ARIMA(xdata,(p,1,q)).fit()
xdata_pred = arima.predict(typ = 'levels')#predict
#print(xdata_pred)
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))

运行后,针对C盘容量的ARIMA(0,1,0)符合白噪声检验。

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

模型预测

应用通过检验的模型进行预测,获取未来5天的预测值,并且与实际值比较。

我们在建模时未使用最后5个数据,我们用这些数据来做预测验证。并将单位换算为GB。

打开文件model.py,添加如下代码:


#模型预测
#forecast向前预测5个值
test_predict = arima.forecast(5)[0]

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

运行后,可以看到预测值:

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

模型评价

至此,我们的模型已经构建完成。为了评价时序预测模型效果的好坏,本实验采用3个衡量模型预测精度的统计量指标:平均绝对误差、均方根误差和平均绝对百分误差。这3个指标从不同侧面反映了算法的预测精度。

结合实际业务分析,将误差阈值设为1.5。

打开文件model.py,添加如下代码:


#计算误差
#列操作
test_data[u'预测容量'] = test_data[u'预测容量'].astype(float)
test_data[u'实际容量'] = test_data[u'实际容量'].astype(float)
#10**6单位换算
abs_ = (test_data[u'预测容量'] - test_data[u'实际容量']).abs()/10**6
mae_ = abs_.mean()
rmse_ = ((abs_**2).mean())**0.05
mape_ = (abs_/test_data[u'实际容量']).mean()

print(u'平均绝对误差为:%0.4f,\n均方根误差为:%0.4f,\n平均绝对百分误差为:%0.6f。'%(mae_,rmse_,mape_))

运行后可以看到:

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

实际值与预测值之间的误差全都小于误差阈值。因此模型的预测效果在实际业务可接受的范围内,可以采用此模型进行预测。

参考:

https://blog.csdn.net/qq_40006058/article/details/80627357
https://blog.csdn.net/sinat_33519513/article/details/79036958
https://blog.csdn.net/huang1024rui/article/details/51375990
https://blog.csdn.net/bi_hu_man_wu/article/details/64918870

10-03 20:16