Rで何かをしたり、読書をするブログ

政府統計の総合窓口のデータや、OECDやUCIやのデータを使って、Rの練習をしています。ときどき、読書記録も載せています。

UCI Machine Learning Repository の Chess (King-Rook vs. King-Pawn) のデータの分析3 - ランダムフォレストによる分類。素晴らしい性能

www.crosshyou.info

の続きです。前回はglmnetパッケージを使い、Elastic-Netで分類してみました。ROCのAUCが0.996と非常に素晴らしい値でした。正直、Elastic-Netでここまで高精度の分類器が作れたので、もういいかな、と思いましたが、今回は、tidymodelsパッケージを使い、rangerエンジンでランダムフォレストモデルを試してみます。

まず、トレーニング用のデータとテスト用のデータにわけます。

モデルを作ります。rand_forest()で、set_engine()でrangerを指定します。特徴量の重要度も見たいので、importance = "impurity"を加えておきます。mtryとmin_nはあとでチューニングできるように、ここでは、tune()としておきます。

レシピを作ります。

step_dummy()でファクター型の変数を0/1のダミー変数にして、step_zv()でゼロ分散の特徴量を除外するというレシピです。

ワークフローは、モデルとレシピを合体させただけです。

fold_cv()関数でクロスバリデーションの各foldを作ります。

チューニング・グリッドを作ります。grid_regular関数を使いました。

tune_grid()関数でチューニングを実行します。結構、時間かかりました。私のLaptop(プロセッサ:Intel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz (1.19 GHz) / 実装 RAM:8.00 GB (7.71 GB 使用可能))だと、5分かかりました。

最適なパラメータを確認します。

mtry = 20, min=n = 2 が最適パラメータでした。この最適なパラメータで、最終ワークフローを作成し、train_dataで学習します。

vipパッケージのvip関数で、重要な変数を調べてみます。

X21, X10, X33が重要度が大きいですね。

前回のElastic-Netのモデルでは、どの変数が重要だったか、みてみましょう。

X21, X10, X33とランダムフォレストと同じ順番で重要となっていますね。

テスト用データで予測しましょう。

ROCのAUCを計算します。roc_auc()関数です。

おお!1.000です!完璧ですね。

混合行列をみてみます。

いや~!凄いですね。7個しか間違えてないです。ランダムフォレスト、素晴らしいですね。Sensitivityとか、Specificityを計算してみようと思います。

カスタム関数を作って、一括計算しました。

どれも素晴らしい性能を表していますね。正解率は、99.3%、F1-Scoreが99.3%という精度です。

今回は以上です。

はじめから読むには、

www.crosshyou.info

です。

今回のコードは以下になります。

#
# トレーニング用のデータとテスト用のデータに分ける
train_data <- df[train, ]
test_data <- df[-train, ]
#
# モデルの作成
rf_model <- rand_forest(
  mtry = tune(),
  min_n = tune(),
  trees = 500
) |>
  set_engine("ranger", importance = "impurity") |>
  set_mode("classification")
#
# レシピの作成
rf_recipe <- recipe(target ~ ., data = train_data) |>
  step_dummy(all_nominal_predictors()) |>
  step_zv(all_predictors())
#
# ワークフローの作成
rf_wf <- workflow() |>
  add_model(rf_model) |>
  add_recipe(rf_recipe)
#
# クロスバリデーションの設定
set.seed(123)
folds <- vfold_cv(train_data, v = 10, strata = target)
#
# チューニング・グリッドを作成
rf_grid <- grid_regular(
  mtry(range = c(2, 20)),
  min_n(range = c(2, 20)),
  levels = 5
)
#
# チューニングの実行
set.seed(123)
rf_tuned <- tune_grid(
  rf_wf,
  resamples = folds,
  grid = rf_grid,
  metrics = metric_set(roc_auc, accuracy)
)
#
# 最適なパラメータの確認
best_params <- select_best(rf_tuned, metric = "roc_auc")
best_params
#
# 最終ワークフローと最終学習モデル
final_rf_wf <- finalize_workflow(rf_wf, best_params)
final_rf_fit <- fit(final_rf_wf, data = train_data)
#
# 重要な変数の表示
library(vip)
final_rf_fit |>
  extract_fit_parsnip() |>
  vip(num_features = 20)
#
# Elastic-Netの変数の重要度
coef_abs <- coef(c0.8, s = "lambda.1se") |> abs() |> round(4)
coef_abs[rev(order(coef_abs[ , 1])), ]
#
# テスト用データで予測
rf_pred <- predict(final_rf_fit, test_data, type = "prob") |>
  bind_cols(predict(final_rf_fit, test_data)) |>
  bind_cols(test_data |> select(target))
rf_pred
#
# ROCのAUC
roc_auc(rf_pred, truth = target, .pred_nowin)
#
# 混合行列
conf_mat(rf_pred, truth = target, estimate = .pred_class)
#
# Sensitivityなどを計算する
conf_mat_metrics <- function(TN, FN, FP, TP) {
  
  Accuracy <- (TN + TP) / (TN + FN + FP + TP)
  Sensitivity <- TP / (TP + FN)
  Specificity <- TN / (TN + FP)
  Precision <- TP / (TP + FP)
  F1_Score <- 2 * (TP / (TP + FP)) * (TP / (TP + FN)) / 
    *1 + (TP / (TP + FN)))
  
  tibble(
    metric = c("Accuracy", "Sensitivity", "Specitificty",
               "Precision", "F1_Score"),
    value = c(Accuracy, Sensitivity, Specificity, Precision, F1_Score)
  )
  
}
conf_mat_metrics(449, 1, 6, 503)
#

 

(冒頭の画像は、Bing Image Creator で生成しました。プロンプトは、Beautiful landscape of 300 years old natural green grass field and higher mountains and close up of red Oleander flowers and trees. Photo です。)

 

*1:TP / (TP + FP