アンサンブル - spark.mllib
アンサンブル法は他の基本モデルのセットからなるモデルを生成する学習アルゴリズムです。spark.mllib
は2つの主要なアンサンブルアルゴリズムをサポートします: 勾配ブースト木
と ランダムフォレスト
。両方とも基本のモデルとして 決定木 を使います。
勾配ブースト木 vs ランダムフォレスト
Gradient-Boosted Trees (GBTs) と Random Forests の両方とも木の学習アンサンブルのためのアルゴリズムですが、訓練プロセスが異なります。幾つかの現実的なトレードオフがあります:
- GBT は一度に1つの木を訓練します。つまりランダムフォレストより訓練するのに時間がかかります。ランダムフォレストは並行して複数の木を訓練することができます。
- 一方で、ランダムフォレストを使うよりGBTの小さな(浅い)木を使うことに意味があることがしばしばあります。小さな木の訓練はより少ない時間が掛かります。
- ランダムフォレストはオーバーフィッティングする傾向を少なくすることができます。ランダムフォレストでのもっと多くの木の訓練はオーバーフィッティングの可能性を減らしますが、GBTを使ったもっと多くの木の訓練はオーバーフィッティングの可能性を増やします。(統計的な言語では、ランダムフォレストは多くの木を使うことで分散を減らし、一方でGBTはもっと多くの木を使うことで偏りを減らします。)
- ランダムフォレストはたくさんの木を使ってパフォーマンスを単調に改善するため、調整するのが簡単です(それに対し、たくさんの木があまりに大きい場合、GBTでのパフォーマンスが小さく始まります)。
簡単に言うと、両方のアルゴリズムとも効果的であり、その選択は特有のデータセットに基づくべきです。
ランダムフォレスト
ランダムフォレスト は決定木のアンサンブルです。ランダムフォレストは分類と回帰のための最も成功した機械学習モデルの一つです。オーバーフィッティングのリスクを減らすために多くの決定木を組み合わせます。決定木のように、ランダムフォレストは分類特徴を処理し、多クラス分類設定を拡張し、特徴のスケーリングを必要とせず、非線形性および特徴の相互作用を獲得することができます。
spark.mllib
は、繰り返しおよび分類機能の両方を使って、バイナリと多層クラス分類、および回帰のためのランダムフォレストをサポートします。spark.mllib
は既存の <a1>決定木</a1> 実装を使ってランダムフォレストを実装します。木についてのもっと詳しい情報は決定木ガイドを見てください。
基本アルゴリズム
ランダムフォレストは個別に決定木のセットを訓練します。そのため訓練は並行して行うことができます。アルゴリズムは各決定木が少し異なるようにランダム性を訓練プロセスに注入します。各木からの予想の組み合わせは予想の分散を減らし、テストデータ上のパフォーマンスを改善します。
練習
訓練プロセスに注入されたランダム性は以下のものを含みます:
- 異なる訓練セット(別名 ブートストラッピング)を取得するための各繰り返し上での元のデータセットの副標本。bootstrapping).
- 各木ノード上で分割するための特徴の異なるランダム下位集合の考慮。
これらのランダム性は別として、各決定木に関しては決定木の訓練は同じ方法で行われます。
予想
新しいインスタンス上で予想をするために、ランダムフォレストは決定木のセットから予想を集約しなければなりません。この集約は分類と回帰のためにそれぞれに行われます。
分類: 過半数の票。各木の予想は一つのクラスへの投票としてカウントされます。ラベルはもっとも多くの投票を受け取ったクラスに予想されます。
回帰: 平均化各木は実際の値を予想します。ラベルは木の予想の平均として予想されます。
使い方のtips
様々なパラメータを議論することで、ランダムフォレストを使うための2、3のガイドラインを含みます。それらは決定木ガイドでカバーされるため、幾つかの決定木パラメータを省略します。
言及する最初の2つのパラメータは最も重要で、それらの調整はしばしばパフォーマンスを改善することができます:
numTrees
: フォレストでの木の数- 木の数の増加は予想の分散を減らし、モデルのテスト時の精度を改善するでしょう。
- 訓練時間は大まかに木の数で線形的に増加します。
maxDepth
: フォレストでの各木の最大の深さ。- 深さの増加はモデルをもっと表現豊かに強力にします。しかし、深い木は訓練に時間がかかり、オーバーフィッティングもしがちになります。
- 一般的に、1つの決定木を使用する場合よりランダムフォレストを使う場合に、より深い木の訓練が望ましいです。一つの木はランダムフォレストよりオーバーフィッティングしやすいです(フォレストでの複数の木の平均からの分散の削減による)。
次の二つのパラメータは一般的に調整を必要としません。しかし、それらは訓練をスピードアップするために調整することができます。
-
subsamplingRate
: このパラメータは、元のデータセットのサイズの断片として、フォレストでの各木の訓練のために使われるデータセットのサイズを指定します。デフォルト (1.0) がお勧めですが、この断片を減らすことで訓練をスピードアップすることができます。 -
featureSubsetStrategy
: 各木ノードで分割するための候補として使われる特徴の数。数は特徴の総数の断片あるいは関数として指定されます。この数を減らすことは訓練をスピードアップしますが、あまりに低い場合には時にはパフォーマンスに影響を与えるかも知れません。
例
分類
以下の例は LIBSVM データファイルをどうやってロードするかを説明し、LabeledPoint
のRDDとしてパースし、ランダムフォレストを使って分類を実施します。テストエラーはアルゴリズムの正確さを計測するために計算されます。
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("Test Error = " + testErr)
println("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 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.api.java.function.Function;
import org.apache.spark.api.java.function.PairFunction;
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.
Integer numClasses = 2;
HashMap<Integer, Integer> categoricalFeaturesInfo = new HashMap<Integer, Integer>();
Integer numTrees = 3; // Use more in practice.
String featureSubsetStrategy = "auto"; // Let the algorithm choose.
String impurity = "gini";
Integer maxDepth = 5;
Integer maxBins = 32;
Integer seed = 12345;
final 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(new PairFunction<LabeledPoint, Double, Double>() {
@Override
public Tuple2<Double, Double> call(LabeledPoint p) {
return new Tuple2<Double, Double>(model.predict(p.features()), p.label());
}
});
Double testErr =
1.0 * predictionAndLabel.filter(new Function<Tuple2<Double, Double>, Boolean>() {
@Override
public Boolean call(Tuple2<Double, Double> pl) {
return !pl._1().equals(pl._2());
}
}).count() / 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");
APIについての詳細はRandomForest
Python ドキュメント およびRandomForestModel
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 (v, p): v != p).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")
回帰
以下の例は LIBSVM データファイルをどうやってロードするかを説明し、LabeledPoint
のRDDとしてパースし、ランダムフォレストを使って回帰を実施します。平均二乗誤差(MSE)は最後に 適合度を評価するために計算されます。
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("Test Mean Squared Error = " + testMSE)
println("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.function.Function2;
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.api.java.function.Function;
import org.apache.spark.api.java.function.PairFunction;
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<Integer, Integer>();
Integer numTrees = 3; // Use more in practice.
String featureSubsetStrategy = "auto"; // Let the algorithm choose.
String impurity = "variance";
Integer maxDepth = 4;
Integer maxBins = 32;
Integer seed = 12345;
// Train a RandomForest model.
final 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(new PairFunction<LabeledPoint, Double, Double>() {
@Override
public Tuple2<Double, Double> call(LabeledPoint p) {
return new Tuple2<Double, Double>(model.predict(p.features()), p.label());
}
});
Double testMSE =
predictionAndLabel.map(new Function<Tuple2<Double, Double>, Double>() {
@Override
public Double call(Tuple2<Double, Double> pl) {
Double diff = pl._1() - pl._2();
return diff * diff;
}
}).reduce(new Function2<Double, Double, Double>() {
@Override
public Double call(Double a, Double b) {
return a + b;
}
}) / testData.count();
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");
APIについての詳細はRandomForest
Python ドキュメント およびRandomForestModel
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 (v, p): (v - p) * (v - p)).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")
勾配ブースト木 (GBT)
Gradient-Boosted Trees (GBTs) は 決定木のアンサンブルです。GBT は損失関数を最小化するために決定木を繰り返し学習します。決定木のように、GBTは分類特徴を処理し、多クラス分類設定を拡張し、特徴のスケーリングを必要とせず、非線形性および特徴の相互作用を獲得することができます。
spark.mllib
は、繰り返しおよび分類機能の両方を使って、バイナリと多層クラス分類、および回帰のためのGBTをサポートします。spark.mllib
は既存の 決定木 実装を使ってGBTを実装します。木についてのもっと詳しい情報は決定木ガイドを見てください。
注意: GBT はまだ多クラスの分類をサポートしません。多クラス問題については、決定木 あるいは ランダムフォレストを使ってください。
基本アルゴリズム
勾配ブーストは決定木の系列を繰り返し訓練します。各繰り返しにおいて、アルゴリズムは各訓練インスタンスのラベルを予想するために現在のアンサンブルを使用し、そして予想と本当のラベルを比較します。データセットは弱い予想を持つ訓練インスタンスをもっと強調するために再びラベルを付けられます。従って、次の繰り返しにおいて、決定木は以前の失敗を正すのに役立つでしょう。
再びラベルをつけるインスタンスのための特定の仕組みは損失関数(以下で議論されます)によって定義されます。各繰り返しによって、GBTは訓練データ上のこの損失関数を更に減らします。
損失
以下の表はspark.mllib
のGBTでサポートされている損失をリスト化します。各損失は、分類あるいは回帰の一つ、両方ではない、に適用可能なことに注意してください。
Notation: $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)))$ | Twice binomial negative log likelihood. |
二乗誤差 | 回帰 | $\sum_{i=1}^{N} (y_i - F(x_i))^2$ | L2損失 とも呼ばれます。回帰タスクのためのデフォルトの損失 |
絶対誤差 | 回帰 | $\sum_{i=1}^{N} |y_i - F(x_i)|$ | L1損失とも呼ばれます。二乗誤差よりも飛び地に対して堅牢になりえます。 |
使い方のtips
様々なパラメータを議論することで、GBTを使うための2、3のガイドラインを含みます。それらは決定木ガイドでカバーされるため、幾つかの決定木パラメータを省略します。
-
損失
: 損失とそれらのタスク(分類 vs. 回帰)への適用性についての情報は上の章を見てください。異なる損失は非常に異なる結果を与えるかも知れず、データセットに依存します。 -
numIterations
: これはアンサンブルでの木の数を設定します。各繰り返しは一つの木を生成します。この数が増えるとモデルはもっと表現が豊かになり、訓練データの正確さが改善されます。しかし、これがあまりに大きい場合は、テスト時の正確さは影響を受けるかも知れません。 -
learningRate
: このパラメータは調整される必要があるべきではありません。アルゴリズムの挙動が安定しないようであれば、この値を減らすことで安定性が改善されるかも知れません。 -
algo
: アルゴリズムあるいはタスク(分類 vs. 回帰)はつり [Strategy] パラメータを使って設定されます。
訓練中の検証
勾配ブーストはもっと多くの木を使って訓練された場合にオーバーフィットするかも知れません。オーバーフィッティングを避けるために、訓練中に検証をすることは有用です。runWithValidation メソッドはこのオプションを利用するために提供されていました。それは引数としてRDDのペアを取り、最初の一つは訓練データセットで、二つ目は検証データセットです。
検証エラーでの改善が特定の許容範囲より小さい(BoostingStrategy
内のvalidationTol
引数によって提供される)場合に、訓練が停止します。実際には、検証エラーは最初に減少し、後で増加します。検証エラーが単調に変化しない場合、ユーザは十分大きな負の許容範囲を設定し、繰り返しの数を調整するためにevaluateEachIteration
(これは繰り返しあたりの誤差と損失を与えます)を使って検証曲線を検査するように忠告されます。
例
分類
以下の例は LIBSVM データファイルをどうやってロードするかを説明し、LabeledPoint
のRDDとしてパースし、損失の対数の勾配ブースト木を使って分類を実施します。テストエラーはアルゴリズムの正確さを計測するために計算されます。
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("Test Error = " + testErr)
println("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.api.java.function.Function;
import org.apache.spark.api.java.function.PairFunction;
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<Integer, Integer>();
boostingStrategy.treeStrategy().setCategoricalFeaturesInfo(categoricalFeaturesInfo);
final GradientBoostedTreesModel model =
GradientBoostedTrees.train(trainingData, boostingStrategy);
// Evaluate model on test instances and compute test error
JavaPairRDD<Double, Double> predictionAndLabel =
testData.mapToPair(new PairFunction<LabeledPoint, Double, Double>() {
@Override
public Tuple2<Double, Double> call(LabeledPoint p) {
return new Tuple2<Double, Double>(model.predict(p.features()), p.label());
}
});
Double testErr =
1.0 * predictionAndLabel.filter(new Function<Tuple2<Double, Double>, Boolean>() {
@Override
public Boolean call(Tuple2<Double, Double> pl) {
return !pl._1().equals(pl._2());
}
}).count() / 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");
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 (v, p): v != p).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")
回帰
以下の例は LIBSVM データファイルをどうやってロードするかを説明し、LabeledPoint
のRDDとしてパースし、二損失として二乗誤差付きの勾配ブースト木を使って回帰を実施します。平均二乗誤差(MSE)は最後に 適合度を評価するために計算されます。
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("Test Mean Squared Error = " + testMSE)
println("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.function.Function2;
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.api.java.function.Function;
import org.apache.spark.api.java.function.PairFunction;
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<Integer, Integer>();
boostingStrategy.treeStrategy().setCategoricalFeaturesInfo(categoricalFeaturesInfo);
final GradientBoostedTreesModel model =
GradientBoostedTrees.train(trainingData, boostingStrategy);
// Evaluate model on test instances and compute test error
JavaPairRDD<Double, Double> predictionAndLabel =
testData.mapToPair(new PairFunction<LabeledPoint, Double, Double>() {
@Override
public Tuple2<Double, Double> call(LabeledPoint p) {
return new Tuple2<Double, Double>(model.predict(p.features()), p.label());
}
});
Double testMSE =
predictionAndLabel.map(new Function<Tuple2<Double, Double>, Double>() {
@Override
public Double call(Tuple2<Double, Double> pl) {
Double diff = pl._1() - pl._2();
return diff * diff;
}
}).reduce(new Function2<Double, Double, Double>() {
@Override
public Double call(Double a, Double b) {
return a + b;
}
}) / data.count();
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");
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 (v, p): (v - p) * (v - p)).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")