该文章出自于ADDOPS团队,前面的《学点机器学习,预测小区房价》很好的给大家科普了一把机器学习,该文章是机器学习在ADDOPS日常运维中的具体实践案例,文章详细介绍了机器学习在磁盘预测方面的使用,能更大的解放运维生产力,希望能给大家一些启发。
背景与目标
存储设备中磁盘容量是服务器能够可靠运行的重要保障。如何避免应用系统中出现存储容量耗尽的情况而导致应用系统负载率过高,最终引发系统故障是一个比较棘手的问题。
目前,工业界普遍采用被动容错机制,为磁盘容量设置一个阈值来保证系统的可靠性:即如果超过阈值,则会发生报警来让人工干预以降低磁盘容量。如果系统管理员不及时进行相应的处理,系统很容易出现故障,从而导致用户无法访问系统,严重影响企业的利益。
本文重点分析存储设备中磁盘容量预测,通过对磁盘容量进行预测,来避免类似情况的发生。
历史数据分析
应用系统出现故障通常不是突然瘫痪造成的,而是一个渐变的过程。例如。系统长时间运行,数据会持续写入存储,存储空间逐渐变少,最终磁盘被写满而导致系统故障。由此可见,在不考虑人为因素的影响时,存储空间随时间变化存在很强的关联性,且历史数据对未来的发展存在一定的影响。所以可以采用时间序列分析法对磁盘容量进行预测分析。
模型使用
本节将以分析磁盘容量时序介绍时间序列模型如何使用。 我们使用以下的步骤来建立一个时间序列模型:
获取数据
我们采集过去7天的数据,采集间隔是1小时。使用下面代码得到历史的数据。
#导入需要的模块
import csv
import date
import datetime
import pandas as pd
#从csv文件中读取时间和对应的数据
data = pd.read_csv("cpu_idle_data.csv")
time_series = []
mydata = []
#将时间保存在time列表中,而将数据保存在mydata中
#将.csv数据读入Pandas数据帧
for timestamp,used_percent in zip(data["timestamp"],data["used_percent"]):
#将数字时间转换为能够识别的时间
a = time.localtime(timestamp)
b = time.strftime("%Y-%m-%d %H:%M:%S", a)
time_series.append(b)
mydata.append(used_percent)
创建时间序列
为数据建立索引,转换为pandas能够识别的时间序列。
dta=pd.Series(mydata)
dta.index = pd.Index(time_series)
dta.index = pd.DatetimeIndex(dta.index)
缺失值处理
使用均值来补齐缺失值。
dta = dta.resample("H")
dta = dta.fillna(np.mean(mydata))
历史趋势
查看磁盘容量过去一周的数据曲线:
predict_outcome = regr.predict(x)
平稳性检测:
观察4中的图,可以看出该序列不平稳,我们需要使用差分的方法来使该序列变为平稳序列。
fig = plt.figure(figsize=(12,8))
ax1= fig.add_subplot(111)
#一阶差分
diff1 = dta.diff(1)
diff1.plot(ax=ax1)
可以看出,经过一阶差分后,数据已经平稳了,可以进行ARMA模型了。 通过肉眼观察每个图像显然不是平稳性检测最好的方法,我们可以使用单位根检测(ADF)进行平稳性检测。 平稳性检测代码:
from statsmodels.tsa.stattools import adfuller as ADF
diff=0
#平稳性检测函数ADF
adf=ADF(dta)
#adf[1]为p值,如果p值小于0.05则认为该序列是平稳的。
while adf[1]>=0.05:
diff=diff+1
adf=ADF(dta)
print(u"原始序列经过%s阶差分后归于平稳,p值为%s" %(diff, adf[1]))
白噪声检验
为了验证系列中是否还有有用的信息,是否已经被提取完毕,需要对序列进行白噪声检验。如果为白噪声,则有用的信息已经被提取完毕,剩下的随机扰动,无法进行预测和使用。 本节使用LB统计量的方法进行白噪声检验,代码如下:
from statsmodels.stats.diagnostic import acorr_ljungbox
#原始序列
[[lb],[p]]=acirr_ljungbox(dta,lag=1)
if p<0.05:
print(u"原始序列为非白噪声序列,对应的p值为%s",%p)
else:
print(u"原始序列为白噪声序列,对应的p值为%s",%p)
#一阶差分序列
[[lb],[p]]=acirr_ljungbox(dta.diff().dropna(),lag=1)
if p<0.05:
print(u"一阶差分序列为非白噪声序列,对应的p值为%s",%p)
else:
print(u"一阶差分序列为白噪声序列,对应的p值为%s",%p)
确定p和q的值,建立ARIMA(p,1,q)模型 第一种方法:人工识别 根据自相关图和偏自相关图来确定p和q的值。
所以p为0,q为0 第二种方法:相对最优模型识别 计算ARIMA(p,q)。当p和q均小于一定值的所有组合的BIC信息量,去其中BIC信息量达到最小的模型阶数。
#迭代的阶数
#一般阶数不超过length/10
pmax = int(len(dta)/10)
qmax = int(len(dta)/10)
bic_matrix = []
for p in range(pmax+1):
tmp = []
for q in range(qmax):
#存在部分p和q建模不成功
try:
model_tmp = ARIMA(dta, (p,1,q), freq="H")
try:
tmp.append(model_tmp.fit().bic)
except:
tmp.append(None)
except:
tmp.append(None)
bic_matrix.append(tmp)
bic_matrix = pd.DataFrame(bic_matrix)
#从中找到p和q的最小值
p,q = bic_matrix.stack().idxmin()
确定p和q的值
从7中获得了p,q值,从5中获得d的值后我们就可以建立ARIMA模型了。
model = ARIMA(dta, (p,d,q), freq="H").fit(trend="nc")
预测未来趋势
预测未来一段时间的值。
#predict_outcome中保存了预测结果、标准误差以及置信区间
predict_outcome = model.forecast(24)
#我们可以从predict_outcome[0]获取到预测的结果
print predict_outcome[0]
预测结果和历史数据:
下面我们通过下面的代码画出历史数据和预测数据的图:
fig, ax = plt.subplots(figsize=(12, 8))
ax = dta.plot()
predict_outcome.plot(ax=ax)
下面是图像:
可以看出预测结果能够真实的反映出历史数据的走势,能够真实的预测出未来的数据值。
总结
该文章的出发点,其实就是为了预测一下磁盘报警的规律,把运维从烦人的磁盘报警中解脱出来,用机器学习的方法来做预测,也是一个AIOPS的更好实践。希望大家能从中得到一些启发,一起探索智能运维。