scikit-learn + RandomForestの性能評価
はじめに
普段はSVMを使うことが多いが、学習器の勉強をせねばとRandom Forestで実験を行った。
参考資料は
http://d.hatena.ne.jp/shakezo/20121221/1356089207
と
統計的機械学習の基礎(http://www.kyoritsu-pub.co.jp/bookdetail/9784320123625)
Random Forestについて
テストデータをブートストラップサンプリングにより複数作成して、複数作成する。
最終的に各決定木の多数決によって、クラスの分類を行う。
決定木を回帰木にしたら数値予測もできる。
バギングとの違いは、RandomForestでは目的変数のサンプリングも同時に行うということ
なぜ精度が良いのか?
汎化誤差 = バイアス + バリアンス + ノイズ
であるとき、
決定木のような学習木はバリアンスが高くなる(少しでもデータが異なると予測結果が大幅に異なる)弱学習木である。
このような学習木をたくさん作成することでバリアンスを下げてやろうというのが、戦略。
ハイパーパラメータには、主に
num_trees: いくつ決定木を作成するか
max_depth: どの深さの決定木を作成するか
num_features: 目的変数のサンプリング時に、いくつの目的変数をサンプリングするか
である。
本には、random_forestは過学習しないのでmax_depthに依存しないや、num_featuresはsqrt(features)がいいなど書いてあったが、本当か?ということで実験を行った。
実験条件
データにはmnistを使用した。
ただ元のデータ量だと多い気がしたので、各数字2000ずつサンプリングを行った。
テストデータはそのままの10000件
実験
num_trees
まずはnum_treesを10, 100, 1000, 10000に変更した時、
max_depthは最後まで、
num_featuresはsqrt(features)に固定
やはり少なすぎると精度が低い様子、でも多すぎても意味がないかな、1000ぐらいが適当そう
depth
次にdepthを変化させた場合、
2, 4, 6, 8, 10, 12, 14, 16, 18, 20の10種類
num_treesは1000に、max_featuresはsqrt(features)に固定
確かに、深く探索しても過学習を起こしてなさそう、深くまで探索しても大丈夫
num_features
num_featuresを10, 15, 20, 25, 30, 35, 40, 45, 50, 55に変化させた時、
num_treesは1000、depthはmaxまで
35、40くらいがピーク?赤線はデフォルトのsprtの時、
デフォルトよりもちょっと多めが今回はよかった?
実行時間
最後に実行時間について
num_trees=1000
max_depth = max
max_features = 40
n_jobs = 6
のCPUのみで実験
3回の平均が28.8秒
比較手法
ベンチマークとしてSVMでもMNISTの分類を行いました。
rbfカーネルでC=1.0, gamma=1/784
グリッドサーチはなし
one-vs-oneとone-vs-restの2種類で
注意点としては、データは0−1で正規化したということ(正規化しないとうまく学習できなかった、なんで?)
F-value | Time | |
---|---|---|
one_versus_one | 0.930 | 1 min 39 s |
one_versus_rest | 0.922 | - |
スパースで、クラス間のサンプル数の偏りがない場合は、RandomForestの方が精度良いし、早い!!
疑問として、one-vs-restの方が遅かったんだけど、なんで?パッケージの問題?
結論
RandomForestを使ってみた印象、やはり早い!!
いつもSVMばっかり使っているからか、尋常じゃなく早く感じる・・・
あとパラメータが少ないのも魅力、num_treesとmax_featuresくらいで大丈夫??
次はboostingかな・・・