
の続きです。今回はランダムフォレストモデルで分析してみます。
まず、トレーニング用のデータフレームとテスト用のデータフレームを用意します。

モデルを設定します。rand_forest()でエンジンはrangerを使います。

レシピを設定します。ランダムフォレストモデルでは前処理は必要ないようです。

モデルとレシピを合わせて、ワークフローを設定します。

チューニング・グリッドを設定します。

チューニングを実行します。

autoplot()でチューニング結果を可視化します。


最良のパラメータを選択します。

最良のパラメータで学習します。

テスト用のデータで予測します。

混合行列をみてみます。

各種指標をみてみます。

ROC AUCをみてみます。

0.639と今までで一番悪いですね。
ROC曲線を描きます。


いままでのモデルのROC AUCをまとめると、

glmnetエンジンでのElastic-Netが一番ですね。そして、ランダムフォレストモデルが一番成績が悪いです。これは何故かをCopilot先生に聞いてみました。
①. 説明変数が 3 つしかない → 木系モデルの強みが出にくい
Random Forest や rpart は、
「特徴量が多い」「非線形性が強い」「相互作用が複雑」
という状況で力を発揮します。
でも今回のデータは:
- Recency
- Frequency
- Time
の 3変数だけで、しかも
線形に近い構造を持っています。
だから、木系モデルは「分割の選択肢が少なすぎて」
アンサンブルの多様性が生まれないんですよね。
結果として:
- glm(線形)
- glmnet(線形+正則化)
の方が自然に強くなります。
②. Random Forest の mtry が 1,2,3 で差が出なかった理由
autoplot で確認した通り、
mtry の違いがほぼ影響しなかったのは、
説明変数が少なすぎて、どれを選んでも似たような木になる
からです。
これは「RF が弱い」のではなく、
データ構造が RF に向いていないというだけ。
③. min_n が大きいほど安定した理由
min_n を大きくすると木が浅くなり、
過学習が抑えられます。
今回のデータは単純なので、
- 深い木 → 過学習
- 浅い木 → 安定
という典型的なパターンが出ています。
④. ranger が一番低い AUC(0.639)なのは自然
これはむしろ「データの性質を正しく反映した結果」です。
- glm(線形)
- glmnet(線形+正則化)
- rpart(単純な木)
- ranger(複数の木の平均)
この中で、
線形モデルが最も適合しやすい構造をしているので、
glm / glmnet が上に来るのは当然なんですよね。
ということです。なるほど~と思いました。
今回は以上です。
はじめから読むには、
です。
今回のコードは、以下になります。
#
# 今回はランダムフォレストでやってみる
#
# トレーニング用のデータとテスト用のデータ
df_rf_train <- training(split) |>
mutate(Donated_Blood = as.factor(Donated_Blood))
df_rf_test <- testing(split) |>
mutate(Donated_Blood = as.factor(Donated_Blood))
#
# モデルを設定
rf_mod <- rand_forest(
mtry = tune(),
trees = 500,
min_n = tune()
) |>
set_engine("ranger") |>
set_mode("classification")
#
# レシピを設定
rf_rec <- recipe(Donated_Blood ~ ., data = df_rf_train)
#
# ワークフローを設定
rf_wf <- workflow() |>
add_model(rf_mod) |>
add_recipe(rf_rec)
#
# チューニンググリッドの設定
# Step1. 説明変数が3つなので mtry は 1, 2, 3 に固定
mtry_values <- 1:3
# Step2. min_n は広めに(例:2〜100)
min_n_values <- seq(2, 100, by = 4)
# Step3. expand_grid()を使う
rf_grid <- expand_grid(
mtry = mtry_values,
min_n = min_n_values
)
rf_grid
#
# チューニング実行
rf_tuned <- tune_grid(
rf_wf,
resamples = folds,
grid = rf_grid,
control = control_grid(save_pred = TRUE),
metrics = metric_set(roc_auc, accuracy)
)
#
# チューニング結果の可視化
autoplot(rf_tuned)
#
# 最良のパラメータを選択
best_params <- select_best(rf_tuned, metric = "roc_auc")
best_params
#
# 最良のパラメータで学習
rf_final_wf <- finalize_workflow(rf_wf, best_params)
rf_final_fit <- fit(rf_final_wf, df_rf_train)
#
# テスト用のデータで予測
rf_results <- df_rf_test |>
select(Donated_Blood) |>
bind_cols(
predict(rf_final_fit, df_rf_test, type = "class"),
predict(rf_final_fit, df_rf_test, type = "prob")
)
rf_results
#
# 混合行列
rf_results |>
conf_mat(truth = Donated_Blood, .pred_class)
#
# 各種評価
metrics <- metric_set(accuracy, sensitivity, specificity)
metrics(rf_results, truth = Donated_Blood, estimate = .pred_class)
#
# ROC AUC
roc_auc(rf_results, truth = Donated_Blood, .pred_0)
#
# ROC曲線
# Step1. ROC曲線データを作成
rf_roc <- roc_curve(rf_results, truth = Donated_Blood, .pred_0) |>
mutate(model = "Random Forest")
#
# Step2. 結合
roc_all <- roc_all |>
bind_rows(rf_roc)
#
# Step3. プロット
roc_all |>
ggplot(aes(x = 1 - specificity, y = sensitivity, color = model)) +
geom_path(linewidth = 1.2) +
geom_abline(lty = 2, color = "gray50") +
coord_equal() +
labs(title = "ROC曲線(logit, glmnet, tree, random forest))",
x = "1 - Specificity (False Posivie Rate)",
y = "Sencitivity (True Positive Rate") +
theme_bw()
#
# 今までのROC AUC
roc_auc(logit_result, truth = Donated_Blood, .pred_0)
roc_auc(glmnet_results, truth = Donated_Blood, .pred_0)
roc_auc(tree_results, truth = Donated_Blood, .pred_0)
roc_auc(rf_results, truth = Donated_Blood, .pred_0)
#
(冒頭の画像は、Bing Image Creatorで生成しました。プロンプトは、A beautiful, serene landscape photograph. Red roses bloom everywhere. です。)