Data Blue

データの海で遊んでます。

Irisデータで勾配ブースティング

実際にxgboostを使用して、Gradient Boostingをしてみます。 今回は、Irisデータを7:3にトレーニングとテストに分けて、XGboostをやってみます。

Petal.Widthがデータ平均以下/以上の予測を行うことにします。

とりあえず、R上で下記を走らせてみます。

# Preparation ##################################
# rm(list=ls())
# setwd("~/")
library(dplyr)
library(data.table)
library(xgboost)
library(caTools)
library(Matrix)
library(verification)

# load iris
dt = data.table(iris)

# Dichotomize Petal Width, split data ###########
dt[, Petal.Width:= ifelse(Petal.Width > mean(dt$Petal.Width), 1, 0)]
lab  = dt$Petal.Width # label
set.seed(123)
split= sample.split(lab, SplitRatio = 0.7)
sm   = sparse.model.matrix(Petal.Width~.-1, data=dt)
sm1  = sm[split == T,] ; lb1 = lab[split == T] # train
sm2  = sm[split == F,] ; lb2 = lab[split == F] # test

# XGB boosting
classifier = xgboost(data = sm1, label = lb1, nrounds = 5, objective = 'binary:logistic')
importance <- xgb.importance(feature_names = colnames(sm1), model = classifier)
importance2  <- xgb.importance(feature_names = colnames(sm1), model = classifier)
xgb.plot.importance(importance_matrix = importance2)

# ROC
pred = predict(classifier, newdata = sm2)
roc.plot(lb2, pred, legend=T)

# Confusion matrix
pred2 = (pred >= 0.5)
table(lab[split==F], pred2)

# See the data structure
plot(iris$Petal.Length, iris$Petal.Width)

importanceは各変数をどのポイントで分けると分離が良いかを示しており、importance2はそれを変数ごとにまとめたものです。 ここでは、Petal.Lengthのみで、Petal.Widthの大/小をほぼ分けられています。f:id:mako_shark:20171021053241p:plain

これは、下記のように、Petal.WidthとPetal.Lengthがとても強い相関を示していることから理解できると思います。 f:id:mako_shark:20171021041101p:plain

ROCとConfusion matrixは、テストデータでのモデル性能がとても良いことを示しています。

これでは、面白くないので、Petal.Lengthを消してみて、同じことをしてみます。

# Erase Petal.Length
dt[, Petal.Length:=NULL]
sm = sparse.model.matrix(Petal.Width~.-1, data=dt)
sm1  = sm[split == T,] ;  # train
sm2  = sm[split == F,] ;  # test

# XGB boosting
classifier = xgboost(data = sm1, label = lb1, nrounds = 10, objective = 'binary:logistic')
importance <- xgb.importance(feature_names = colnames(sm1), model = classifier)
importance2  <- xgb.importance(feature_names = colnames(sm1), model = classifier)
xgb.plot.importance(importance_matrix = importance2)

# Prediction
pred = predict(classifier, newdata = sm2)
roc.plot(lb2, pred)
pred2 = (pred >= 0.5)
table(lab[split==F], pred2)

今回は、Speciesの違いも説明変数に入ってきました。 f:id:mako_shark:20171021053757p:plain

最後に、xgboostでは、

classifier = xgboost(data = sm1, label = lb1, nrounds = 10, objective = 'reg:linear')

とObjectiveを変えることで、直線回帰もできるようです。