Spark ML PipeLineスタディノート

spark.mlパッケージの目標は、統一された高レベルAPIを提供することです。これらの高レベルAPIは、ユーザーが実用的な機械学習パイプラインを作成および調整するのに役立つDataFrameに基づいて構築されています。固有の機能コンバーターやパイプラインAPIのコレクションなど、以下のspark.mlサブパッケージガイドのアルゴリズムガイドの部分をご覧ください。

目次:
パイプラインの主な概念

機械学習アルゴリズムの場合、spark ML標準化APIにより、複数のアルゴリズムを同じパイプラインまたはワークフローに簡単に組み合わせることができます。このセクションでは、spark ML APIによって導入された主な概念を紹介します。パイプラインのコンセプトは、scikit-learnから多くのインスピレーションを受けています。

  • DataFrame:Spark MLは、学習データセットとしてSpark sqlからDataFrameを取得します。たとえば、dfにはテキスト、特徴ベクトル、真のラベル、予測結果の複数の異なる列を含めることができます。


  • コンバーター:コンバーターは、DFを別のDFに変換するアルゴリズムです。たとえば、MLモデルは、機能を持つDataFrameを予測結果を持つDFに変換するコンバーターです。

  • エバリュエーター:エバリュエーターは、コンバーターをDFに適合させるアルゴリズムです。例:学習アルゴリズムはエバリュエーターであり、DFでトレーニングし、モデルを生成します。


  • パイプライン:パイプラインは、複数のコンバーターとエバリュエーターをワークフローとして接続します。

  • パラメーター:指定されたパラメーターについて、すべてのコンバーターとエバリュエーターは共通のAPIを共有します。

DataFrame
機械学習は、ベクター、テキスト、画像、構造化データなど、多くのデータタイプに適用できます。MLはDFを使用して複数のデータ型をサポートします。
dfは、多くの基本型と構造型をサポートし、spark sqlの型とベクトルをサポートします。
DFは、従来のRDDから明示的または暗黙的に作成できます。詳細について
は、コードdfの列を参照してください 以下の例のコード名は、「テキスト」、「機能」、および「ラベルとして用いる。」

コンジットアセンブリコンバータ
含む変換 特性コンバータ及び学習モデルの 抽象化。技術的には、コンバーターはDFを変換するためにtransform()メソッドを実行します。通常、1つ以上の列が追加されます。例:
  • 機能コンバーターはDFを取得し、列を読み取って新しい列にマップします。次に、マップされた列を含む新しいDFを出力します。
  • 学習モデルはDFを取得します。特徴ベクトルを含む列を読み取り、各特徴ベクトルのラベルを予測し、予測されたラベルを新しい列として配置してDFに出力します。
評価者
評価者データ上のアプリケーションやトレーニングアルゴリズムの抽象的な概念。技術的には、エバリュエーターはfit()メソッドを呼び出します。このメソッドはDFを受け取り、モデルを生成します。このモデルはコンバーターです。例:ロジスティック回帰などの学習アルゴリズムはEstimatorsであり、モデルであるトランスフォーマーであるLogisticRegressionModelをトレーニングするためにfit()メソッドが呼び出されます。

パイプラインコンポーネントのプロパティ
Transformer.transform()sおよびEstimator.fit()sはどちらもステートレスです。将来、ステートフルアルゴリズムは別の概念でサポートできるようになります。
TransformerまたはEstimatorの各インスタンスには一意のIDがあり、パラメーターを指定するときに役立ちます(以下で説明します)。

パイプラインの

機械学習では、通常、プロセスデータへの一連のアルゴリズムを実行し、学びます。例:単純なテキストドキュメント処理ワークフローには、いくつかの段階を含めることができます。

  • ドキュメント内のテキストを単語に分割します。
  • ドキュメント内の各単語をデジタル化された特徴ベクトルに変換します
  • 特徴ベクトルとラベルを使用して、予測モデルを学習します。
spark MLはワークフローをパイプラインとして記述します。パイプラインは、指定された順序で実行される一連のPipelineStage(トランスフォーマーおよびエスティメータ)で構成されています。このパートでは、この単純なワークフローを実行例として使用します

仕組み

パイプラインは一連のステージとして指定され、各ステージはトランスフォーマーまたはエスティメータです。これらのステージは規則正しく動作し、入力DFは通過する各ステージによって変換されます。Transformerステージの場合、dfでtransform()メソッドが呼び出されます。Estimatorステージの場合、fit()メソッドが呼び出されて新しいTransformerが生成され(コンバーターはPipelineModelの一部または適切なパイプラインになります)、コンバーターはtransform()メソッドを呼び出しますdfに適用されます。

次の図は、単純なテキストドキュメントワークフローで示しています。パイプラインのトレーニング時間の使用状況を示しています。



上の行は、3つのステージを含むパイプラインを表しています。最初の2つの青(TokenizerとHashingTF)はコンバーターで、3番目のLogisticRegressionはエバリュエーターです。一番下の行は、パイプラインを通るデータフローを表しています。シリンダーはDFです。Pipeline.fit()メソッドは、ラインテキストとラベルである最初のdfで呼び出されます。Tokenizer.transform()メソッドは、テキストの行を単語に分割し、単語を含む新しい列をDFに追加します。HashingTF.transform()メソッドは、word列を特徴ベクトルに変換し、そのベクトルを含む新しい列をDFに追加します。LogisticRegressionがエバリュエーターになったので、パイプラインは最初にLogisticRegression.fit()を呼び出してLogisticRegressionModelを生成します。パイプラインに複数のステージがある場合、次のステージにdfを渡す前にLogisticRegressionModelのtransform()メソッドを呼び出します。


パイプラインはエバリュエーターであるため、パイプラインのfit()メソッドが実行されると、コンバーターであるPipelineModelが生成されます。このPipelineModelはテスト時に使用されます。次の図は、PipelineModelの使用法を示しています。



上の図では、PipelineModelと元のパイプラインステージの数は同じです。しかし、元のパイプラインでは、すべてのエバリュエーターがコンバーターになります。PipelineModelの変換()がテストデータセットで呼び出されると、データは適切なパイプラインを順番に通過します。各ステージの変換()はデータセットを更新してから、次のステージに渡します。

PipelineとPipelineModelは、トレーニングセットとテストセットが同じ特徴処理ステップを取得することを保証します。

詳細な
DAGパイプライン:パイプラインの複数のステージは、順序付けされた配列として指定されます。上記の例は、線形パイプラインの例を示しています。パイプラインのステージで使用されるデータは、前のステージによって生成されます。データフローグラフがDAGグラフである限り、非線形パイプラインを作成することもできます。DAGチャートは、各ステージの入出力の列名に基づいて暗黙的に指定できます。パイプラインがDAGの形式である場合は、ステージのトポロジシーケンスを指定する必要があります。

ランタイム検出:パイプラインは複数のタイプのデータフレームで動作できるため、コンパイル時のタイプ検出は実行できません。PipelinesとPipelineModelは実行時に検出されます。検出にはDataFrameのスキーマを使用します。
一意のパイプラインステージ:パイプラインステージは一意のインスタンスである必要があります。例:パイプラインには一意のIDが必要なため、同じmyHashingインスタンスをパイプラインに2回挿入することはできません。ただし、インスタンスが異なると異なるIDが生成されるため、インスタンスの2つのインスタンス(myHashingTF1とmyHashingTF2)を同じパイプラインに配置できます。


パラメータ

MLのEstimatorとTransformerは、同じAPIを使用してパラメーターを指定します。
パラメータ名Paramはパラメータであり、ParamMapはパラメータセット(parameter、value)
です。パラメータをアルゴリズムに渡すには、主に次の2つの方法があり
ます。1.インスタンスのパラメータを設定します。例:lrがLogisticRegressionのインスタンスの場合。lr.setMaxIter(10)を設定すると、lr.fit()を最大10回反復できます。このAPIは、spark.mllibパッケージのAPIを統合します。
2. ParamMapをfit()またはtransform()メソッドに渡します。ParamMapのパラメーターは、setterメソッドによって以前に設定されたパラメーターをオーバーライドします。
パラメータは、指定されたEstimatorsおよびTransformerインスタンスに属します。たとえば、2つのロジスティック回帰lr1とlr2がある場合、2つのmaxIterパラメータを含むParamMapを作成できます:ParamMap(lr1.maxIter-> 10、lr2.maxIter-> 20)。これは、両方のアルゴリズムのパイプラインにmaxIterパラメータがある場合に役立ちます。


保存と読み込みのパイプは

次の時間が貴重で使用するためには、モデルやディスクへのパイプラインを保存します。スパーク1.6で。モデルのインポートおよびエクスポート機能がパイプラインAPIに追加されました。いくつかの基本的な学習モデルと同様に、ほとんどの基本的なトランスフォーマーがサポートされています。アルゴリズムAPIのドキュメントを参照して、保存と読み込みがサポートされているかどうかを確認してください。


コード例:

このセクションでは、上記の機能を説明するためのコードをいくつか示します。詳細については、APIを参照してください。一部のSpark MLアルゴリズムは、spark.mllibアルゴリズムのラッパーです。詳細については、MLlibプログラミングガイドをご覧ください。

例:Estimator、Transformer、およびParam



このセクションでは、Estimator、Transformer、およびParamについて説明します

import org.apache.spark.ml.classification.LogisticRegression
import org.apache.spark.ml.param.ParamMap
import org.apache.spark.mllib.linalg.{Vector, Vectors}
import org.apache.spark.sql.Row
// Prepare training data from a list of (label, features) tuples.
//准备带标签和特征的数据
val training = sqlContext.createDataFrame(Seq(
  (1.0, Vectors.dense(0.0, 1.1, 0.1)),
  (0.0, Vectors.dense(2.0, 1.0, -1.0)),
  (0.0, Vectors.dense(2.0, 1.3, 1.0)),
  (1.0, Vectors.dense(0.0, 1.2, -0.5))
)).toDF("label", "features")

// Create a LogisticRegression instance.  This instance is an Estimator.
//创建一个逻辑回归事例,这个实例是评估器
val lr = new LogisticRegression()
// Print out the parameters, documentation, and any default values.
//输出参数等默认值
println("LogisticRegression parameters:\n" + lr.explainParams() + "\n")

// We may set parameters using setter methods.
//使用setter方法设置参数
lr.setMaxIter(10)
  .setRegParam(0.01)

// Learn a LogisticRegression model.  This uses the parameters stored in lr.
//使用存储在lr中的参数来,学习一个模型,
val model1 = lr.fit(training)
// Since model1 is a Model (i.e., a Transformer produced by an Estimator),
// we can view the parameters it used during fit().
// This prints the parameter (name: value) pairs, where names are unique IDs for this
// LogisticRegression instance.
//由于model1是一个模型,(也就是,一个评估器产生一个转换器),
// 我们可以看lr在fit()上使用的参数。
//输出这些参数对,参数里的names是逻辑回归实例的唯一id
println("Model 1 was fit using parameters: " + model1.parent.extractParamMap)

// We may alternatively specify parameters using a ParamMap,
// which supports several methods for specifying parameters.
//我们可以使用paramMap选择指定的参数,并且提供了很多方法来设置参数
val paramMap = ParamMap(lr.maxIter -> 20)
  .put(lr.maxIter, 30) // Specify 1 Param.  This overwrites the original maxIter. 指定一个参数。
  .put(lr.regParam -> 0.1, lr.threshold -> 0.55) // Specify multiple Params. 指定多个参数

// One can also combine ParamMaps.
val paramMap2 = ParamMap(lr.probabilityCol -> "myProbability") // Change output column name 改变输出列的名称
val paramMapCombined = paramMap ++ paramMap2

// Now learn a new model using the paramMapCombined parameters.
// paramMapCombined overrides all parameters set earlier via lr.set* methods.
//使用新的参数学习模型。
val model2 = lr.fit(training, paramMapCombined)
println("Model 2 was fit using parameters: " + model2.parent.extractParamMap)

// Prepare test data.
//准备测试数据
val test = sqlContext.createDataFrame(Seq(
  (1.0, Vectors.dense(-1.0, 1.5, 1.3)),
  (0.0, Vectors.dense(3.0, 2.0, -0.1)),
  (1.0, Vectors.dense(0.0, 2.2, -1.5))
)).toDF("label", "features")

// Make predictions on test data using the Transformer.transform() method.
// LogisticRegression.transform will only use the 'features' column.
// Note that model2.transform() outputs a 'myProbability' column instead of the usual
// 'probability' column since we renamed the lr.probabilityCol parameter previously.
//使用转换器的transform()方法在测试数据上作出预测.
// 逻辑回归的transform方法只使用“特征”列.
// 注意model2.transform()方法输出的是myProbability列而不是probability列,因为在上面重命名了lr.probabilityCol 参数。
model2.transform(test)
  .select("features", "label", "myProbability", "prediction")
  .collect()
  .foreach { case Row(features: Vector, label: Double, prob: Vector, prediction: Double) =>
  println(s"($features, $label) -> prob=$prob, prediction=$prediction")
}
個人的に考える:このトレーニングプロセスの最後のステップは、アルゴリズムをよりよく機能させるためのパラメーターを設定することです。はい

例:パイプライン



この例は、上の図に示されているテキストドキュメントパイプラインです。


import org.apache.spark.ml.{Pipeline, PipelineModel}
import org.apache.spark.ml.classification.LogisticRegression
import org.apache.spark.ml.feature.{HashingTF, Tokenizer}
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.sql.Row
// Prepare training documents from a list of (id, text, label) tuples.
//准备训练文档,(id,内容,标签)
val training = sqlContext.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")

// Configure an ML pipeline, which consists of three stages: tokenizer, hashingTF, and lr.
//配置ML管道,由三个stage组成,tokenizer, hashingTF, and lr ,
val tokenizer = new Tokenizer()
  .setInputCol("text")
  .setOutputCol("words")
val hashingTF = new HashingTF()
  .setNumFeatures(1000)
  .setInputCol(tokenizer.getOutputCol)
  .setOutputCol("features")
val lr = new LogisticRegression()
  .setMaxIter(10)
  .setRegParam(0.01)
val pipeline = new Pipeline()
  .setStages(Array(tokenizer, hashingTF, lr))

// Fit the pipeline to training documents.
//安装管道到数据上
val model = pipeline.fit(training)

// now we can optionally save the fitted pipeline to disk
//现在可以保存安装好的管道到磁盘上
model.save("/tmp/spark-logistic-regression-model")

// we can also save this unfit pipeline to disk
//也可以保存未安装的管道到磁盘上
pipeline.save("/tmp/unfit-lr-model")

// and load it back in during production
//加载管道
val sameModel = PipelineModel.load("/tmp/spark-logistic-regression-model")

// Prepare test documents, which are unlabeled (id, text) tuples.
//准备测试文档,不包含标签
val test = sqlContext.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.
//在测试文档上做出预测
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")
}

例:交差検証によるモデルの選択




機械学習における重要なタスクは、モデルの選択、またはデータを使用してタスクに最適なモデルまたは設定パラメーターを見つけることです。これはチューニングと呼ばれます。パイプライン内の各要素を個別に調整するよりも、パイプライン全体を調整することにより、パイプライン選択モデルを促進する方が簡単です。
現在、spark.mlは、クロスバリデーター CrossValidator クラス選択モデルをサポートしてい ます。このクラスは、Estimator、パラメーターセット、およびエバリュエーターを受け取ります。CrossValidatorは、データセットをフォールドセットに分割し始めます。このフォールドセットは、個別のテストおよびトレーニングとして使用されます。データセット;例:3分割のCrossValidatorは、3セットの(トレーニング、テスト)データセットを生成し、各データセットはトレーニングデータとして2/3、テストデータとして1/3です。パラメーターセットによるCrossValidator反復計算。ParamMapごとに、指定されたEstimatorをトレーニングし、指定されたEvaluatorを使用して評価します。

RegressionEvaluator は回帰問題を評価し BinaryClassificationEvaluator はバイナリデータを評価し MultiClassClassificationEvaluator は多変量分類問題を評価します。
最適なparaMapパラメータを選択するために使用されるデフォルトのメトリックは、EvaluatorのsetMetricメソッドによってオーバーライドできます。

最良の評価メトリックを生成するparamMapが最良のモデルとして選択されます。最終的に、CrossValidatorは最適なparamMapとデータセット全体の評価エバリュエーター(エバリュエーターを実行するfitメソッドを意味

します)を使用します次の例は、グリッドパラメーターから選択するCrossValidatorです。使用のみ ParamGridBuilder ツールは、パラメトリックグリッドを構築します。
グリッドパラメータのクロスチェックは非常に負荷が高いことに注意してください。たとえば、次の例では、hashingTF.numFeaturesに3つの値があり、lr.regParamに2つの値のパラメーターネットワークがあり、CrossValidatorフォールドは2です。この乗算の出力は(3×2)×2 = 12です。さまざまな詳細をトレーニングする必要があります。実際の設定では、パラメーターはより大きく設定され、フォールドが多くなります(通常は3または10)。言い換えれば。CorssValidatorの使用は非常に高価です。
ただし、パラメータを選択するための有効な方法でもあります。

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.tuning.{ParamGridBuilder, CrossValidator}
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.sql.Row
    // Prepare training data from a list of (id, text, label) tuples.
    //准备训练数据,id 内容,标签
    val training = sqlContext.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.
//    配置机器学习管道,由tokenizer, hashingTF,  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.
    //使用ParamGridBuilder 构造一个参数网格,
    //hashingTF.numFeatures有3个值,lr.regParam有2个值,
    // 这个网格有6个参数给CrossValidator来选择
    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.
    //现在我们把管道看做成一个Estimator,把它包装到CrossValidator实例中。
    //这可以让我们连带的为管道的所有stage选择参数。
    //CrossValidator需要一个Estimator,一个评估器参数集合,和一个Evaluator。
    //注意这里的evaluator 是二元分类的BinaryClassificationEvaluator,它默认的度量是areaUnderROC.
    val cv = new CrossValidator()
      .setEstimator(pipeline)
      .setEvaluator(new BinaryClassificationEvaluator)
      .setEstimatorParamMaps(paramGrid)
      .setNumFolds(2) // Use 3+ in practice  // 在实战中使用3+

    // 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 = sqlContext.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是选择出来的最好的模型
    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")
    }

個人的な理解:クロスチェックを使用して、一連のパラメーターから最適なものを自動的に選択し、よく整理されたモデルを構築します。

例:トレイン検証分割によるモデル選択例:トレーニング検証分離によるモデル選択




CrossValidatorに加えて、Sparkはハイパーパラメーター調整用のTrainValidationSplitも提供します。TrainValidationSplitは、各パラメーターの組み合わせを1回だけ評価します。CrossValidatorをk回評価する代わりに、TrainValidationSplitは1回のみです。したがって、それほど高価ではありませんが、トレーニングデータセットが十分に大きくない場合、信頼できる結果を生成できません。

TrainValidationSplitは、Estimator、estimatorParamMapsパラメータを含む一連のparaMap、およびEvaluatorを渡す必要があります。最初にtrainRatioパラメータ値を使用して、データセットをトレーニングデータとテストデータに分割します。例:trainRatio = 0.75(デフォルト)を使用すると、TrainValidationSplitはトレーニング用のデータの75%とテスト用のデータの25%を生成します。CrossValidatorと同様に、TrainValidationSplitもパラメータセットparamMapを反復処理します。各パラメーターの組み合わせについて、指定されたEstimatorでトレーニングし、指定されたEvaluatorで評価します。最良の評価指標を生成するparamMapが最良の選択です。TrainValidationSplitは最終的に、Estimatorを使用してデータセット全体の最適なパラメーターと近似メソッドを使用します。




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 = sqlContext.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()

// 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.
//ParamGridBuilder构建一组参数
//TrainValidationSplit将尝试从这些所有值的组合中使用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.
//在这里estimator是简单的线性回归
//TrainValidationSplit 需要一个Estimator , 一个Estimator ParamMaps集,一个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.
  //80%数据作为训练,剩下的20%作为验证
  .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()
元の記事を30件公開 賞賛された74件 230,000回の閲覧+

おすすめ

転載: blog.csdn.net/ruiyiin/article/details/75909677