《Elastic Stack 实战手册》——四、应用实践——4.2 可观测性应用场景 ——4.2.1.基于Elasticsearch实现预测系统(2) https://developer.aliyun.com/article/1226133
分类与回归
机器学习本质上是基于统计学原理,构建数学模型的过程,而构建出来的模型又可以用于数据分析与数据预测。机器学习一般分为监督学习和无监督学习两大类,它们分别针对有标注(Label)数据和无标注数据构建数学模型。
标注可以认为是对数据在某一维度上的识别,比如让计算机识别声音或图像中的文字,就需要先对它们做标注,然后才可以根据标注对声音或图像构建数学模型。具体来说,人们先要提供一组与文字关联好的音频或图片,计算机再根据这些标注好的数据,找出从声音频率、图片像素到文字的映射关系。由于不同人对文字的发音和书写存在着巨大的差异,所以需要通过海量音频和图像进行统计分析,找出这种映射关系中最为本质的转换模型。所以监督学习的本质是学习输入到输出的统计学规律,只不过这些映射关系并不像加减法那样直观,需要借助计算机统计与分析才能完成。
无监督学习则是根据无标注数据进行数学建模的过程,它不存在输入与输出,本质上是学习数据中天然的统计规律或潜在结构。比如用户的消费行为就很难根据他们的年龄、性别、学历等特征做区分,而且由于涉及隐私这些数据也不一定会在系统中查到。换句话说,即使两个人的硬性特征完全相同,但在人生经历、思想认识等方面存在着的差异,依然可能使他们的消费行为不同。所以这时就只能通过用户消费行为产生的数据对他们进行聚类,相同聚类的用户往往有着相类似的消费习惯,聚类结果也就可以应用于商品推荐系统之中了。
本章介绍的智能预测系统是一种通过监督学习,构建预测模型的机器学习系统,本质上就是发现已知条件与未知结果之间的统计规律。我们之所以要建立这样一个系统,是因为在以往对业务系统日志的统计分析中发现,在某些特定条件下某些用户请求一定会失败。这让我们坚信在已知请求条件与未知运行结果之间,一定存在着某种映射关系,我们希望借由这样一个系统找到这种神秘的映射关系。
在监控系统的数据中原本就包含了请求执行结果,这个数据就可以作为整个请求与处理相关数据的标注。在监督学习中,作为输入的数据一般称为特征(Feature),而输出的结果则一般称为标注(Label)。在示例中定义的 featureFields 定义的就是索引上那些可以作为特征的字段,而 labelField 则是索引上可以作为标注的字段。示例中的代码就是将特征字段的值和标注字段的值从 Map 中取出,并将它们统一放置到一个数组中并转换为 Spark 运算需要使用的
DataFrame。
正如前面所介绍的那样,监督学习的本质是学习输入到输出的统计学规律。如果从输入到输出的产出结果是有限的,那么这时机器学习生成的模型称为分类器(Classifier),而它解决的问题就是分类问题。比如我们正在介绍智能预测系统,它通过已知的请求条件预测执行结果,输入是在请求执行前已知的请求条件,而输出则是该请求的执行结果。
执行结果只有两种结果,要么成功要么失败,所以计算机学习出来的数学模型就是一个分类器。除了分类问题以外,监督学习可以解决的另一种类问题是回归问题。与分类问题不同,回归问题输出的不是有限数量的结果,而是数值连续的结果,它更像我们在数学中学习到的常规函数。
同样是以请求条件作为输入,如果预测的不是执行结果而是执行时间,那么这时要解决的就不再是分类问题而是回归问题。因为请求的执行时间并不是离散的,它可能是任意一个非负的数值。
Spark机器学习支持多种实现分类与回归问题的算法,包括逻辑回归、决策树、随机森林、梯度提升树等等。我们很难在一个章节中将上述算法完全讲解清楚,但所幸应用这些算法做预测也并不需要深入了解算法原理。本章仅以梯度提升树为例解决分类问题,也就是通过梯度提升树实现对请求执行结果的预测,读者可根据本章所列方法实现对请求执行时间的预测。
Spark 在实现机器学习时一般会将数据分成两组,一组用于构建数学模型,而另一组则用于验证已构建的模型。
示例中的代码就是将示例中生成的数据按 8:2 分成两组,8 成的数据用于生成模型,而 2 成的数据用于验证模型:
Dataset<Row>[] splits = featurized.randomSplit(new double[]{0.8, 0.2}); GBTClassifier gbt = new GBTClassifier() .setLabelCol(LABEL_COL) .setFeaturesCol(FEATURES_COL) .setMaxIter(10); GBTClassificationModel model = gbt.fit(splits[0]); Dataset<Row> predictions = model.transform(splits[1]); MulticlassClassificationEvaluator evaluator = new MulticlassClassificationEvaluator() .setLabelCol(LABEL_COL) .setPredictionCol(PREDICTION_COL) .setMetricName("accuracy"); double accuracy = evaluator.evaluate(predictions); log.info("Test Error = " + (1.0 - accuracy)); model.write().overwrite().save(path);
示例1.5 生成预测模型
如示例所示,GBTClassifier 就是基于 GBT 算法的分类器,通过它可以生成基于 GBT 算法的分类模型。setLabelCol 和 setFeaturesCol 分别设置了数据的标注和特征,而 setMaxIter 则设置了生成模型时迭代的次数。有了 GBT 分类器后,调用其 fit 方法并将8成的数据 splits[0]传入就会触发模型创建的运算。
模型生成的运算通常比较慢,具体时间长度取决于参与运算的数据量大小,但一般都是分钟级别的。由于模型一旦生成往往可以复用,所以在数据变化不是特别剧烈的情况下,可以将模型保存到硬盘。这样在需要预测时就不用再通过匹配数据生成模型,通过硬盘中保存的现成模型数据就可迅速生成模型。所以在我们的实验中,会每天定时更新一次模型到硬盘,但在实例应用模型时,都是直接从硬盘中加载模型以节省运算时间。
示例展示了从硬盘中加载模型,并根据输入的特征向量进行预测的代码片段:
GBTClassificationModel model = GBTClassificationModel.load(path); Dataset<Row> predictions = model.transform(featurized); predictions.show(false);
示例1.6 实现预测
示例中使用的 tranform 方法在这里就是最终用于预测的方法,传入的 featurized 则是经过向量化的已知数据。
当然,以上示例代码中省略大量的代码细节,在实际应用中还有许多更为具体的问题要解决。根据我们应用的效果来看,预测结果的准确率可以达到 95% 以上。
回归类问题的处理过程与本章所介绍内容类似,感兴趣的读者可根据本章内容尝试实现对请求处理时间的预测。