spark mllib 之 Pipeline工作流构建

来源:互联网 发布:网络出版物的图书 编辑:程序博客网 时间:2024/06/05 10:49

Spark 机器学习库从 1.2 版本以后被分为两个包

  • spark.mllib 包含基于RDD的原始算法API。Spark MLlib 历史比较长,在1.0 以前的版本即已经包含了,提供的算法实现都是基于原始的 RDD。
  • spark.ml 则提供了基于DataFrames 高层次的API,可以用来构建机器学习工作流(PipeLine)。ML Pipeline 弥补了原始 MLlib 库的不足,向用户提供了一个基于 DataFrame 的机器学习工作流式 API 套件。

使用 ML Pipeline API可以很方便的把数据处理,特征转换,正则化,以及多个机器学习算法联合起来,构建一个单一完整的机器学习流水线。这种方式给我们提供了更灵活的方法,更符合机器学习过程的特点,也更容易从其他语言迁移。Spark官方推荐使用spark.ml。如果新的算法能够适用于机器学习管道的概念,就应该将其放到spark.ml包中,如:特征提取器和转换器。最主要的是,从Spark2.0开始,基于RDD的API进入维护模式(即不增加任何新的特性),并预期于3.0版本的时候被移除出MLLib

既然官方都准备抛弃mllib,我们还是抓紧入手spark.ml吧

构建一个管道,这里我使用的是LogisticRegression(逻辑回归),它的原理就不介绍了,网上有很多大佬详细的说了逻辑回归的原理,这里提供一个连接http://blog.csdn.net/han_xiaoyang/article/details/49123419

这里我们来介绍一下工作流是如何应用的,先给出示例代码。

import org.apache.spark.sql.SparkSessionimport org.apache.spark.ml.feature._import org.apache.spark.ml.classification.LogisticRegressionimport org.apache.spark.ml.{Pipeline,PipelineModel}import org.apache.spark.ml.linalg.Vectorimport org.apache.spark.sql.Rowobject PipeLine {  def main(args: Array[String]): Unit = {    val spark = SparkSession.builder().master("local").appName("pipeLine").getOrCreate()    import spark.implicits._    // 创建数据 dataframe    val traing = spark.createDataFrame(Seq(      (0L, "a b c d e spark", 1.0),      (1L, "b d", 0.0),      (2L, "spark f g h", 1.0),      (3L, "hadoop mapreduce", 0.0)    )).toDF("id", "text", "label")    // 定义pipeline中各个工作流阶段PipelineStage,包括转换器和评估器,具体的    // 包含 tokenizer hashingTF lr 三个步骤    val tokenzier = new Tokenizer().setInputCol("text").setOutputCol("words")    val hashingTF = new HashingTF().setNumFeatures(1000).setInputCol(tokenzier.getOutputCol)      .setOutputCol("features")    val lr = new LogisticRegression().setMaxIter(10).setRegParam(0.01)    // 定义管道,此时它还只是一个评估器,只有调用fit()函数之后,返回的model才是一个转换器    val pipeline = new Pipeline().setStages(Array(tokenzier, hashingTF, lr))    val model = pipeline.fit(traing)    // 构建测试数据    val test = spark.createDataFrame(Seq(      (4L, "spark i j k"),      (5L, "l m n"),      (6L, "spark a"),      (7L, "apache hadoop")    )).toDF("id", "text")    // 调用我们训练好的pipelinModel的transform()方法,让测试数据按照顺序通过拟合的工作流    // 产生我们所需要的预测结果    model.transform(test).select("id", "text", "probability", "prediction")      .collect().foreach{      case Row(id: Long, text: String, prob: Vector, prediction: Double) =>        println(s"($id, $text) --> prob=$prob, prediction=$prediction")    }  }}
  1. 我们通过spark.createDataFrame()创建了一个示例数据集,通过它来训练模型。
  2. 定义 Pipeline 中的各个工作流阶段PipelineStage,包括转换器和评估器,具体的,包含tokenizer, hashingTF和lr三个步骤。在定义评估器的过程中,并不涉及实际数据的操作,我理解的是先定义结构,再训练数据。
  3. 有了这些处理特定问题的转换器和评估器之后,接下来就可以按照具体的处理逻辑有序的组织PipelineStages 并创建一个Pipeline。
  4. 在模型构建好以后,创建测试数据集
  5. 调用我们训练好的PipelineModel的transform()方法,让测试数据按顺序通过拟合的工作流,生成我们所需要的预测结果。

结果如下:

通过上述结果,我们可以看到,第4句和第6句中都包含”spark”,其中第六句的预测是1,与我们希望的相符;而第4句虽然预测的依然是0,但是通过概率我们可以看到,第4句有46%的概率预测是1,而第5句、第7句分别只有7%和2%的概率预测为1,这是由于训练数据集较少,如果有更多的测试数据进行学习,预测的准确率将会有显著提升。

参考:
http://dblab.xmu.edu.cn/blog/1459-2/

原创粉丝点击