作者 :sileng
前言
近年来,机器学习领域取得了突破性的发展,越来越多的应用场景受益于此,也取得突破。机器学习善于解决重复性,有规律的的问题,而运维的某些业务场景也恰是被枯燥的、重复性的工作所堆积。为此作者尝试使用机器学习的方法来解决运维场景下的某些问题,记录此文。
机器学习与平时编程解决问题的区别
我们平时编程解决问题,主要是基于规则,而通过机器学习来解决问题是通过建立模型。
1、基于规则
我们通过经验或者智慧,主动发掘可以解决问题的规则(也许就是一条条if语句),然后将许多规则结合在一起形成解决问题的方案。就比如图中判断垃圾邮件的过程,标题是否包含某种词……等就是明确的规则。这种方法修改起来非常方便,只要根据场景的演变,不断修正规则集。
2、基于模型
机器学习就是通过模型来解决问题,首先需要一堆数据(假设为X),然后通过某一种算法进行学习(这里的某种算法多种多样,需要了解但不需要精通,毕竟不是专业人士),数据+学习算法 就会产生一个模型(模型这里我们认为是一个复杂的函数f)。有了这个函数,当有新的数据来需要预测的时候,就代入函数得到函数的结果(函数结果也即为问题结果)。
这里有两个问题:
1、这个模型是由算法+数据 训练产生的,而不是人工干预形成的,所以当你觉得模型不满意的时候,你没法直接调整模型,因为模型对于你来说是一个黑盒。你只能通过调整数据或者调整算法来间接调整模型,已达到优化解决方案的目的。所以有一个尴尬是,当你遇到一个新的问题场景,你想说像基于规则的程序那样,我们快点给模型加一个规则来修正模型以解决新问题吧,抱歉,臣妾做不到……必须重新训练模型。
2、通过模型计算出的结果往往不太好解释,不像规则产生的结果可追溯形成的过程,从而完成修正。
机器学习问题类型
对问题进行分类,能够帮助我们更好的找到适合机器学习发挥的场景,一般有四大类型:
1、分类(classification):在训练数据上建模,对于新样本,判断它的类别。如垃圾邮件识别中判断是否垃圾邮件(二分类)、tensoflow的入门教程-手写数字识别(多分类)等
2、回归(regression):在训练数据上建模,对于新样本,判断它的标注值。标注值与分类问题不同,分类问题的标注是离散值,而回归问题中的标注是实数(连续的)。如股价预测、房价预测、监控曲线预测等。
3、聚类(clustering):给出了一些相似度衡量标准,用来判断两个不同数据的相似程度,然后根据这些标准将数据进行划分。如在一堆未给出名字的照片中,自动的将同一个人的照片聚集到一块。
4、规则抽取(rule extraction):发现数据中属性之间的统计关系,而不只是预测一些事情。如啤酒和尿布的关系。商品推荐就是最典型的应用场景。
尝试的场景
运维的工作中,经常需要对重要的指标曲线进行观察,来判断系统是否正常or异常。这个场景广泛发生在包括监控告警、运营变更、容灾演练等情况下,但是通过一些固定阀值+特定检测算法的方法并不能满足不断变化的情况。所以第一个尝试的场景就是:
根据某一指标曲线的历史数据判断当前/未来数据点是否异常。
在实践上述问题的过程中,发现因为机器学习毕竟是基于历史预测未来,如果历史本就没有值得学习的价值,那判断是否异常就会导致不可理解的结果(就是某些指标图形效果不好),继而产生另一场景:
把指标曲线进行分类,把不同图形特征的指标曲线分成若干类,分而治之。
指标曲线异常检测
1.提前想清楚的问题
数据有哪些?针对某一条指标曲线,假设是每一分钟为一个slot,那么一天就是1440 slot。又因为我们秒级监控的数据是保存两周,那么14 * 1440个slot。
数据需要提取特征吗?常规的机器学习都需要通过专门设计、特征工程等方法来提取特征。(直接怼原始数据这种适用于深度学习的方法,应该是基于海量数据,略过…)
指标曲线异常检测是什么类型的问题?二分类问题,判断slot是否异常。
应该使用什么算法?因为数据本身并不具备标记,且通过设计方法来标记数据的成本也很高(slot太多,每个都要标记),所以只能采用无监督算法来建立模型。
每一个指标曲线都建立一个唯一模型?理论上,针对异常分类,每个指标曲线单独一个模型肯定是最优的,因为可以避免其他指标曲线的干扰。但是因为实时性、资源等实际情况,需要针对应用场景自己决定,此处单独建模。
2.特征提取
时序数据如何提取有关于异常检测的特征。采取的方法是:每个slot单独提取特征向量(可能变化slot时间窗口为5min)。每个slot提取特征的过程,是使用很多比较“流行”的异常检测器来完成。slot经过每个检测器的提取之后,会得到一些被检查器量化过的,可以衡量数据异常程度的数值,称为serverity,然后采各种不同的serverity组合形成slot对应的特征向量。举例servertiy的方法:
比如常见的正态分布的方法,假设某一时间点(纵向上看,不同天但同时同分)的数据符合正太分布,即14个slot符合正太分布,计算14个点的μ和σ,然后对于某个点x的serverity=|x-μ| / σ。另外其他能够预测指标曲线值的方法可以使用 serverity = |预测值 - 实际值| / (max -min) 的方法来度量异常程度。
如下图所示的思想,把每一个slot分别转换为不同的检测器产生的serverity。这样做的思考是,通过聚集不同检测器的能力,检测出不同情况下的异常,再通过机器学习来区分哪些是真正的异常点。经过转化之后有效的去除了时间、数值等带来的影响。
我们最终实现了的检测器包括:sma(移动平均法)、wma(加权移动平均)、tsd(时间序列分解法)、diff(差分)、rate(同环比)、gasi(高斯分布)、ema(一次指数平滑)、hw(三次指数平滑)、arima(自回归积分华东平均)等。
3.训练模型
训练模型,采用是sklearn的python库来实现。经过对比和实验,选取的机器学习算法是无监督的分类异常检测算法 isolationForest(孤异森林)。该算法的特点是:无监督、速度快、效果好(ps:已经有wxg同学在登录异常检测中尝试过)。放一张某天tdp系统异常时某核心指标曲线的检测效果:
上图为当日异常曲线与昨日正常曲线对比图,下图为经过模型判断之后的图,红色表示判断为异常点。该模型已经尝试在一体化流程系统的上线验证模块使用。
指标曲线分类
曲线分类,同样是机器学习中典型的分类问题,而且针对这个问题已经有同学进行过尝试,可参考<智能告警算法-曲线识别模型>。接下来简单描述下不同的地方:
1、特征的设计:采用了开源工程提取特征和人工设计特征相结合的方法,开源时序特征工程为cesium 和 tsfresh。因为开源特征较多,可以使用一个特征选择的方法,进行筛选之后使用,第一版本的模型,使用了19个特征。
2、标记的训练数据:并没有采用kmeans的方法来形成标记数据,反而使用了人工标记的方法(标记了200个不同的曲线,花了一天时间)。之前也参考其他同学的方法先用kmeans聚类打标,但是效果一直不太好,且聚类完成之后也要人工挑选确认样本,所以一不做二不休直接人工了,23333333。
3、监督分类算法:监督分类算法很多,比如svm、LR、神经网络等。因为我们训练数据不多,最后采用的是随机森林。
4、人工划分了4个类别:周期较光滑曲线、周期较粗糙曲线、类心跳曲线(整体起伏不大,在某一个范围内反复上线跳动)、类错误率曲线(绝大部分情况为恒定值,比如0,偶尔有异常突起或下陷)。该模型在脚本大师上建立了一个体验任务,可是输入秒级监控的曲线体验分类。
总结
1、特征很重要:”数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。“由此可见,特征工程尤其是特征选择在机器学习中占有相当重要的地位。在实践中,大部分时间也都花在了特征选择与提取上。怪不得深度学习如此火,跳过这步还是很伟大的,23333。
2、数据难获得:实践中,数据的获取,特别是有标记的数据获取,感觉是十分困难的。看似有很多数据,但是不知道怎么把看似大量数据变成问题所需要且能够使用的数据,还真是个世界难题。
3、应用场景难选取:想在运维实践中运用机器学习获得良好的效果,需要丰富的运维经验,又要深厚的机器学习功底。21世纪什么最重要?人才、人才、人才。好好学习把,童鞋们!