Spark MLlib模型训练—分类系列算法
今天这一讲,我们会结合房屋预测场景,一起学习回归、分类与聚类中的典型算法在 Spark MLlib 框架下的具体用法。掌握这些用法之后,针对同一类机器学习问题(回归、分类或是聚类),你就可以在其算法集合中,灵活、高效地做算法选型。
在这个场景中,我们有 3 个实例,分别是房价预测、房屋分类和房屋聚类。房价预测我们并不陌生,在前面的学习中,我们一直在尝试把房价预测得更准。
房屋分类,它指的是,给定离散标签(Label),如“OverallQual”(房屋质量),结合房屋属性特征,将所有房屋分类到相应的标签取值,如房屋质量的“好、中、差”三类。
而房屋聚类,它指的是,在不存在标签的情况下,根据房屋特征向量,结合“物以类聚”的思想,将相似的房屋聚集到一起,形成聚类。
今天我们的目标是房屋分类也就是分类系列算法,我们会采用GBDT和RF 同时对房屋进行分类,从而可以方便的对算法模型进行对比。
RF 房屋分类
在“House Prices - Advanced Regression Techniques”竞赛项目中,数据集总共有 79 个字段。在之前,我们一直把售价 SalePrice 当作是预测标的,也就是 Label,而用其他字段构建特征向量。
现在,我们来换个视角,把房屋质量 OverallQual 看作是 Label,让售价 SalePrice 作为普通字段去参与构建特征向量。在房价预测的数据集中,房屋质量是离散特征,它的取值总共有 10 个,如下图所示。
如此一来,我们就把先前的回归问题(预测连续值),转换成了分类问题(预测离散值)。不过,不管是什么机器学习问题,模型训练都离不开那 3 个环节:
- 准备训练样本
- 定义模型,并拟合训练数据
- 验证模型效果
在训练样本的准备上,除了把预测标的从 SalePrice 替换为 OverallQual,我们完全可以复用之前使用 回归来预测房价的代码实现。
// 分类标的字段OverallQual
val labelField= "OverallQual"
val labelFeature= "indexedOverallQual"
engineeringDF = engineeringDF
.withColumn(labelFeature, col(labelField).cast(IntegerType))
.drop(labelField)
接下来,我们就可以定义随机森林模型、并拟合训练数据。实际上,除了类名不同,RandomForestClassifier 在用法上与 RandomForestRegressor 的几乎一模一样,如下面的代码片段所示。
import org.apache.spark.ml.classification.RandomForestClassifier
// 定义随机森林模型
val rf= new RandomForestClassifier ()
// Label不再是房价,而是房屋质量
.setLabelCol(labelFeature)
.setFeaturesCol("indexedFeatures")
// 限定每棵树的最大深度
.setMaxDepth(5)
// 限定决策树的最大棵树
.setMaxIter(30)
// 区分训练集、验证集
val Array(trainingData, testData) = engineeringDF.randomSplit(Array(0.7, 0.3))
// 拟合训练数据
val rfModel = rf.fit(trainingData)
为了方便学习,这里给出核心代码的完整逻辑
// 从CSV文件创建DataFrame
val trainDF: DataFrame = spark.read.format("csv").option("header", true).load(fileP