LoginSignup
3
3

More than 5 years have passed since last update.

spark mlで分類器に関するTips

Last updated at Posted at 2016-12-07

この記事は、Machine Learning Advent Calendar 2016 8日目の記事です。

spark mlの分類器をお試しする上でのTipsを4つご紹介します!

1. お試しに便利なlibsvmデータセット

機械学習を試す上で、データセットを用意する必要があります。
よく知られているものとして、
UCI http://archive.ics.uci.edu/ml/index.html
kaggle https://www.kaggle.com/datasets
MovieLens http://grouplens.org/datasets/movielens/
などを利用することが多いと思います。
ただ、クラス数、特徴量の数、データ量など、適切なものを探すのは大変です。
LIBSVMでは、UCI等で取得できる分類や回帰に利用できるデータが、それぞれのクラス数、特徴量数、データ量、ダウンロード元が一目でわかるようにまとまっています。
また、データはすべてlibsvm形式で格納されています。
libsvmはsparseなデータに対する分類や回帰を行うために適したデータレイアウトのテキストフォーマットのデータソースです。
実際のデータレイアウトはこんな感じです。

label index1:value1 index2:value2 ・・・

また、sparkのdataFrameとしてロードすると、このような形で見えます。

// sample 1
import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.appName("VectorIndexerSample").getOrCreate()
spark.read.format("libsvm").load("/path/to/data").head(1)

//出力結果
//Array[label,(num features,[index1,index2,・・・],[value1,value2,・・・])]

このように、inputFormatによって、Sparkのmllib/mlを使用する際の入力データの形式であるSparseMarixの形でロードされるため、データをロードした後の前処理に苦労しなくて良いという利点があります。

なお、libsvmは、データセット以外にも様々なライブラリでlibsvmフォーマットを利用するためのパッケージなども置いてあります。

2. 前処理

データを分類器の学習に適した形にするための特徴量変換のAPIが幾つかあります。
注意が必要な点として、分類器を使う上で、特徴量を連続値として扱うかを、制御する必要があります。
mllibでは、分類器の学習時に与えるパラメータとして、カテゴリ値として利用する特徴量をcategoricalFeaturesInfo: Map[Int, Int]の形式で与えるようになっていました。
ただし、このやり方の場合、カテゴリ値として使用する特徴量を手動で与えるので、特徴量の数が膨大な場合は実装を行う上で少し面倒です。
そこで、spark.mlでは、VectorIndexerというAPIで自動的にスキーマのmetadataとしてカテゴリ値か連続値かを判別するためのattributeを付与するようになっています。VectorIndexerでは、カーディナリティがmaxCategoriesで与えた数値以下である特徴量はカテゴリ値、カーディナリティがmaxCategoriesで与えた数値よりも大きい場合は連続値としてattributeを付与します。

以下サンプルコードです。

// sample 2
import org.apache.spark.sql.SparkSession
org.apache.spark.ml.feature.VectorIndexer

val spark = SparkSession.builder.appName("VectorIndexerSample").getOrCreate()
val data = spark.read.format("libsvm").load("/path/to/data")
val featureIndexer = new VectorIndexer()
                     .setInputCol("features")
                     .setOutputCol("indexedfeatures")
                     .setMaxCategories(20)
                     .fit(data)
val featureIndexed = featureIndexer.transform(data)

3. 多クラス分類への対応

sparkのmllib/mlの分類器は、多クラス分類に対応しているものと、2クラス分類のみに対応しているものがあります。
以下、対応を表にしてみました。

mllib spark.ml
DecisionTree 2クラス/多クラス 2クラス/多クラス
RandomForest 2クラス/多クラス 2クラス/多クラス
GBT(勾配ブースティングツリー) 2クラスのみ 2クラスのみ
LogisticRegression 2クラス/多クラス 2クラスのみ
NaiveBayes 2クラス/多クラス 2クラス/多クラス
SVM 2クラスのみ 実装なし

4.分類木のメモリ設定

決定木、ランダムフォレスト、GBTといった分類木で、特に深い木の学習を行う際など、パフォーマンスが気になる場合は、
maxMemoryInMBの設定を行うと良いです。
Sparkでは、分類木の学習において、このmaxMemoryInMBで指定したメモリサイズで扱える数のツリーノードの計算を並列化します。このmaxMemoryInMBは、初期値が256MBと小さいため、クラスタのexecutorメモリのサイズに合わせてチューニングを行うことで、並列度を上げて、学習のイテレーション数を減らすことができます。

以下、決定木の学習におけるサンプルコードです。
(sample 2 の続き)

// sample 3
import org.apache.spark.ml.classification.DecisionTreeClassifier

//maxMemoryInMBの値を1024MBに設定
val model = new DecisionTreeClassifier()
            .setLabelCol("label")
            .setFeaturesCol("indexedFeatures")
            .setMaxMemoryInMB(1024)
            .fit(featureIndexed)

本当は最後に各分類器のパフォーマンスやAccuracyを比較したかったのですが、
時間が取れなかったのでまたの機会に。。。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3