页面树结构

2017-07-25 Apache Spark 2.2.0 官方文档中文版发布 : http://spark.apachecn.org/docs/cn/2.2.0/


MachineLearning 优酷地址 : http://i.youku.com/apachecn

转至元数据结尾
转至元数据起始
本节介绍如何使用MLlib的工具来调整ML算法和管道。
内置的交叉-验证和其他工具允许用户优化算法和流水线中的超参数。
目录

模型选择(a.k.a.超参数调整)

ML中的一个重要任务是模型选择,或使用数据找到给定任务的最佳模型或参数。这也叫调优。可以针对个体估算器(如Logistic回归)或包括多个算法,特征化和其他步骤的整个管道完成调整。用户可以一次调整整个流水线,而不是单独调整管道中的每个元素。

MLlib支持使用 CrossValidatorTrainValidationSplit等工具进行模型选择。这些工具需要以下项目:

在高层次上,这些模型选择工具的工作如下:

  • 他们将输入数据分成单独的培训和测试数据集。
  • 对于每个(训练,测试)对,他们遍历一组ParamMaps:
    • 对于每个ParamMap,它们使用这些参数适合Estimator,获得拟合的Model,并使用Evaluator评估Model的性能。
  • 他们选择由最佳性能参数组合生成的模型。

评估者可以是回归问题的RegressionEvaluator,二进制数据的BinaryClassificationEvaluator或多类问题的MulticlassClassificationEvaluator。用于选择最佳ParamMap的默认度量可以被这些评估器中的每一个的setMetricName方法覆盖。

为了帮助构建参数网格,用户可以使用ParamGridBuilder实用程序。

 

交叉-验证

CrossValidator首先将数据集分成一组折叠,这些折叠用作单独的训练和测试数据集。 例如,k = 3倍,CrossValidator将生成3个(训练,测试)数据集对,每个数据集使用2/3的数据进行训练,1/3进行测试。 为了评估一个特定的ParamMap,CrossValidator通过在3个不同的(训练,测试)数据集对上拟合Estimator来计算3个模型的平均评估度量。

在确定最佳ParamMap之后,CrossValidator最终使用最好的ParamMap和整个数据集重新拟合Estimator。

示例:通过交叉-验证进行模型选择

以下示例演示如何使用CrossValidator从参数网格中进行选择。

请注意,通过参数网格的交叉验证是昂贵的。 例如,在下面的示例中,参数网格具有3个值,用于hashingTF.numFeatures,2个值用于lr.regParam,CrossValidator使用2个折叠。 这被乘以 (3×2)×2 = 12个不同的模型被训练。 在现实的设置中,尝试更多的参数并使用更多的折叠(k = 3和k = 10是常见的)是常见的。 换句话说,使用CrossValidator可能是非常昂贵的。 然而,它也是一种成熟的方法,用于选择比启发式手动调谐更具统计学意义的参数。

有关API的详细信息,请参阅[`CrossValidator` Scala docs](api/scala/index.html#org.apache.spark.ml.tuning.CrossValidator)

Scala
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

// 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")
  }

 查找Spark repo中的“examples/src/main/scala/org/apache/spark/examples/ml/ModelSelectionViaCrossValidationExample.scala”的完整示例代码。


火车-验证 拆分

除了CrossValidator Spark,还提供了用于超参数调整的TrainValidationSplit。 TrainValidationSplit仅对参数的每个组合进行一次评估,而在CrossValidator的情况下,则不是k次。 因此,它较便宜,但在训练数据集不够大时不会产生可靠的结果。

与CrossValidator不同,TrainValidationSplit创建一个(训练,测试)数据集对。 它使用trainRatio参数将数据集分成这两个部分。 例如,trainRatio = 0.75,TrainValidationSplit将生成训练和测试数据集对,其中75%的数据用于培训,25%用于验证。

像CrossValidator一样,TrainValidationSplit最终适合使用最好的ParamMap和整个数据集的Estimator。

示例:通过列车验证拆分模型选择

有关API的详细信息,请参阅TrainValidationSplit Scala文档

Scala
import org.apache.spark.ml.evaluation.RegressionEvaluator
import org.apache.spark.ml.regression.LinearRegression
import org.apache.spark.ml.tuning.{ParamGridBuilder, TrainValidationSplit}

// Prepare training and test data.
val data = spark.read.format("libsvm").load("data/mllib/sample_linear_regression_data.txt")
val Array(training, test) = data.randomSplit(Array(0.9, 0.1), seed = 12345)

val lr = new LinearRegression()
    .setMaxIter(10)

// We use a ParamGridBuilder to construct a grid of parameters to search over.
// TrainValidationSplit will try all combinations of values and determine best model using
// the evaluator.
val paramGrid = new ParamGridBuilder()
  .addGrid(lr.regParam, Array(0.1, 0.01))
  .addGrid(lr.fitIntercept)
  .addGrid(lr.elasticNetParam, Array(0.0, 0.5, 1.0))
  .build()

// In this case the estimator is simply the linear regression.
// A TrainValidationSplit requires an Estimator, a set of Estimator ParamMaps, and an Evaluator.
val trainValidationSplit = new TrainValidationSplit()
  .setEstimator(lr)
  .setEvaluator(new RegressionEvaluator)
  .setEstimatorParamMaps(paramGrid)
  // 80% of the data will be used for training and the remaining 20% for validation.
  .setTrainRatio(0.8)

// Run train validation split, and choose the best set of parameters.
val model = trainValidationSplit.fit(training)

// Make predictions on test data. model is the model with combination of parameters
// that performed best.
model.transform(test)
  .select("features", "label", "prediction")
  .show()

在Spark repo中的“examples/src/main/scala/org/apache/spark/examples/ml/ModelSelectionViaTrainValidationSplitExample.scala”中查找完整示例代码。


  • 无标签