Rでランダムフォレスト(random forest)

今回は機械学習のアルゴリズムの一種「ランダムフォレスト(random forest)」について紹介したいと思います。

ランダムフォレストとは?

ランダムフォレストは決定木を弱学習器とする集団学習アルゴリズムです。
細かなことは理解できる頭がないので、こちらのサイトを参照ください。
ざっくり要約してみると、学習用のデータをサンプリングして多数の決定木を作成し、作成した決定木をもとに多数決で結果を決める方法です。
イメージ図としては下図のようなものです。
ランダムフォレスト


ランダムフォレストは複数のモデル(決定木)の結果を統合・組み合わせることにより、高精度で汎用性の高いモデルを生成することができます。
ここで生成されたモデルを利用して、予測・分類を行っていきます。

Rでランダムフォレストの実行

Rでランダムフォレストを実行するためのパッケージは複数存在します。(「randomForest」、「ranger」、「Rborist」など)
今回は結果の分析もやってみたいので、「randomForest」パッケージを使って分析していこうと思います。
まずはランダムフォレスト実行時に必要なパラメータ(特徴量の数)を決めます。
「randomForest」パッケージの「tuneRF」関数を利用します。

#パッケージの準備
library(“randomForest”)#分析用パッケージ
library(“inTrees”)#結果出力用のパッケージ

#学習用サンプルデータの抽出
num_train<-sample(nrow(iris),100)#学習用データをサンプリング
num_test <-sample(nrow(iris),50)#テスト用データをサンプリング
train_iris<-iris[num_train,]
test_iris <-iris[num_test,] #チューニング
tuneRF(train_iris,train_iris$Species,plot = TRUE, doBest = FALSE)
mtry = 2 OOB error = 0%
Searching left …
mtry = 1 OOB error = 1%
-Inf 0.05
Searching right …
mtry = 4 OOB error = 1%
-Inf 0.05

Call:
randomForest(x = x, y = y, mtry = res[which.min(res[, 2]), 1])
Type of random forest: classification
Number of trees: 500
No. of variables tried at each split: 2

OOB estimate of error rate: 0%
Confusion matrix:
setosa versicolor virginica class.error
setosa 38 0 0 0
versicolor 0 37 0 0
virginica 0 0 25 0
ランダムフォレスト_チューニング

上記のチューニングは、特徴量というパラメータを定めるために行いました。
結果から、OOB Errorが一番小さい特徴量を利用します。

さてパラメータが決まったので、実際に分析をしてみましょう。
今回は学習用データから分類機を生成し、生成した分類機でテスト用データを分類します。
テスト用データからは「Species」という列を除いた状態で分類してみます。

#分析実行
#mtry(特徴量の数)には、さっきのチューニング結果で「OOB error」の最も小さかった2を利用します。
rf <- randomForest(Species ~., data=train_iris, mtry=2, ntree = 500, predict.all=TRUE)#予測・分類器の構築
result <- predict(rf, newdata=test_iris[-5],predict.all=TRUE)#構築した分類器で、分類対象のデータを分類
#結果の出力(分類結果の表)#縦軸がテスト用データ、横軸が分析結果
table(test_iris$Species, result$aggregate)

setosa versicolor virginica
setosa 17 0 0
versicolor 0 13 0
virginica 0 2 18

#結果の出力(重要度)
varImpPlot(rf)#重要度のグラフ
ランダムフォレスト_重要度
rf$importance#重要度をコンソールに出力
MeanDecreaseGini
Sepal.Length 5.213838
Sepal.Width 1.315528
Petal.Length 26.239781
Petal.Width 32.166626

実際にどのように分類されたかが確認できます。
今回はテストということで結果が分かっているので実際値と予測値の差を確認できますが、かなり高精度で分類できていますね(50件中2件のNG→96%の正答率)
また、重要度というものを出力できます。これはどの要素が結果の判定にどの程度影響を与えているのかを知ることができます。
今回の例では「Petal.Length」、「Petal.Width」が結果の判定に大きく影響しているみたいですね。
このように、過去のデータから未来を予想することができます。

分類ルールを抽出してみる

さて、このモデルはどのような分類ルールを使用しているのでしょうか?
「randomForest」パッケージだけではモデルの判定はできないので、「inTrees」パッケージを利用して、内部構造を抽出します。

#パッケージの準備
library(“inTrees”)#結果出力用のパッケージ

#学習後の森構造を要約
treeList <- RF2List(rf)#すべてのtreeの木構造を取得(getTree()する)
exec <- extractRules(treeList,train_iris,ntree=500)#決定木に含まれる条件文を抽出
ruleMetric <- getRuleMetric(exec,train_iris,train_iris$Species)#取り出した条件文を集計
ruleMetric <- pruneRule(ruleMetric,train_iris,train_iris$Species)#余計な条件を削除
ruleMetric <- selectRuleRRF(ruleMetric,train_iris,train_iris$Species)#条件文を集約
learner <- buildLearner(ruleMetric,train_iris,train_iris$Species,minFreq=0.01)#レアな(発生頻度の低い)ルールを切り落とし、1本に集約
readableRules <- presentRules(learner,colnames(train_iris)) #ルールを読みやすく加工
readableRules#結果の表示

len freq err condition pred
[1,] “1” “0.38” “0” “Petal.Length<=2.35" "setosa"
[2,] “3” “0.37” “0” “Petal.Length>2.35 & Petal.Length<=5.25 & Petal.Width<=1.65" "versicolor"
[3,] “1” “0.25” “0” “Else” “virginica”

ランダムフォレストは決定木のようにグラフィカルに表現できないのが欠点ですが、これでルールは読み解くことができます。

最後に

ランダムフォレストは過去のデータから高精度で予想・分類ができる方法です。
ビッグデータが叫ばれている昨今、過去のデータから未来のデータを予測する必要が出てきます。
その中でかなり強力なツールとなるのではないでしょうか?


コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA