gbm
zmienna \(y\) jako zmienna numeryczna, \(X\) jako zmienne czynnikowe (bez wyrzucania stałej kolumny powinno zadziałać)
zmienna \(y\) jako zmienna numeryczna, \(X\) przekodowane na zmienne binarne (funkcja dummyVars
nie przyjmie stałej kolumny)
Przykład jak szybko przekodować (one-hot encoder):
x1 <- factor(c("a", "a", "b", "c", "b"), levels=c("a", "b", "c"))
x2 <- factor(c("dobrze", "dobrze", "srednio", "srednio", "srednio"), levels=c("dobrze", "srednio"))
df <- data.frame(x1, x2)
df
## x1 x2
## 1 a dobrze
## 2 a dobrze
## 3 b srednio
## 4 c srednio
## 5 b srednio
library(caret)
dmy <- dummyVars(" ~ .", data = df)
df_nowe <- data.frame(predict(dmy, newdata = df))
df_nowe
## x1.a x1.b x1.c x2.dobrze x2.srednio
## 1 1 0 0 1 0
## 2 1 0 0 1 0
## 3 0 1 0 0 1
## 4 0 0 1 0 1
## 5 0 1 0 0 1
xgboost
xgb.DMatrix
lub po prostu matrix
, as.matrix
)Skorzystamy z danych Boston
. Zmienna medv
to mediana wartości domu i to będziemy modelować w zależności od innych zmiennych (przekodowałam na 1 - drogie domy, 0 - nie). Od razu robię podział na trening i zbiór testowy.
library(MASS)
df <- Boston
df$medv <- ifelse(df$medv < 25, "tani", "drogi")
df$medv <- make.names(df$medv)
df$medv <- factor(df$medv, levels=c("drogi", "tani"))
set.seed(123)
ind.train <- sample(1:nrow(Boston), size=350, replace=FALSE)
ind.test <- setdiff(1:nrow(Boston), ind.train)
df_train <- df[ind.train,]
df_test <- df[ind.test,]
str(df)
## 'data.frame': 506 obs. of 14 variables:
## $ crim : num 0.00632 0.02731 0.02729 0.03237 0.06905 ...
## $ zn : num 18 0 0 0 0 0 12.5 12.5 12.5 12.5 ...
## $ indus : num 2.31 7.07 7.07 2.18 2.18 2.18 7.87 7.87 7.87 7.87 ...
## $ chas : int 0 0 0 0 0 0 0 0 0 0 ...
## $ nox : num 0.538 0.469 0.469 0.458 0.458 0.458 0.524 0.524 0.524 0.524 ...
## $ rm : num 6.58 6.42 7.18 7 7.15 ...
## $ age : num 65.2 78.9 61.1 45.8 54.2 58.7 66.6 96.1 100 85.9 ...
## $ dis : num 4.09 4.97 4.97 6.06 6.06 ...
## $ rad : int 1 2 2 3 3 3 5 5 5 5 ...
## $ tax : num 296 242 242 222 222 222 311 311 311 311 ...
## $ ptratio: num 15.3 17.8 17.8 18.7 18.7 18.7 15.2 15.2 15.2 15.2 ...
## $ black : num 397 397 393 395 397 ...
## $ lstat : num 4.98 9.14 4.03 2.94 5.33 ...
## $ medv : Factor w/ 2 levels "drogi","tani": 2 2 1 1 1 1 2 1 2 2 ...
caret
i caretEnsemble
library(caret)
library(caretEnsemble)
Ustawienia opcji:
"repeatedcv"
oznacza, że kroswalidacja number
-krotna zostanie powtórzona repeats
razyclassProbs
czy prawdopodobieństwo klas ma być liczonesavePredictions
czy wszystkie predykcje mają być zapisywane, czy tylko te dla najlepszego modelusummaryFunction = twoClassSummary
pozwoli jako optymalizowaną miarę zastosować AUCcontrol <- trainControl(method="repeatedcv", number=5, repeats=5,
classProbs=TRUE, savePredictions='all',
summaryFunction = twoClassSummary)
Jakie modele będziemy łączyć:
algorithmList <- c('rpart', 'glm', 'lda')
Budujemy modele wymienione w algorithmList
według control
, optymalizujemy AUC (metric='ROC'
). Dodatkowo wyliczana będzie czułość i specyficzność dla punktu odcięcia 0.5.
set.seed(123)
stack_models <- caretList(medv~., data=df_train, trControl=control, methodList=algorithmList, metric='ROC')
Funkcja resamples
pozwala zebrać i podsumować wyniki wszystkich modeli łącznie:
stacking_results <- resamples(stack_models)
Na ile modele są ze sobą skorelowane:
summary(stacking_results)
##
## Call:
## summary.resamples(object = stacking_results)
##
## Models: rpart, glm, lda
## Number of resamples: 25
##
## ROC
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## rpart 0.7532051 0.8002137 0.8872863 0.8632692 0.9086538 0.9476496 0
## glm 0.8792735 0.9273504 0.9433761 0.9421795 0.9615385 0.9882479 0
## lda 0.8579060 0.9081197 0.9326923 0.9261538 0.9497863 0.9764957 0
##
## Sens
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## rpart 0.5000000 0.6111111 0.7222222 0.7333333 0.8333333 0.9444444 0
## glm 0.6111111 0.7777778 0.7777778 0.7977778 0.8333333 0.9444444 0
## lda 0.5000000 0.6111111 0.7222222 0.6933333 0.7222222 0.8888889 0
##
## Spec
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## rpart 0.8653846 0.9230769 0.9423077 0.9376923 0.9615385 1.0000000 0
## glm 0.8461538 0.9230769 0.9423077 0.9369231 0.9423077 0.9807692 0
## lda 0.9038462 0.9423077 0.9615385 0.9623077 0.9807692 1.0000000 0
dotplot(stacking_results)
Budowa komitetów:
stackControl <- trainControl(method="repeatedcv", number=5, repeats=5,
savePredictions='all', classProbs=TRUE,
summaryFunction = twoClassSummary)
Komitet 1 (predykcje modeli połączone modelem liniowym)
model.ensemble <- caretEnsemble(stack_models, trControl=stackControl, metric = "ROC")
plot(model.ensemble)
summary(model.ensemble)
## The following models were ensembled: rpart, glm, lda
## They were weighted:
## 3.5438 -1.8746 -3.4883 -1.9204
## The resulting ROC is: 0.9507
## The fit for each individual model on the ROC is:
## method ROC ROCSD
## rpart 0.8632692 0.06100930
## glm 0.9421795 0.02724764
## lda 0.9261538 0.03601885
Komitet 2 (predykcje modeli połączone gradient boostingiem)
library(gbm)
model.gbm <- caretStack(stack_models, method="gbm", trControl=stackControl, metric = "ROC", verbose = FALSE)
plot(model.gbm)
summary(model.gbm)
## var rel.inf
## glm glm 54.28523
## lda lda 27.05308
## rpart rpart 18.66169
Wyniki:
predykcje <- data.frame(predict(stack_models, df_test))
predykcje[,"komitet1"] <- predict(model.ensemble, newdata=df_test, type = "prob")
predykcje[,"komitet2"] <- predict(model.gbm, newdata=df_test, type = "prob")
## rpart glm lda komitet1 komitet2
## 1 0.9058062 0.9385965 0.9381788 0.9490393 0.9417293