アンサンブル - RDDベースのAPI
アンサンブル法は、他のベースモデルの集合で構成されるモデルを作成する学習アルゴリズムです。 spark.mllib
は、2つの主要なアンサンブルアルゴリズム、GradientBoostedTrees
とRandomForest
をサポートしています。どちらもベースモデルとして決定木を使用します。
勾配ブースティング木とランダムフォレスト
勾配ブースティング木 (GBT)とランダムフォレストはどちらも木のアンサンブルを学習するためのアルゴリズムですが、トレーニングプロセスが異なります。いくつかの実際的なトレードオフがあります。
- GBTは一度に1本の木をトレーニングするため、ランダムフォレストよりもトレーニングに時間がかかる場合があります。ランダムフォレストは複数の木を並列にトレーニングできます。
- 一方、GBTではランダムフォレストよりも小さい(浅い)木を使用するのが合理的であり、小さい木のトレーニングには時間がかかりません。
- ランダムフォレストは過学習を起こしにくい可能性があります。ランダムフォレストでより多くの木をトレーニングすると過学習の可能性が低くなりますが、GBTでより多くの木をトレーニングすると過学習の可能性が高くなります。(統計用語では、ランダムフォレストはより多くの木を使用することで分散を削減しますが、GBTはより多くの木を使用することでバイアスを削減します。)
- ランダムフォレストは、木の数が増えるにつれてパフォーマンスが単調に verbessert werdenため、チューニングが容易になる可能性があります(一方、GBTでは、木の数が多すぎるとパフォーマンスが低下し始める可能性があります)。
要するに、どちらのアルゴリズムも効果的であり、選択は特定のデータセットに基づいて行う必要があります。
ランダムフォレスト
ランダムフォレストは決定木のアンサンブルです。ランダムフォレストは、分類と回帰のための最も成功した機械学習モデルの1つです。過学習のリスクを 줄이기 위해多くの決定木を組み合わせます。決定木と同様に、ランダムフォレストはカテゴリ特徴量を処理し、多クラス分類設定に拡張し、特徴量のスケーリングを必要とせず、非線形性と特徴量の相互作用を捉えることができます。
spark.mllib
は、連続特徴量とカテゴリ特徴量の両方を使用して、バイナリおよび多クラス分類と回帰のためのランダムフォレストをサポートしています。 spark.mllib
は、既存の決定木実装を使用してランダムフォレストを実装しています。木についての詳細は、決定木のガイドを参照してください。
基本アルゴリズム
ランダムフォレストは決定木のセットを個別にトレーニングするため、トレーニングは並列に実行できます。アルゴリズムはトレーニングプロセスにランダム性を注入するため、各決定木は少し異なります。各木の予測を組み合わせることで、予測の分散が削減され、テストデータのパフォーマンスが向上します.
トレーニング
トレーニングプロセスに注入されるランダム性には、次のものが含まれます。
- 反復ごとに元のデータセットをサブサンプリングして、異なるトレーニングセットを取得します(別名、ブートストラップ)。
- 各ツリーノードで分割の候補として使用する特徴量の異なるランダムサブセットを検討します。
これらのランダム化とは別に、決定木のトレーニングは個々の決定木の場合と同じ方法で行われます。
予測
新しいインスタンスの予測を行うには、ランダムフォレストは決定木のセットからの予測を集約する必要があります。この集約は、分類と回帰で異なって行われます。
分類: 多数決。各木の予測は、1つのクラスへの投票としてカウントされます。ラベルは、最も多くの投票を受けたクラスとして予測されます。
回帰: 平均。各木は実数値を予測します。ラベルは、木の予測の平均として予測されます。
使用上のヒント
さまざまなパラメータについて説明することで、ランダムフォレストを使用するためのいくつかのガイドラインを紹介します。決定木のパラメータの一部は決定木のガイドで説明されているため、ここでは省略します。
最初に述べる2つのパラメータが最も重要であり、これらのパラメータを調整することでパフォーマンスが向上することがよくあります。
numTrees
: フォレスト内の木の数。- 木の数を増やすと、予測の分散が減少し、モデルのテスト時の精度が向上します。
- トレーニング時間は木の数にほぼ比例して増加します。
maxDepth
: フォレスト内の各木の最大深度。- 深度を大きくすると、モデルの表現力と能力が高まります.ただし、深い木はトレーニングに時間がかかり、過学習を起こしやすいです。
- 一般に、単一の決定木を使用する場合よりも、ランダムフォレストを使用する場合に、より深い木をトレーニングすることは許容されます。1つの木は、ランダムフォレストよりも過学習を起こしやすいです(フォレスト内の複数の木の平均化による分散の減少のため)。
次の2つのパラメータは、一般的に調整する必要はありません。ただし、トレーニングを高速化するために調整できます。
-
subsamplingRate
: このパラメータは、フォレスト内の各木のトレーニングに使用されるデータセットのサイズを、元のデータセットのサイズの割合として指定します。デフォルト(1.0)が推奨されますが、この割合を減らすとトレーニングを高速化できます。 -
featureSubsetStrategy
: 各ツリーノードで分割の候補として使用する特徴量の数を指定します。この数値は、特徴量の総数の割合または関数として指定されます。この数を減らすとトレーニングが高速化されますが、低すぎるとパフォーマンスに影響を与える場合があります。
例
分類
以下の例は、LIBSVMデータファイルを読み込み、LabeledPoint
のRDDとして解析し、ランダムフォレストを使用して分類を実行する方法を示しています。テストエラーは、アルゴリズムの精度を測定するために計算されます。
APIの詳細については、RandomForest
PythonドキュメントおよびRandomForest
Pythonドキュメントを参照してください。
from pyspark.mllib.tree import RandomForest, RandomForestModel
from pyspark.mllib.util import MLUtils
# Load and parse the data file into an RDD of LabeledPoint.
data = MLUtils.loadLibSVMFile(sc, 'data/mllib/sample_libsvm_data.txt')
# Split the data into training and test sets (30% held out for testing)
(trainingData, testData) = data.randomSplit([0.7, 0.3])
# Train a RandomForest model.
# Empty categoricalFeaturesInfo indicates all features are continuous.
# Note: Use larger numTrees in practice.
# Setting featureSubsetStrategy="auto" lets the algorithm choose.
model = RandomForest.trainClassifier(trainingData, numClasses=2, categoricalFeaturesInfo={},
numTrees=3, featureSubsetStrategy="auto",
impurity='gini', maxDepth=4, maxBins=32)
# Evaluate model on test instances and compute test error
predictions = model.predict(testData.map(lambda x: x.features))
labelsAndPredictions = testData.map(lambda lp: lp.label).zip(predictions)
testErr = labelsAndPredictions.filter(
lambda lp: lp[0] != lp[1]).count() / float(testData.count())
print('Test Error = ' + str(testErr))
print('Learned classification forest model:')
print(model.toDebugString())
# Save and load model
model.save(sc, "target/tmp/myRandomForestClassificationModel")
sameModel = RandomForestModel.load(sc, "target/tmp/myRandomForestClassificationModel")
APIの詳細については、RandomForest
ScalaドキュメントおよびRandomForestModel
Scalaドキュメントを参照してください。
import org.apache.spark.mllib.tree.RandomForest
import org.apache.spark.mllib.tree.model.RandomForestModel
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
// Split the data into training and test sets (30% held out for testing)
val splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
// Train a RandomForest model.
// Empty categoricalFeaturesInfo indicates all features are continuous.
val numClasses = 2
val categoricalFeaturesInfo = Map[Int, Int]()
val numTrees = 3 // Use more in practice.
val featureSubsetStrategy = "auto" // Let the algorithm choose.
val impurity = "gini"
val maxDepth = 4
val maxBins = 32
val model = RandomForest.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo,
numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins)
// Evaluate model on test instances and compute test error
val labelAndPreds = testData.map { point =>
val prediction = model.predict(point.features)
(point.label, prediction)
}
val testErr = labelAndPreds.filter(r => r._1 != r._2).count.toDouble / testData.count()
println(s"Test Error = $testErr")
println(s"Learned classification forest model:\n ${model.toDebugString}")
// Save and load model
model.save(sc, "target/tmp/myRandomForestClassificationModel")
val sameModel = RandomForestModel.load(sc, "target/tmp/myRandomForestClassificationModel")
APIの詳細については、RandomForest
JavaドキュメントおよびRandomForestModel
Javaドキュメントを参照してください。
import java.util.HashMap;
import java.util.Map;
import scala.Tuple2;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.mllib.regression.LabeledPoint;
import org.apache.spark.mllib.tree.RandomForest;
import org.apache.spark.mllib.tree.model.RandomForestModel;
import org.apache.spark.mllib.util.MLUtils;
SparkConf sparkConf = new SparkConf().setAppName("JavaRandomForestClassificationExample");
JavaSparkContext jsc = new JavaSparkContext(sparkConf);
// Load and parse the data file.
String datapath = "data/mllib/sample_libsvm_data.txt";
JavaRDD<LabeledPoint> data = MLUtils.loadLibSVMFile(jsc.sc(), datapath).toJavaRDD();
// Split the data into training and test sets (30% held out for testing)
JavaRDD<LabeledPoint>[] splits = data.randomSplit(new double[]{0.7, 0.3});
JavaRDD<LabeledPoint> trainingData = splits[0];
JavaRDD<LabeledPoint> testData = splits[1];
// Train a RandomForest model.
// Empty categoricalFeaturesInfo indicates all features are continuous.
int numClasses = 2;
Map<Integer, Integer> categoricalFeaturesInfo = new HashMap<>();
int numTrees = 3; // Use more in practice.
String featureSubsetStrategy = "auto"; // Let the algorithm choose.
String impurity = "gini";
int maxDepth = 5;
int maxBins = 32;
int seed = 12345;
RandomForestModel model = RandomForest.trainClassifier(trainingData, numClasses,
categoricalFeaturesInfo, numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins,
seed);
// Evaluate model on test instances and compute test error
JavaPairRDD<Double, Double> predictionAndLabel =
testData.mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));
double testErr =
predictionAndLabel.filter(pl -> !pl._1().equals(pl._2())).count() / (double) testData.count();
System.out.println("Test Error: " + testErr);
System.out.println("Learned classification forest model:\n" + model.toDebugString());
// Save and load model
model.save(jsc.sc(), "target/tmp/myRandomForestClassificationModel");
RandomForestModel sameModel = RandomForestModel.load(jsc.sc(),
"target/tmp/myRandomForestClassificationModel");
回帰
以下の例は、LIBSVMデータファイルを読み込み、LabeledPoint
のRDDとして解析し、ランダムフォレストを使用して回帰を実行する方法を示しています。平均二乗誤差 (MSE) は、適合度を評価するために最後に計算されます。
APIの詳細については、RandomForest
PythonドキュメントおよびRandomForest
Pythonドキュメントを参照してください。
from pyspark.mllib.tree import RandomForest, RandomForestModel
from pyspark.mllib.util import MLUtils
# Load and parse the data file into an RDD of LabeledPoint.
data = MLUtils.loadLibSVMFile(sc, 'data/mllib/sample_libsvm_data.txt')
# Split the data into training and test sets (30% held out for testing)
(trainingData, testData) = data.randomSplit([0.7, 0.3])
# Train a RandomForest model.
# Empty categoricalFeaturesInfo indicates all features are continuous.
# Note: Use larger numTrees in practice.
# Setting featureSubsetStrategy="auto" lets the algorithm choose.
model = RandomForest.trainRegressor(trainingData, categoricalFeaturesInfo={},
numTrees=3, featureSubsetStrategy="auto",
impurity='variance', maxDepth=4, maxBins=32)
# Evaluate model on test instances and compute test error
predictions = model.predict(testData.map(lambda x: x.features))
labelsAndPredictions = testData.map(lambda lp: lp.label).zip(predictions)
testMSE = labelsAndPredictions.map(lambda lp: (lp[0] - lp[1]) * (lp[0] - lp[1])).sum() /\
float(testData.count())
print('Test Mean Squared Error = ' + str(testMSE))
print('Learned regression forest model:')
print(model.toDebugString())
# Save and load model
model.save(sc, "target/tmp/myRandomForestRegressionModel")
sameModel = RandomForestModel.load(sc, "target/tmp/myRandomForestRegressionModel")
APIの詳細については、RandomForest
ScalaドキュメントおよびRandomForestModel
Scalaドキュメントを参照してください。
import org.apache.spark.mllib.tree.RandomForest
import org.apache.spark.mllib.tree.model.RandomForestModel
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
// Split the data into training and test sets (30% held out for testing)
val splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
// Train a RandomForest model.
// Empty categoricalFeaturesInfo indicates all features are continuous.
val numClasses = 2
val categoricalFeaturesInfo = Map[Int, Int]()
val numTrees = 3 // Use more in practice.
val featureSubsetStrategy = "auto" // Let the algorithm choose.
val impurity = "variance"
val maxDepth = 4
val maxBins = 32
val model = RandomForest.trainRegressor(trainingData, categoricalFeaturesInfo,
numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins)
// Evaluate model on test instances and compute test error
val labelsAndPredictions = testData.map { point =>
val prediction = model.predict(point.features)
(point.label, prediction)
}
val testMSE = labelsAndPredictions.map{ case(v, p) => math.pow((v - p), 2)}.mean()
println(s"Test Mean Squared Error = $testMSE")
println(s"Learned regression forest model:\n ${model.toDebugString}")
// Save and load model
model.save(sc, "target/tmp/myRandomForestRegressionModel")
val sameModel = RandomForestModel.load(sc, "target/tmp/myRandomForestRegressionModel")
APIの詳細については、RandomForest
JavaドキュメントおよびRandomForestModel
Javaドキュメントを参照してください。
import java.util.HashMap;
import java.util.Map;
import scala.Tuple2;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.mllib.regression.LabeledPoint;
import org.apache.spark.mllib.tree.RandomForest;
import org.apache.spark.mllib.tree.model.RandomForestModel;
import org.apache.spark.mllib.util.MLUtils;
import org.apache.spark.SparkConf;
SparkConf sparkConf = new SparkConf().setAppName("JavaRandomForestRegressionExample");
JavaSparkContext jsc = new JavaSparkContext(sparkConf);
// Load and parse the data file.
String datapath = "data/mllib/sample_libsvm_data.txt";
JavaRDD<LabeledPoint> data = MLUtils.loadLibSVMFile(jsc.sc(), datapath).toJavaRDD();
// Split the data into training and test sets (30% held out for testing)
JavaRDD<LabeledPoint>[] splits = data.randomSplit(new double[]{0.7, 0.3});
JavaRDD<LabeledPoint> trainingData = splits[0];
JavaRDD<LabeledPoint> testData = splits[1];
// Set parameters.
// Empty categoricalFeaturesInfo indicates all features are continuous.
Map<Integer, Integer> categoricalFeaturesInfo = new HashMap<>();
int numTrees = 3; // Use more in practice.
String featureSubsetStrategy = "auto"; // Let the algorithm choose.
String impurity = "variance";
int maxDepth = 4;
int maxBins = 32;
int seed = 12345;
// Train a RandomForest model.
RandomForestModel model = RandomForest.trainRegressor(trainingData,
categoricalFeaturesInfo, numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins, seed);
// Evaluate model on test instances and compute test error
JavaPairRDD<Double, Double> predictionAndLabel =
testData.mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));
double testMSE = predictionAndLabel.mapToDouble(pl -> {
double diff = pl._1() - pl._2();
return diff * diff;
}).mean();
System.out.println("Test Mean Squared Error: " + testMSE);
System.out.println("Learned regression forest model:\n" + model.toDebugString());
// Save and load model
model.save(jsc.sc(), "target/tmp/myRandomForestRegressionModel");
RandomForestModel sameModel = RandomForestModel.load(jsc.sc(),
"target/tmp/myRandomForestRegressionModel");
勾配ブースティング木 (GBT)
勾配ブースティング木 (GBT)は、決定木のアンサンブルです。GBTは、損失関数を最小化するために、決定木を反復的にトレーニングします。決定木と同様に、GBTはカテゴリ特徴量を処理し、多クラス分類設定に拡張し、特徴量のスケーリングを必要とせず、非線形性と特徴量の相互作用を捉えることができます。
spark.mllib
は、連続特徴量とカテゴリ特徴量の両方を使用して、バイナリ分類と回帰のためのGBTをサポートしています。 spark.mllib
は、既存の決定木実装を使用してGBTを実装しています。木についての詳細は、決定木のガイドを参照してください。
注: GBTはまだ多クラス分類をサポートしていません。多クラス問題の場合は、決定木またはランダムフォレストを使用してください。
基本アルゴリズム
勾配ブースティングは、決定木のシーケンスを反復的にトレーニングします。反復ごとに、アルゴリズムは現在のアンサンブルを使用して各トレーニングインスタンスのラベルを予測し、予測を真のラベルと比較します。データセットは、予測の不十分なトレーニングインスタンスにより重点を置くように再ラベル付けされます。したがって、次の反復では、決定木は以前の間違いを修正するのに役立ちます。
インスタンスの再ラベル付けの具体的なメカニズムは、損失関数(下記参照)によって定義されます。反復ごとに、GBTはトレーニングデータのこの損失関数をさらに削減します。
損失
以下の表は、spark.mllib
のGBTで現在サポートされている損失をリストしています. 各損失は、分類または回帰のいずれかに適用可能であり、両方に適用可能ではないことに注意してください。
表記: $N$ = インスタンスの数。 $y_i$ = インスタンス $i$ のラベル。 $x_i$ = インスタンス $i$ の特徴量。 $F(x_i)$ = インスタンス $i$ に対するモデルの予測ラベル。
損失 | タスク | 式 | 説明 |
---|---|---|---|
対数損失 | 分類 | 分類 | $2 \sum_{i=1}^{N} \log(1+\exp(-2 y_i F(x_i)))$ |
2倍の二項負の対数尤度。 | 回帰 | 二乗誤差 | 回帰 |
$\sum_{i=1}^{N} (y_i - F(x_i))^2$ | 回帰 | L2損失とも呼ばれます。回帰タスクのデフォルトの損失。 | 絶対誤差 |
使用上のヒント
回帰
-
loss
: 損失とそのタスク(分類 vs. 回帰)への適用性については、上記のセクションを参照してください。データセットに応じて、異なる損失が大きく異なる結果をもたらす可能性があります。 -
numIterations
: アンサンブル内のツリーの数を設定します。各反復で1つのツリーが生成されます。この数を増やすと、モデルの表現力が高まり、トレーニングデータの精度が向上します。ただし、大きすぎるとテスト時の精度が低下する可能性があります。 -
learningRate
: このパラメータは調整する必要はありません。アルゴリズムの動作が不安定に見える場合は、この値を小さくすると安定性が向上する可能性があります。 -
algo
: アルゴリズムまたはタスク(分類 vs. 回帰)は、ツリーの[Strategy]パラメータを使用して設定します。
トレーニング中の検証
勾配ブースティングは、より多くのツリーでトレーニングすると過学習する可能性があります。過学習を防ぐために、トレーニング中に検証することが有効です。このオプションを利用するために、`runWithValidation`メソッドが提供されています。引数としてRDDのペアを取り、最初のRDDはトレーニングデータセット、2番目のRDDは検証データセットです。
検証誤差の改善が特定の許容範囲(BoostingStrategy
の validationTol
引数で指定)を超えなくなると、トレーニングは停止します。実際には、検証誤差は最初に減少し、その後増加します。検証誤差が単調に変化しない場合があり、ユーザーは十分に大きな負の許容範囲を設定し、evaluateEachIteration
(反復ごとの誤差または損失を示す)を使用して検証曲線を調べ、反復回数を調整することをお勧めします。
例
分類
以下の例は、LIBSVMデータファイルを読み込み、LabeledPoint
のRDDとして解析し、ログ損失を使用して勾配ブースティングツリーで分類を実行する方法を示しています。アルゴリズムの精度を測定するために、テスト誤差が計算されます。
APIの詳細については、GradientBoostedTrees
Python ドキュメント および GradientBoostedTreesModel
Python ドキュメント を参照してください。
from pyspark.mllib.tree import GradientBoostedTrees, GradientBoostedTreesModel
from pyspark.mllib.util import MLUtils
# Load and parse the data file.
data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
# Split the data into training and test sets (30% held out for testing)
(trainingData, testData) = data.randomSplit([0.7, 0.3])
# Train a GradientBoostedTrees model.
# Notes: (a) Empty categoricalFeaturesInfo indicates all features are continuous.
# (b) Use more iterations in practice.
model = GradientBoostedTrees.trainClassifier(trainingData,
categoricalFeaturesInfo={}, numIterations=3)
# Evaluate model on test instances and compute test error
predictions = model.predict(testData.map(lambda x: x.features))
labelsAndPredictions = testData.map(lambda lp: lp.label).zip(predictions)
testErr = labelsAndPredictions.filter(
lambda lp: lp[0] != lp[1]).count() / float(testData.count())
print('Test Error = ' + str(testErr))
print('Learned classification GBT model:')
print(model.toDebugString())
# Save and load model
model.save(sc, "target/tmp/myGradientBoostingClassificationModel")
sameModel = GradientBoostedTreesModel.load(sc,
"target/tmp/myGradientBoostingClassificationModel")
APIの詳細については、GradientBoostedTrees
Scala ドキュメント および GradientBoostedTreesModel
Scala ドキュメント を参照してください。
import org.apache.spark.mllib.tree.GradientBoostedTrees
import org.apache.spark.mllib.tree.configuration.BoostingStrategy
import org.apache.spark.mllib.tree.model.GradientBoostedTreesModel
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
// Split the data into training and test sets (30% held out for testing)
val splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
// Train a GradientBoostedTrees model.
// The defaultParams for Classification use LogLoss by default.
val boostingStrategy = BoostingStrategy.defaultParams("Classification")
boostingStrategy.numIterations = 3 // Note: Use more iterations in practice.
boostingStrategy.treeStrategy.numClasses = 2
boostingStrategy.treeStrategy.maxDepth = 5
// Empty categoricalFeaturesInfo indicates all features are continuous.
boostingStrategy.treeStrategy.categoricalFeaturesInfo = Map[Int, Int]()
val model = GradientBoostedTrees.train(trainingData, boostingStrategy)
// Evaluate model on test instances and compute test error
val labelAndPreds = testData.map { point =>
val prediction = model.predict(point.features)
(point.label, prediction)
}
val testErr = labelAndPreds.filter(r => r._1 != r._2).count.toDouble / testData.count()
println(s"Test Error = $testErr")
println(s"Learned classification GBT model:\n ${model.toDebugString}")
// Save and load model
model.save(sc, "target/tmp/myGradientBoostingClassificationModel")
val sameModel = GradientBoostedTreesModel.load(sc,
"target/tmp/myGradientBoostingClassificationModel")
APIの詳細については、GradientBoostedTrees
Java ドキュメント および GradientBoostedTreesModel
Java ドキュメント を参照してください。
import java.util.HashMap;
import java.util.Map;
import scala.Tuple2;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.mllib.regression.LabeledPoint;
import org.apache.spark.mllib.tree.GradientBoostedTrees;
import org.apache.spark.mllib.tree.configuration.BoostingStrategy;
import org.apache.spark.mllib.tree.model.GradientBoostedTreesModel;
import org.apache.spark.mllib.util.MLUtils;
SparkConf sparkConf = new SparkConf()
.setAppName("JavaGradientBoostedTreesClassificationExample");
JavaSparkContext jsc = new JavaSparkContext(sparkConf);
// Load and parse the data file.
String datapath = "data/mllib/sample_libsvm_data.txt";
JavaRDD<LabeledPoint> data = MLUtils.loadLibSVMFile(jsc.sc(), datapath).toJavaRDD();
// Split the data into training and test sets (30% held out for testing)
JavaRDD<LabeledPoint>[] splits = data.randomSplit(new double[]{0.7, 0.3});
JavaRDD<LabeledPoint> trainingData = splits[0];
JavaRDD<LabeledPoint> testData = splits[1];
// Train a GradientBoostedTrees model.
// The defaultParams for Classification use LogLoss by default.
BoostingStrategy boostingStrategy = BoostingStrategy.defaultParams("Classification");
boostingStrategy.setNumIterations(3); // Note: Use more iterations in practice.
boostingStrategy.getTreeStrategy().setNumClasses(2);
boostingStrategy.getTreeStrategy().setMaxDepth(5);
// Empty categoricalFeaturesInfo indicates all features are continuous.
Map<Integer, Integer> categoricalFeaturesInfo = new HashMap<>();
boostingStrategy.treeStrategy().setCategoricalFeaturesInfo(categoricalFeaturesInfo);
GradientBoostedTreesModel model = GradientBoostedTrees.train(trainingData, boostingStrategy);
// Evaluate model on test instances and compute test error
JavaPairRDD<Double, Double> predictionAndLabel =
testData.mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));
double testErr =
predictionAndLabel.filter(pl -> !pl._1().equals(pl._2())).count() / (double) testData.count();
System.out.println("Test Error: " + testErr);
System.out.println("Learned classification GBT model:\n" + model.toDebugString());
// Save and load model
model.save(jsc.sc(), "target/tmp/myGradientBoostingClassificationModel");
GradientBoostedTreesModel sameModel = GradientBoostedTreesModel.load(jsc.sc(),
"target/tmp/myGradientBoostingClassificationModel");
回帰
以下の例は、LIBSVMデータファイルを読み込み、LabeledPoint
のRDDとして解析し、二乗誤差を損失として使用して勾配ブースティングツリーで回帰を実行する方法を示しています。適合度を評価するために、最後に平均二乗誤差(MSE)が計算されます。
APIの詳細については、GradientBoostedTrees
Python ドキュメント および GradientBoostedTreesModel
Python ドキュメント を参照してください。
from pyspark.mllib.tree import GradientBoostedTrees, GradientBoostedTreesModel
from pyspark.mllib.util import MLUtils
# Load and parse the data file.
data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
# Split the data into training and test sets (30% held out for testing)
(trainingData, testData) = data.randomSplit([0.7, 0.3])
# Train a GradientBoostedTrees model.
# Notes: (a) Empty categoricalFeaturesInfo indicates all features are continuous.
# (b) Use more iterations in practice.
model = GradientBoostedTrees.trainRegressor(trainingData,
categoricalFeaturesInfo={}, numIterations=3)
# Evaluate model on test instances and compute test error
predictions = model.predict(testData.map(lambda x: x.features))
labelsAndPredictions = testData.map(lambda lp: lp.label).zip(predictions)
testMSE = labelsAndPredictions.map(lambda lp: (lp[0] - lp[1]) * (lp[0] - lp[1])).sum() /\
float(testData.count())
print('Test Mean Squared Error = ' + str(testMSE))
print('Learned regression GBT model:')
print(model.toDebugString())
# Save and load model
model.save(sc, "target/tmp/myGradientBoostingRegressionModel")
sameModel = GradientBoostedTreesModel.load(sc, "target/tmp/myGradientBoostingRegressionModel")
APIの詳細については、GradientBoostedTrees
Scala ドキュメント および GradientBoostedTreesModel
Scala ドキュメント を参照してください。
import org.apache.spark.mllib.tree.GradientBoostedTrees
import org.apache.spark.mllib.tree.configuration.BoostingStrategy
import org.apache.spark.mllib.tree.model.GradientBoostedTreesModel
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
// Split the data into training and test sets (30% held out for testing)
val splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
// Train a GradientBoostedTrees model.
// The defaultParams for Regression use SquaredError by default.
val boostingStrategy = BoostingStrategy.defaultParams("Regression")
boostingStrategy.numIterations = 3 // Note: Use more iterations in practice.
boostingStrategy.treeStrategy.maxDepth = 5
// Empty categoricalFeaturesInfo indicates all features are continuous.
boostingStrategy.treeStrategy.categoricalFeaturesInfo = Map[Int, Int]()
val model = GradientBoostedTrees.train(trainingData, boostingStrategy)
// Evaluate model on test instances and compute test error
val labelsAndPredictions = testData.map { point =>
val prediction = model.predict(point.features)
(point.label, prediction)
}
val testMSE = labelsAndPredictions.map{ case(v, p) => math.pow((v - p), 2)}.mean()
println(s"Test Mean Squared Error = $testMSE")
println(s"Learned regression GBT model:\n ${model.toDebugString}")
// Save and load model
model.save(sc, "target/tmp/myGradientBoostingRegressionModel")
val sameModel = GradientBoostedTreesModel.load(sc,
"target/tmp/myGradientBoostingRegressionModel")
APIの詳細については、GradientBoostedTrees
Java ドキュメント および GradientBoostedTreesModel
Java ドキュメント を参照してください。
import java.util.HashMap;
import java.util.Map;
import scala.Tuple2;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.mllib.regression.LabeledPoint;
import org.apache.spark.mllib.tree.GradientBoostedTrees;
import org.apache.spark.mllib.tree.configuration.BoostingStrategy;
import org.apache.spark.mllib.tree.model.GradientBoostedTreesModel;
import org.apache.spark.mllib.util.MLUtils;
SparkConf sparkConf = new SparkConf()
.setAppName("JavaGradientBoostedTreesRegressionExample");
JavaSparkContext jsc = new JavaSparkContext(sparkConf);
// Load and parse the data file.
String datapath = "data/mllib/sample_libsvm_data.txt";
JavaRDD<LabeledPoint> data = MLUtils.loadLibSVMFile(jsc.sc(), datapath).toJavaRDD();
// Split the data into training and test sets (30% held out for testing)
JavaRDD<LabeledPoint>[] splits = data.randomSplit(new double[]{0.7, 0.3});
JavaRDD<LabeledPoint> trainingData = splits[0];
JavaRDD<LabeledPoint> testData = splits[1];
// Train a GradientBoostedTrees model.
// The defaultParams for Regression use SquaredError by default.
BoostingStrategy boostingStrategy = BoostingStrategy.defaultParams("Regression");
boostingStrategy.setNumIterations(3); // Note: Use more iterations in practice.
boostingStrategy.getTreeStrategy().setMaxDepth(5);
// Empty categoricalFeaturesInfo indicates all features are continuous.
Map<Integer, Integer> categoricalFeaturesInfo = new HashMap<>();
boostingStrategy.treeStrategy().setCategoricalFeaturesInfo(categoricalFeaturesInfo);
GradientBoostedTreesModel model = GradientBoostedTrees.train(trainingData, boostingStrategy);
// Evaluate model on test instances and compute test error
JavaPairRDD<Double, Double> predictionAndLabel =
testData.mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));
double testMSE = predictionAndLabel.mapToDouble(pl -> {
double diff = pl._1() - pl._2();
return diff * diff;
}).mean();
System.out.println("Test Mean Squared Error: " + testMSE);
System.out.println("Learned regression GBT model:\n" + model.toDebugString());
// Save and load model
model.save(jsc.sc(), "target/tmp/myGradientBoostingRegressionModel");
GradientBoostedTreesModel sameModel = GradientBoostedTreesModel.load(jsc.sc(),
"target/tmp/myGradientBoostingRegressionModel");