どうも、solobochiのbochiです。
昨年、データサイエンティスト協会主催のデータサイエンティスト養成講座を受講し、その中でRを使ったデータ分析手法を学んだのでその復習兼ねてまとめておきます。
目次
5.モデル構築
前回記事↓まででデータ分析で最も手間のかかる前処理工程及び決定木での分析まで実施したので、同様にランダムフォレスト、XGBoostでの分析を実施する。
ランダムフォレスト(RandomForest)
# RandomForest # 構築データの割合 rate <- 0.75 # 構築データ数(小数の切捨て) num1 <- as.integer(nrow(train_data_ohe3)*rate) # 再現性のため乱数シードを固定 set.seed(17) # sample(ベクトル, ランダムに取得する個数, 復元抽出の有無) row1 <- sample(1:nrow(train_data_ohe3), num1, replace=FALSE) # 学習データ rf_train_train <- train_data_ohe3[row1,] %>% dplyr::select(-y) y_train_train <- train_data_ohe3[row1,] %>% dplyr::select(y) # 検証データ rf_train_test <- train_data_ohe3[-row1,] %>% dplyr::select(-y) y_train_test <- train_data_ohe3[-row1,] %>% dplyr::select(y) # モデル構築(学習) rf <- randomforest(rf_train_train, #学習データ(説明変数) as.factor(rf_train_train$y), #学習データ(目的変数) mtry=12, #1本の木に使う特徴量の数(パラメータチューニングで最適化する) sampsize=nrow(rf_train_train)*0.25, #各決定木に使うデータ数 nodesize=20, #各決定木のノードが含むサンプルデータ最小数 maxnode=150, #各決定木のノードが含むサンプルデータ最大数 ntree=90, #決定木の数 importance=T) # モデルの確認 rf # 変数重要度 print(importance(rf)
使ったコマンド
randomforest
使用目的:ランダムフォレストモデルの構築(学習)
使用方法:randomforest(dataframe(説明変数),
y(目的変数),
mtry(各決定木に用いる特徴量の数),
sampsize(モデル構築に用いるデータ数),
nodesize(各決定木の終端ノードにおける最小サンプル数),
maxnode(各決定木の終端ノードにおける最大サンプル数),
ntree(生成する決定木の数),
importance(変数重要度の有無),
)
👉OOB(Out-Of-Bag):10.05%ということで、学習時点でモデルの予測エラー率は約10%
👉変数重要度。durationが圧倒的に高い点は決定木と同じ結果。
これをテストデータにも適用させて精度を検証する。
# predict pred_rf <- predict(rf, rf_train_test, type="prob")[,2] # auc auc_rf <- roc(y_train_test, pred_rf) print(auc_rf)
👉AUCは0.91とまずまずの値となりました。
さらにXGBoostでも分析を実施する。
※XGBoost:eXtremely Gradient Boosting。RandomForestとGradientBoostingをアンサンブル学習させた勾配ブースティング決定木のライブラリ。
XGBoost
# xgboost # 行列に変換 x_train_xgb <- as.matrix(dplyr::select(train_data_ohe3, -y)) x_test_xgb <- as.matrix(dplyr::select(test_data_ohe3)) # 目的変数(学習データのみ) y_train_xgb <- train_data_ohe3$y # Hold out # 構築データの割合 rate <- 0.7 # 構築データ数 num2 <- as.integer(nrow(x_train_xgb)*rate) set.seed(17) # 学習データ row2 <- sample(1:nrow(x_train_xgb), num2, replace=FALSE) xgb_train_train <- x_train_xgb[row2,] #訓練データ xgb_train_test <- x_train_xgb[-row2,] #検証データ y_train_train <- y_train_xgb[row2,] #訓練データの目的変数 y_train_test <- y_train_xgb[-row2,] #検証データの目的変数 # パラメータ設定 parm <- list(objective="binary:logistic", #学習方法(binary:logisticは2クラス分類の確率で出力) eval_metric = "auc", #評価指標(validation) eta = 0.07, #学習率(ステップごとの学習幅) max_depth = 10, #決定木の階層数 min_child_weight = 10, #最小ノード数(これを下回ると分割を止める) colsample_bytree = 0.4, #各決定木を作る際に使う列数をサンプリングする割合 gamma = 0.9, #損失還元最小値(決定木の葉の数に対するペナルティ、過学習の抑制) subsample = 1 #学習に使用するデータ(標本)の割合 ) #xgb.cv(Cross Validation)による最適パラメータ探索(nrounds:ブースティング回数、決定木の本数を最適化する) xgbcv <- xgb.cv(param = parm, #パラメータ(objective,eval_metric,eta,max_depthなど) data = x_train_train, #訓練データ label = y_train_train, #目的変数 nrounds = 400, #施行回数 nfold = 10, #分割数 nthread = 1 #使用CPU数 ) # モデル構築 model_xgb <- xgboost(param = parm, #パラメータ data = x_train_train, #訓練データ label = y_train_train, #目的変数 nrounds = which.max(xgbcv$evaluation_log$test_auc_mean), nthread = 1, importance = True ) # train_testのauc pred_xgb <- predict(model_xgb, x_train_test) auc_xgb <- roc(y_train_test, pred_xgb) print(auc_xgb)
使ったコマンド xgboost xgboostのパラメータの詳細についてはこちらのリファレンス参照。
使用目的:xgboostのモデル構築
使用方法:xgboost(param, data, label, nrounds, nthread, importance)
※param = objective, eval_metric, eta, max_depth, min_child_weight, colsample_bytree, gamma, subsample
xgboostリファレンス
👉AUCは92.3%となり、RandomForestよりも若干良いスコアになりました。
6.予測と結果
続いて、ここまで作成してきたモデルを使ってコンペ用のデータに対して予測を行います。
決定木
# submit test_pred_tree <- predict(tree2, test_data_ohe3) test_pred_tree <- test_pred_tree[,2] # CSV出力(コンペ提出の形式) out_tree <- data.frame(test_data_ohe3$id, test_pred_tree) write.table(out_tree, #出力データ "/Users/xxxxx/xxxxx.csv", #任意のディレクトリ配下に出力ファイルを作成 quote = FALSE , #文字列を""で囲むかどうか col.names = FALSE, #変数名の有無 row.names = FALSE, #行番号の有無 sep = ',' #区切り文字の設定 )
これで作成されるファイルを投稿すれば提出すれば完了。
決定木のデータでの精度は、およそ75%でした。
続いてランダムフォレストでもやってみる。
RandomForest
# submit # predict pred_test_rf <- predict(rf, test_data_ohe3, type="prob") pred_test_rf <- pred_test_rf[,2] # submit形式に出力 submit_rf <- data.frame(test_data_ohe3$id, pred_test_rf) write.table(submit_rf, #出力データ "/Users/xxx/xxx.csv", quote = FALSE, col.names = FALSE, row.names = FALSE, sep = "," )
👉ランダムフォレストの結果、精度が91.3%に向上しました。
最後にxgboostでも同様に予測、投稿して結果を検証する。
XGBoost
# submit # predict x_test_xgb <- as.matrix(dplyr::select(test_data_ohe3, -id)) pred_test_xgb <- predict(model_xgb, x_test_xgb, type="response") pred_test_xgb <- pred_test_xgb[,2] # submit形式に出力 submit_xgb <- data.frame(test_data_ohe3$id, pred_test_xgb) write.table(submit_xgb, #出力データ "/Users/xxx/xxx.csv", quote = FALSE, col.names = FALSE, row.names = FALSE, sep = "," )
👉精度が92.4%へと向上しました。
決定木(75%) < RandomForest(91.3%) < XGBoost(92.4%)
という結果になりました。
最後に、これらの結果をアンサンブル学習させてみます。
# colname names(out_tree2)[which(names(out_tree2)=="test_data_ohe3.id")] <- "id" names(out_tree2)[which(names(out_tree2)=="test_pred_tree")] <- "pred_tree" names(submit_rf2)[which(names(submit_rf2)=="test_data_ohe3.id")] <- "id" names(submit_rf2)[which(names(submit_rf2)=="pred_test_rf2")] <- "pred_rf" names(submit_xgb2)[which(names(submit_xgb2)=="test_data_ohe3.id")] <- "id" names(submit_xgb2)[which(names(submit_xgb2)=="pred_test_xgb")] <- "pred_xgb" # merge submit_tr_rf <- merge(out_tree2, submit_rf2, by = "id") submit_tr_rf_xgb <- merge(submit_tr_rf, submit_xgb2, by = "id") # ensemble submit_tr_rf_xgb <- mutate(submit_tr_rf_xgb, mean1 = (pred_tree*0.05 + pred_rf*0.15 + pred_xgb*0.8)) collist1 <- c("id","mean1") submit_en1 <- submit_tr_rf_xgb[,collist1] # submit形式に出力 write.table(submit_en1, #出力データ "/Users/xxx/xxx.csv", quote = FALSE, col.names = FALSE, row.names = FALSE, sep = ',' )
👉わずかですが、xgboost単体から92.5%まで精度向上しました。
7.評価
これまでの結果をまとめると以下の通り。
まず手元の学習データでの精度は、
・決定木 74.4%
・RandomForest 91%
・XGBoost 92.3%
続いて投稿した未知のデータでの精度では、
・決定木 75%
・RandomForest 91.3%
・XGBoost 92.4%
・アンサンブル 92.5%
となりました。
ー
以上