Spark系列--Mlib(1)

ML Pipelines(ML管道)

Pipelines的主要概念

MLlib 将机器学习算法的API标准化,以便将多种算法更容易地组合成单个 Pipeline (管道)或者工作流。本节介绍Pipelines API 的关键概念,其中 Pipeline(管道)的概念主要是受到 scikit-learn 项目的启发.

  • DataFrame(数据模型):ML API 将从Spark SQL查出来的 DataFrame 作为 ML 的数据集,数据集支持许多数据类型。例如,一个 DataFrame 可以有不同的列储存 text(文本)、feature(特征向量)、true labels(标注)、predictions(预测结果)等机器学习数据类型.
  • Transformer(转换器):使用 Transformer 将一个 DataFrame 转换成另一个 DataFrame 的算法,例如,一个 ML Model 是一个 Transformer,它将带有特征的 DataFrame 转换成带有预测结果的 DataFrame.
  • Estimator(模型学习器):Estimator 是一个适配 DataFrame 来生成 Transformer(转换器)的算法.例如,一个学习算法就是一个 Estimator 训练 DataFrame 并产生一个模型的过程.
  • Pipeline(管道):Pipeline 将多个 Transformer和 Estimators 绑在一起形成一个工作流.
  • Parameter(参数):所有的 Transformer和 Estimator都已经使用标准的 API 来指定参数.

DataFrame

机器学习可以应用于各种各样的数据类型,比如向量,文本,图形和结构化数据.API 采用 Spark Sql 的 DataFrame 就是为了支持各种各样的数据类型.

DataFrame 支持许多基本的结构化的数据,参考Spark SQL datatype reference上的一系列支持的类型。另外除了 Spark SQL guide 列举的类型,DataFrame 还支持使用 ML Vector 类型.

DataFrame 可以用标准的 RDD 显式或者非显式创建。请参考下面的例子,或者前往 Spark SQL programming guide 查看例子

DataFrame 中的列是有名称的.下面的代码示例会使用名称如 "文本","特征"和"标签".

 

Pipelines 组件

Transformers(转换器)

 转换器是特征变换和机器学习模型的抽象。转换器必须实现transform方法,这个方法将一个 DataFrame 转换成另一个 DataFrame,通常是附加一个或者多个列。比如:

  • 一个特征变换器是输入一个 DataFrame,读取一个列(比如:text),将其映射成一个新列(比如,特征向量),然后输出一个新的 DataFrame 并包含这个映射的列.
  • 一个机器学习模型是输入一个 DataFrame,读取包含特征向量的列,预测每个特征向量的标签,并输出一个新的 DataFrame ,并附加预测标签作为一列.

Estimators(模型学习器)

Estimators 模型学习器是拟合和训练数据的机器学习算法或者其他算法的抽象。技术上来说, Estimator(模型学习器)实现 fit() 方法,这个方法输入一个 DataFrame 并产生一个 Model 即一个 Transformer(转换器)。举个例子,一个机器学习算法是一个 Estimator 模型学习器,比如这个算法是 LogisticRegression(逻辑回归),调用 fit() 方法训练出一个 LogisticRegressionModel,这是一个 Model,因此也是一个 Transformer(转换器).

Pipeline组件的参数

Transformer.transform() 和 Estimator.fit() 都是无状态。以后,可以通过替换概念来支持有状态算法.

每一个 Transformer(转换器)和 Estimator (模型学习器)都有一个唯一的ID,这在指定参数上非常有用(将在下面进行讨论).

 

Pipeline

在机器学习中,通常会执行一系列算法来处理和学习模型,比如,一个简单的文本文档处理流程可能包括这几个步骤:

  • 把每个文档的文本分割成单词.
  • 将这些单词转换成一个数值型特征向量.
  • 使用特征向量和标签学习一个预测模型.

MLlib 代表一个流水线,就是一个 Pipeline(管道)Pipeline(管道) 包含了一系列有特定顺序的管道步骤(Transformers(转换器) 和 Estimators(模型学习器))。我们将使用这个简单的工作流作为本节的运行示例.

如何工作

一个 pipeline 由多个步骤组成,每一个步骤都是一个 Transformer(转换器)或者 Estimator(模型学习器)。这些步骤按顺序执行,输入的 DataFrame 在通过每个阶段时进行转换。在 Transformer (转换器)步骤中,DataFrame 会调用 transform() 方法;在 Estimator(模型学习器)步骤中,fit() 方法被调用并产生一个 Transformer(转换器)(会成为 PipelineModel(管道模型)的一部分,或者适配 Pipeline ),并且 DataFrame 会调用这个 Transformer’s(转换器)的transform()方法.

我们通过简单的文本文档工作流来说明.

下图是显示了使用管道的训练流程

 

 

 

package com.demo.cn.mlib

import org.apache.spark.ml.classification.GBTClassifier
import org.apache.spark.sql.SparkSession
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.classification.LogisticRegression
import org.apache.spark.ml.evaluation.BinaryClassificationEvaluator
import org.apache.spark.ml.feature.{HashingTF, Tokenizer}
import org.apache.spark.ml.linalg.Vector
import org.apache.spark.ml.tuning.{CrossValidator, ParamGridBuilder}
import org.apache.spark.sql.Row

object LRCorss {

  def main(args: Array[String]): Unit = {

    val spark=SparkSession
      .builder()
      .master("local[*]")
      .appName("LRCorss")
      .getOrCreate()
    // Prepare training data from a list of (id, text, label) tuples.
    val training = 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),
      (4L, "b spark who", 1.0),
      (5L, "g d a y", 0.0),
      (6L, "spark fly", 1.0),
      (7L, "was mapreduce", 0.0),
      (8L, "e spark program", 1.0),
      (9L, "a e c l", 0.0),
      (10L, "spark compile", 1.0),
      (11L, "hadoop software", 0.0)
    )).toDF("id", "text", "label")

    // Configure an ML pipeline, which consists of three stages: tokenizer, hashingTF, and lr.
    val tokenizer = new Tokenizer()
      .setInputCol("text")
      .setOutputCol("words")
    val hashingTF = new HashingTF()
      .setInputCol(tokenizer.getOutputCol)
      .setOutputCol("features")
    val lr = new LogisticRegression()
      .setMaxIter(10)
    val pipeline = new Pipeline()
      .setStages(Array(tokenizer, hashingTF, lr))

    // We use a ParamGridBuilder to construct a grid of parameters to search over.
    // With 3 values for hashingTF.numFeatures and 2 values for lr.regParam,
    // this grid will have 3 x 2 = 6 parameter settings for CrossValidator to choose from.
    val paramGrid = new ParamGridBuilder()
      .addGrid(hashingTF.numFeatures, Array(10, 100, 1000))
      .addGrid(lr.regParam, Array(0.1, 0.01))
      .build()

    // We now treat the Pipeline as an Estimator, wrapping it in a CrossValidator instance.
    // This will allow us to jointly choose parameters for all Pipeline stages.
    // A CrossValidator requires an Estimator, a set of Estimator ParamMaps, and an Evaluator.
    // Note that the evaluator here is a BinaryClassificationEvaluator and its default metric
    // is areaUnderROC.
    val cv = new CrossValidator()
      .setEstimator(pipeline)
      .setEvaluator(new BinaryClassificationEvaluator)
      .setEstimatorParamMaps(paramGrid)
      .setNumFolds(2)  // Use 3+ in practice

    //交叉验证会选择一个参数值最好的模型
    // Run cross-validation, and choose the best set of parameters.
    val cvModel = cv.fit(training)


    // Prepare test documents, which are unlabeled (id, text) tuples.
    val test = spark.createDataFrame(Seq(
      (4L, "spark i j k"),
      (5L, "l m n"),
      (6L, "mapreduce spark"),
      (7L, "apache hadoop")
    )).toDF("id", "text")

    // Make predictions on test documents. cvModel uses the best model found (lrModel).
    cvModel.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")
      }

  }

}

执行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值