アンサンブル - RDDベースAPI
アンサンブル手法とは、他の複数のベースモデルからなるモデルを作成する学習アルゴリズムです。spark.mllibは、GradientBoostedTreesとRandomForestという2つの主要なアンサンブルアルゴリズムをサポートしています。どちらもベースモデルとして決定木を使用します。
勾配ブースティングツリー vs. ランダムフォレスト
勾配ブースティングツリー (GBTs)とランダムフォレストは、どちらもツリーのアンサンブルを学習するためのアルゴリズムですが、トレーニングプロセスは異なります。いくつかの実用的なトレードオフがあります。
- GBTは一度に1つのツリーをトレーニングするため、ランダムフォレストよりもトレーニングに時間がかかる場合があります。ランダムフォレストは複数のツリーを並列でトレーニングできます。
- 一方、GBTではランダムフォレストよりも小さい(浅い)ツリーを使用することが許容される場合が多く、小さいツリーのトレーニングは時間がかかりません。
- ランダムフォレストは過学習しにくい傾向があります。ランダムフォレストでツリーの数を増やすと過学習の可能性が減りますが、GBTでツリーの数を増やすと過学習の可能性が増加します(統計学的な言葉で言えば、ランダムフォレストはより多くのツリーを使用して分散を減らし、GBTはより多くのツリーを使用してバイアスを減らします)。
- ランダムフォレストはチューニングが容易な場合があります。これは、ツリーの数が増えるにつれてパフォーマンスが単調に改善されるためです(一方、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");勾配ブースティングツリー (GBTs)
勾配ブースティングツリー (GBTs)は、決定木のアンサンブルです。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損失とも呼ばれます。回帰タスクのデフォルトの損失。 |
| 絶対誤差 | 回帰 | $\sum_{i=1}^{N} |y_i - F(x_i)|$ | L1損失とも呼ばれます。二乗誤差よりも外れ値に対してロバストである可能性があります。 |
使用上のヒント
さまざまなパラメータについて議論することで、GBTを使用するためのいくつかのガイドラインを含めます。決定木ガイドで説明されている決定木パラメータは省略します。
-
loss:損失関数とそのタスク(分類対回帰)への適用性については、上記のセクションを参照してください。データセットによっては、異なる損失関数が大幅に異なる結果をもたらす可能性があります。 -
numIterations:これはアンサンブル内のツリーの数を設定します。各イテレーションで1つのツリーが生成されます。この数を増やすと、モデルはより表現力豊かになり、トレーニングデータの精度が向上します。ただし、これが大きすぎるとテスト時の精度が低下する可能性があります。 -
learningRate:このパラメータはチューニングする必要はありません。アルゴリズムの動作が不安定なように見える場合は、この値を下げることで安定性が向上する可能性があります。 -
algo:アルゴリズムまたはタスク(分類対回帰)は、ツリー[Strategy]パラメータを使用して設定されます。
トレーニング中の検証
勾配ブースティングは、より多くのツリーでトレーニングすると過学習する可能性があります。過学習を防ぐために、トレーニング中に検証することが役立ちます。`runWithValidation`メソッドは、このオプションを使用するために提供されています。これは、2つのRDDのペアを引数として取ります。最初のペアはトレーニングデータセット、2番目のペアは検証データセットです。
検証エラーの改善がある許容値(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");