Nessa continuação iremos usar outro método, muito poderoso e rápido, para a predição das notas e compará-las aos resultados obtidos no artigo anterior.
Caso não tenha visto, Veja aqui!
Usaremos os mesmo banco de dados, com diferentes inputs. Significa que usaremos mais variáveis para o nosso modelo. O XGBoost está entre os algoritmos com maior destaque, pois sua maior simplicidade de calculo e rapidez de processamento o torna popular, não só isso, está entre os melhores, e ganhando inúmeras competições.
Porém o modelo necessita de alguma particularidades e é em cima disso que iremos trabalhar, se forma simples, pois nosso banco de dados facilita nosso trabalho.
definimos o diretório (etapa não obrigatória, pois importaremos o banco de dados de um pacote)
diretorio <- getwd()
setwd(diretorio)
Importaremos os pacotes necessários para realizar nosso modelo:
library(tidyverse)
## -- Attaching packages -------------------------------------------- tidyverse 1.2.1 --
## v ggplot2 2.2.1 v purrr 0.2.4
## v tibble 1.4.1 v dplyr 0.7.4
## v tidyr 0.7.2 v stringr 1.2.0
## v readr 1.1.1 v forcats 0.2.0
## -- Conflicts ----------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(xgboost)
##
## Attaching package: 'xgboost'
## The following object is masked from 'package:dplyr':
##
## slice
De maneira simples e igualmente ao exemplo anterior, importamos o banco de dados do pacote:
prime <- ggplot2movies::movies
Da mesma maneira selecionamos e limpamos os dados.
Note que, ao contrário do exemplo anterior, selecionamos ainda dummy variables referentes ao tipo de filme (drama, ação, comédia, etc)
dados <- ggplot2movies::movies %>%
filter(!is.na(budget), budget > 0) %>%
select( year, budget, rating, Action, Animation, Comedy, Drama, Documentary, Romance, Short) %>%
arrange(desc(year))
Para validação do modelo é necessário saber o quão bom nosso modelo está sendo.
Então faremos a seleção de 75% dos dados para treinamento e 25% para teste.
Definimos train e test.
smp_size <- floor(0.75 * nrow(dados))
train_ind <- sample(seq_len(nrow(dados)), size = smp_size)
train <- dados[train_ind, ]
test <- dados[-train_ind, ]
labels <- train$rating
ts_label <- test$rating
O XGBoost necessita que os dados estejam em matrix ou no formato proprio xgb.mtx para isso transformamos o nosso data.frame em matrix.
Note que aqui, obrigatoriamente devemos ter dados numéricos. Pode ser um empasse se tiver fatores, comuns em data.frames. Porém podem ser facilmente convertidos em dummy variables. No nosso caso, já possuimos o formato correto, porém pode ser facilmente conseguido atravéz de vários pacotes em R.
Poderíamos ter feito antes e depois ter dividido os dados, nos evitaria gastar algumas linhas de códigos.
new_tr <- model.matrix(~.+0,train[,-3])
new_ts <- model.matrix(~.+0,test[,-3])
dados_matrix <- data.matrix(dados, rownames.force = NA)
Para melhor desempenho, como recomenda o desenvolvedor. Então faremos isso:
dtrain <- xgb.DMatrix(data = new_tr, label = labels)
dtest <- xgb.DMatrix(data = new_ts, label = ts_label)
Vamo agora criar nosso modelo como reg:linear
, eta=0.3
, gamma=0
, max_depth=6
, min_child_weig=1
,subsample=1
e colsample_bytree=1
Esses são nossos parametros padrões
params <- list(booster = "gbtree", objective = "reg:linear",
eta=0.3, gamma=0, max_depth=6, min_child_weight=1,
subsample=1, colsample_bytree=1)
Usando a função nativa do modelo xgb.cv
, vamos calcular o melhor numero de rounds nrounds
para esse modelo. E mais, essa função também retorna o erro de CV que é uma estimativa do erro do modelo.
Chamamos nossos parametro params
, os dados para treinamento no formato xgb dtrain
, nround=100
, nfold=5
e com early.stop.round=20
. Imprimindo a cada 10 rounds.
xgbcv <- xgb.cv( params = params, data = dtrain,
nrounds = 100, nfold = 5, showsd = T, stratified = T,
print_every_n = 10, early_stop_round = 20, maximize = F)
## [1] train-rmse:4.208212+0.006881 test-rmse:4.213284+0.045450
## [11] train-rmse:1.214817+0.005037 test-rmse:1.351302+0.018935
## [21] train-rmse:1.131980+0.012267 test-rmse:1.353012+0.021421
## [31] train-rmse:1.077095+0.009034 test-rmse:1.362972+0.020514
## [41] train-rmse:1.030146+0.009939 test-rmse:1.372006+0.021572
## [51] train-rmse:0.991713+0.009474 test-rmse:1.380108+0.019636
## [61] train-rmse:0.953274+0.013946 test-rmse:1.389901+0.022987
## [71] train-rmse:0.919142+0.019412 test-rmse:1.400244+0.024642
## [81] train-rmse:0.884433+0.019332 test-rmse:1.412106+0.028881
## [91] train-rmse:0.859247+0.016239 test-rmse:1.420127+0.025833
## [100] train-rmse:0.841786+0.018456 test-rmse:1.427388+0.027767
Também avaliamos o RMSE mínimo.
min(xgbcv$evaluation_log$train_rmse_mean)
## [1] 0.8417856
Dos dados resultantes da função de validação cruzada, temos nrounds=90
xgb1 <- xgb.train (params = params, data = dtrain, nrounds = 90,
watchlist = list(val=dtest,train=dtrain), print_every_n = 10,
early_stop_round = 10, maximize = F , eval_metric = "error")
## [1] val-error:-5.166821 train-error:-5.127039
## [11] val-error:-5.166821 train-error:-5.127039
## [21] val-error:-5.166821 train-error:-5.127039
## [31] val-error:-5.166821 train-error:-5.127039
## [41] val-error:-5.166821 train-error:-5.127039
## [51] val-error:-5.166821 train-error:-5.127039
## [61] val-error:-5.166821 train-error:-5.127039
## [71] val-error:-5.166821 train-error:-5.127039
## [81] val-error:-5.166821 train-error:-5.127039
## [90] val-error:-5.166821 train-error:-5.127039
De forma simples escrevemos apenas:
xgbpred <- predict(xgb1,dtest)
Calculamos simplesmento o RMSE entre o valor predito e o valor real do filme.
library(caret)
## Loading required package: lattice
##
## Attaching package: 'caret'
## The following object is masked from 'package:purrr':
##
## lift
xgb1_rmse <- RMSE(test$rating, xgbpred)
xgb1_rmse
## [1] 1.418679
Sendo esse o valor do erro médio quadrátido.
Para ficar bonito, plotamos o grafico que nos diz o grau de importancia das variáveis:
library(caret)
mat <- xgb.importance (feature_names = colnames(new_tr),model = xgb1)
xgb.plot.importance (importance_matrix = mat[1:9], col=3)
Assim vemos que ao adicionar nota a um filme, o fator mais importante é o orçamento, seguido do ano de lançamento. Tiramos a importante informação que se o filme for drama e curtametragem também tem peso significativo para o valor da nota.
É isso. Qualquer dúvida fique a vontade de enviar um e-mail para vinicius.lucena.souza@gmail.com