前回、Xgboost のパラメータについて列挙しましたが、あれだけ見ても実際にどう使うのかよく分かりません。そこで今回はR で、とりあえず iris data を用いてその使い方を見ていきたいと思います。
まず、iris data の奇数番目を訓練データ、偶数番目を検証データとします。
dim(iris) # 行数:150, 列数:5 odd.n<-2*(1:75)-1 iris.train<-iris[odd.n,] # 奇数を訓練データ iris.test<-iris[-odd.n,] # 偶数を検証データ
次に、xgboost に適した形式に変換します。
library(xgboost) y <- iris.train[,5] # 目的変数 y <- as.integer(y)-1 #xgboost で既定されいるクラスは 0 base train.x<-iris.train[,1:4] x <- rbind(train.x,iris.test[,-5]) # xgboost を使うときのため x <- as.matrix(x) trind <- 1:length(y) # 先程定義したx の中の訓練データを指すのに使う teind <- (nrow(train.x)+1):nrow(x) # 先程定義したx の中の検証用データを指すのに使う
必要最低限のパラメータの設定は次のようになります。
set.seed(131) # 固定シードで試す param <- list("objective" = "multi:softprob", # 多クラスの分類で各クラスに所属する確率を求める "eval_metric" = "mlogloss", # 損失関数の設定 "num_class" = 3 # class がいくつ存在するのか )
実際に、予測をする前に最適な木の数を探します。
k<-round(1+log2(nrow(train.x))) cv.nround <- 100 #search bst.cv <- xgb.cv(param=param, data = x[trind,], label = y, nfold = k, nrounds=cv.nround)
これを実行すると、次のような結果が出てきます。
[0] train-mlogloss:0.752857+0.007342 test-mlogloss:0.772249+0.027355 [1] train-mlogloss:0.542712+0.008457 test-mlogloss:0.569818+0.047944 [2] train-mlogloss:0.404424+0.008669 test-mlogloss:0.441932+0.068164 [3] train-mlogloss:0.306743+0.007542 test-mlogloss:0.351062+0.084861 (略) [26] train-mlogloss:0.031981+0.002944 test-mlogloss:0.121880+0.128820 (略) [97] train-mlogloss:0.023760+0.001694 test-mlogloss:0.134890+0.156262 [98] train-mlogloss:0.023744+0.001690 test-mlogloss:0.135084+0.156458 [99] train-mlogloss:0.023728+0.001686 test-mlogloss:0.135296+0.156967
この場合、検証データにおける最適な木の数は26+1(0 baseのため)となります。
これを基に予測をしてみます。
set.seed(131) nround <- 27 # モデルの構築 bst <- xgboost(param=param, data = x[trind,], label = y, nrounds=nround) pred <- predict(bst,x[teind,]) # モデルを使って予測値を算出 pred <- matrix(pred,3,length(pred)/3) # 今回は3クラスあるので pred <- t(pred) colnames(pred)<-c("setosa","versicolor","virginica")
結果を見てみると、
head(pred,3) setosa versicolor virginica [1,] 0.9838002 0.008915161 0.007284546 [2,] 0.9870363 0.008944485 0.004019236 [3,] 0.9870363 0.008944485 0.004019236
となっていて、各データが"setosa","versicolor","virginica"のどれに属するかの確率が求められています。この中の最大値をとるクラスに、そのデータは属すると思われます。
このような確率に興味がなく、どこのグループに属するかだけを知りたいなら次のように"multi:softmax"を使います。
param <- list("objective" = "multi:softmax", # multi:softmax に変更! "eval_metric" = "mlogloss", "num_class" = 3 ) set.seed(131) nround <- 27 bst <- xgboost(param=param, data = x[trind,], label = y, nrounds=nround) pred <- predict(bst,x[teind,])
データを整えて、結果を見てみます。
for(i in 1:length(pred)){ if(pred[i]==0) {pred[i]="setosa"} else if(pred[i]==1) {pred[i]="versicolor"} else {pred[i]="virginica"} } table(iris.test[,5],pred) # 結果 pred setosa versicolor virginica setosa 25 0 0 versicolor 0 23 2 virginica 0 0 25
これが良いのかどうかいまいち分からないので、とりあえずランダムフォレストと比較してみます。
odd.n<-2*(1:75)-1 iris.train<-iris[odd.n,] # 奇数を訓練データ iris.test<-iris[-odd.n,] # 偶数を検証データ # randomForest library(randomForest) set.seed(131) train.x<-iris.train[,1:4] train.y<-as.factor(iris.train[,5]) model.rf<-tuneRF(train.x,train.y,doBest=T) pred<-predict(model.rf,iris.test[,-5]) table(iris.test[,5],pred) # 結果 pred setosa versicolor virginica setosa 25 0 0 versicolor 0 24 1 virginica 0 2 23
これだけでは、なんとも言えなさそうですが、xgboost の性能の高さは認めらるかなと思います。