一个典型的机器学习机器学习过程通常会包含:源数据 ETL,数据预处理,指标提取,模型训练与交叉验证,新数据预测等。我们可以看到这是一个包含多个步骤的流水线式工作,也就是说数据从收集开始,要经历多个步骤,才能得到我们需要的输出。
如果目标数据集结构复杂需要多次处理,或者是对新数据进行预测的时候需要结合多个已经训练好的单个模型进行综合预测 (集成学习的思想),那么使用 MLlib 将会让程序结构复杂,难于理解和实现。
Spark 1.2 版本之后引入了 ML Pipeline(一个可以用于构建复杂机器学习工作流应用的新库),经过几个版本的发展,截止目前已经变得足够稳定易用。
Pipeline中的主要概念
Spark ML Pipeline 的出现,是受到了 scikit-learn 项目的启发,并且总结了 MLlib 在处理复杂机器学习问题上的弊端,旨在向用户提供基于 DataFrame 之上的更加高层次的 API 库,以更加方便的构建复杂的机器学习工作流式应用。
一个 Pipeline 在结构上会包含一个或多个 PipelineStage,每一个 PipelineStage 都会完成一个任务,如数据集处理转化,模型训练,参数设置或数据预测等,这样的 PipelineStage 在 ML 里按照处理问题类型的不同都有相应的定义和实现。
其实,类似Pipeline的概念在其他一些流行的开源项目中也有应用,如TensorFlow、Keras、Theano等深度学习框架,将不同的网络层组合起来;如Oozie,将不同类型的作业组合起来。
DataFrame:ML API使用这个来自Spark SQL的概念作为ML dataset,可以保存多种数据类型。比如:使用不同的列存储文本、特征向量、真实标签和预测结果。
Transformer:转换器,是一个 PipelineStage,实现上也是继承自 PipelineStage 类,主要是用来把 一个 DataFrame 转换成另一个 DataFrame,比如一个模型就是一个 Transformer,因为它可以把 一个不包含预测标签的测试数据集 DataFrame 打上标签转化成另一个包含预测标签的 DataFrame,显然这样的结果集可以被用来做分析结果的可视化。
Estimator:评估器或适配器,在 Pipeline 里通常是被用来操作 DataFrame 数据并生产一个 Transformer,如一个随机森林算法就是一个 Estimator,因为它可以通过训练特征数据而得到一个随机森林模型。实现上 Estimator 也是继承自 PipelineStage 类。
Parameter:被用来设置 Transformer 或者 Estimator 的参数。
Pipeline:一个Pipeline链是将多个Transformer和Estimator组合在一起组成一个ML workflow。
要构建一个 Pipeline,首先我们需要定义 Pipeline 中的各个 PipelineStage,如指标提取和转换模型训练等。有了这些处理特定问题的 Transformer 和 Estimator,我们就可以按照具体的处理逻辑来有序的组织 PipelineStages 并创建一个 Pipeline,如 val pipeline = new Pipeline().setStages(Array(stage1,stage2,stage3,…))。然后就可以把训练数据集作为入参并调用 Pipelin 实例的 fit 方法来开始以流的方式来处理源训练数据,这个调用会返回一个 PipelineModel 类实例,进而被用来预测测试数据的标签,它是一个 Transformer。
Pipeline组件
Transformers
Transformer是一个抽象类,包括特征转换以及学习后的模型两种情况。不管是哪一种都需要实现方法transform(),用以将一个DataFrame转换成另一个,通常都是添加一个或多个列。
比如:
特征转换是:读取一个列(比如:text)然后映射为一个新列(比如:特征向量),输出的新DataFrame就是将新映射出来的列加到原来的DataFrame中。
学习后的模型:读取一个DataFrame(包含特征向量),对于每个特征向量预测label,最后输出携带预测结果的新的DataFrame。
Estimators
这个是一个学习算法的抽象,可以对数据fit或者train。一个Estimator需要实现方法fit(),这个方法接收一个DataFrame并输出一个模型也就是Transformer。比如:LogisticRegression就是一个Estimator,通过调用fit()训练得到LogisticRegressionModel,这个输出模型也就是Transformer。
MLlib的Estimator和Transformer使用统一的API来管理参数。
Parameters
ParamMap是一个(parameter, value)的集合。
有两种方法对算法传入参数:
1、通过实例来设置参数。比如:lr是LogisticRegression的一个实例,那么lr.setMaxIter(10)就是让lr在调用fit()方法的时候使用最大10次迭代的参数。
2、通过ParamMap对fit()和transform()设置参数。如果在方法fit()或者transf