在系統(tǒng)運(yùn)維中,經(jīng)常會(huì)遇到某個(gè)具體組件發(fā)生故障,進(jìn)而導(dǎo)致整個(gè)應(yīng)用系統(tǒng)癱瘓的情況,所以要及時(shí)對(duì)這些具體組件進(jìn)行跟蹤和預(yù)測,判斷出如果發(fā)生故障,要及時(shí)給予告警。
如下為某個(gè)應(yīng)用系統(tǒng)的拓?fù)潢P(guān)系圖。
本案例的目的是通過分析歷史磁盤容量相關(guān)數(shù)據(jù),采用時(shí)間序列分析法,預(yù)測應(yīng)用系統(tǒng)服務(wù)器磁盤已使用空間的大小,根據(jù)用戶需求設(shè)定不同的預(yù)警等級(jí),將預(yù)測值和容量值進(jìn)行比較,對(duì)其結(jié)果進(jìn)行預(yù)警判斷,提供定制化預(yù)警的提示。
分析步驟為:
- 從數(shù)據(jù)源中選擇型抽取歷史數(shù)據(jù)與每天定時(shí)抽取數(shù)據(jù)。
- 對(duì)抽取的數(shù)據(jù)進(jìn)行周期性分析以及數(shù)據(jù)清洗,數(shù)據(jù)變換等操作后,形成建模數(shù)據(jù)。
- 采用時(shí)間序列分析法對(duì)建模數(shù)據(jù)進(jìn)行模型的構(gòu)建,利用模型預(yù)測服務(wù)器磁盤已使用情況。
- 應(yīng)用模型預(yù)測服務(wù)器磁盤將要使用的情況,通過預(yù)測到的磁盤使用大小與磁盤容量大小按照定制化標(biāo)準(zhǔn)進(jìn)行判斷。
1. 數(shù)據(jù)預(yù)處理
1.1 平穩(wěn)性分析
將原始的時(shí)序型數(shù)據(jù)繪圖,可以觀察到:磁盤的使用情況并不具有周期性,它們表現(xiàn)出緩慢型增長,呈現(xiàn)一定的趨勢性,因此可以初步確認(rèn)數(shù)據(jù)為非平穩(wěn)性。
1.2 屬性構(gòu)造
原始的磁盤空間數(shù)據(jù)并不是直接可以使用的屬性數(shù)據(jù)集,所以我們需要自己動(dòng)手構(gòu)建屬性,比如
將上面兩個(gè)樣本的屬性合并為一個(gè)樣本的四個(gè)屬性。代碼為:
data=pd.read_excel(r"E:\PyProjects\DataSet\PyMining\Data\chapter11\demo\data\discdata.xls")
data = data[data['TARGET_ID'] == 184].copy() #只保留TARGET_ID為184的數(shù)據(jù)
# 183表示磁盤容量,而184表示磁盤已使用大小
data_group = data.groupby('COLLECTTIME') #以時(shí)間分組
def attr_trans(x): #定義屬性變換函數(shù)
result = pd.Series(index = ['SYS_NAME', 'CWXT_DB:184:C:\\', 'CWXT_DB:184:D:\\','COLLECTTIME'])
result['SYS_NAME'] = x['SYS_NAME'].iloc[0]
result['COLLECTTIME'] = x['COLLECTTIME'].iloc[0]
result['CWXT_DB:184:C:\\'] = x['VALUE'].iloc[0]
result['CWXT_DB:184:D:\\'] = x['VALUE'].iloc[1]
return result
data_processed = data_group.apply(attr_trans) #逐組處理,每一天構(gòu)成一組,從每一組中提取出value等
data_processed.head(10)
繪圖查看下C盤和D判斷已使用容量變化趨勢圖為:
2. 時(shí)序建模
建模流程圖為:
首先對(duì)觀測值序列進(jìn)行平穩(wěn)性檢驗(yàn),如果不平穩(wěn),則對(duì)其進(jìn)行差分處理直到差分后的數(shù)據(jù)平穩(wěn),在平穩(wěn)后,對(duì)其進(jìn)行白噪聲檢驗(yàn),如果沒有通過白噪聲檢驗(yàn),就進(jìn)行模型識(shí)別,識(shí)別其模型屬于AR,MA,ARMA中的哪一種模型。
2.1 平穩(wěn)性檢測
為了確定原始數(shù)據(jù)序列中沒有隨機(jī)趨勢或確定趨勢,需要對(duì)數(shù)據(jù)進(jìn)行平穩(wěn)性檢驗(yàn),否則將會(huì)產(chǎn)生偽回歸現(xiàn)象。下面采用單位根檢驗(yàn)(ADF)的方法對(duì)時(shí)序圖進(jìn)行平穩(wěn)性檢驗(yàn)。
data2=data_processed.copy()
#平穩(wěn)性檢測
from statsmodels.tsa.stattools import adfuller as ADF
diff = 0
adf = ADF(data2['CWXT_DB:184:D:\\'])
while adf[1] > 0.05:
diff = diff + 1
adf = ADF(data2['CWXT_DB:184:D:\\'].diff(diff).dropna())
print('原始序列經(jīng)過%s階差分后歸于平穩(wěn),p值為%s' %(diff, adf[1]))
結(jié)果為:原始序列經(jīng)過1階差分后歸于平穩(wěn),p值為2.702061091530161e-06
2.2 白噪聲檢驗(yàn)
為了驗(yàn)證序列中有用的信息是否已被提取完畢,需要對(duì)序列進(jìn)行白噪聲檢驗(yàn),如果序列檢驗(yàn)為白噪聲序列,說明序列中有用的信息已經(jīng)被提取完畢,剩下的全都是隨機(jī)擾動(dòng),無法進(jìn)行預(yù)測和使用。下面采用LB統(tǒng)計(jì)量的方法進(jìn)行白噪聲檢驗(yàn)。
#白噪聲檢測
from statsmodels.stats.diagnostic import acorr_ljungbox
[[lb], [p]] = acorr_ljungbox(data2['CWXT_DB:184:D:\\'], lags = 1)
if p < 0.05:
print('原始序列為非白噪聲序列,對(duì)應(yīng)的p值為:%s' %p)
else:
print('原始該序列為白噪聲序列,對(duì)應(yīng)的p值為:%s' %p)
[[lb], [p]] = acorr_ljungbox(data2['CWXT_DB:184:D:\\'].diff().dropna(), lags = 1)
if p < 0.05:
print('一階差分序列為非白噪聲序列,對(duì)應(yīng)的p值為:%s' %p)
else:
print('一階差分該序列為白噪聲序列,對(duì)應(yīng)的p值為:%s' %p)
結(jié)果為:
2.3 模型識(shí)別
采用極大似然比方法進(jìn)行模型的參數(shù)估計(jì),估計(jì)各個(gè)參數(shù)的值然后針對(duì)各個(gè)不同模型,采用BIC信息準(zhǔn)則對(duì)模型進(jìn)行定階,確定p,q參數(shù),從而選擇最優(yōu)模型。
from statsmodels.tsa.arima_model import ARIMA
#定階
pmax = int(len(xdata)/10) #一般階數(shù)不超過length/10
qmax = int(len(xdata)/10) #一般階數(shù)不超過length/10
bic_matrix = [] #bic矩陣
for p in range(pmax+1):
tmp = []
for q in range(qmax+1):
try: #存在部分報(bào)錯(cuò),所以用try來跳過報(bào)錯(cuò)。
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.iloc[:,:-1].stack().argmin() #先用stack展平,然后用idxmin找出最小值位置。
print(u'BIC最小的p值和q值為:%s、%s' %(p,q))
結(jié)果是:BIC最小的p值和q值為:1、1
2.4 模型檢驗(yàn)
模型確定后,需要檢驗(yàn)其殘差序列是否為白噪聲,如果不是白噪聲,說明殘差中還存在有用的信息,需要修改模型或者進(jìn)一步提取。
from statsmodels.tsa.arima_model import ARIMA #建立ARIMA(0,1,1)模型
arima = ARIMA(xdata, (0, 1, 1)).fit() #建立并訓(xùn)練模型
xdata_pred = arima.predict(typ = 'levels') #預(yù)測
pred_error = (xdata_pred - xdata).dropna() #計(jì)算殘差
lagnum = 12 #殘差延遲個(gè)數(shù)
from statsmodels.stats.diagnostic import acorr_ljungbox #白噪聲檢驗(yàn)
lb, p= acorr_ljungbox(pred_error, lags = lagnum)
h = (p < 0.05).sum() #p值小于0.05,認(rèn)為是非白噪聲。
if h > 0:
print(u'模型ARIMA(0,1,1)不符合白噪聲檢驗(yàn)')
else:
print(u'模型ARIMA(0,1,1)符合白噪聲檢驗(yàn)')
結(jié)果:模型ARIMA(0,1,1)不符合白噪聲檢驗(yàn),說明殘差序列中還有有用的信息?
2.5 誤差計(jì)算
#計(jì)算誤差
abs_ = (data[u'預(yù)測值'] - data[u'實(shí)際值']).abs()
mae_ = abs_.mean() # mae
rmse_ = ((abs_**2).mean())**0.5 # rmse
mape_ = (abs_/data[u'實(shí)際值']).mean() # mape
print(u'平均絕對(duì)誤差為:%0.4f,\n均方根誤差為:%0.4f,\n平均絕對(duì)百分誤差為:%0.6f。' %(mae_, rmse_, mape_))
參考資料:
《Python數(shù)據(jù)分析和挖掘?qū)崙?zhàn)》張良均等