Iremos apresentar nosso trabalho utilizando a base de dados do Titanic. É uma base famosa e de fácil compreensão. Utilizaremos três técnicas de previsão que foram apresentados durante o curso de Data Science: * ÁRVORE DE DECISÃO * PROBIT * LOGIT
Também faremos análise gráficas para ilustrar e mensurar o trabalho feito.
O objetivo do trabalho é utilizar as variáveis de características dos passageiros para prever as mortes do acidente.
Estruturamos o script em basicamente quatro etapas:
Comando que verifica se o pacote está instalado. Se não estiver, instala e carrega.
if(!require(rpart)) {install.packages("rpart")}
require(rpart)
if(!require(rattle)) {install.packages("rattle")}
require(rattle)
if(!require(rpart.plot)) {install.packages("rpart.plot")}
require(rpart.plot)
if(!require(readxl)) {install.packages("readxl")}
require(readxl)
if(!require(readr)) {install.packages("readr")}
require(readr)
if(!require(caret)) {install.packages("caret")}
require(caret)
if(!require(tidyverse)) {install.packages("tidyverse")}
require(tidyverse)
if(!require(ggplot2)) {install.packages("ggplot2")}
require(ggplot2)
if(!require(ggthemes)) {install.packages("ggthemes")}
require(ggthemes)
if(!require(mice)) {install.packages("mice")}
require(mice)Importando Base de Dados
titanic <- read_excel("titanic.xls", col_types = c("numeric",
"numeric", "text", "text", "numeric",
"numeric", "numeric", "text", "numeric",
"text", "text", "text", "numeric", "text",
"numeric"))Agora que temos nossas varáveis, sabemos que temos 1309 observações e 12 variáveis Abaixo segue uma breve descrição de cada uma:
| Nome | Descrição |
|---|---|
| Survived | Sobreviveu (1) ou morreu (0) |
| Pclass | Classe do passageiro |
| Name | Nome do passageiro |
| Sex | Sexo do passageiro |
| Age | Idade do passageiro |
| SibSp | Número de irmãos/esposo(a) a bordo |
| Parch | Número de pais/filhos(as) a bordo |
| Ticket | Número do ticket |
| Fare | Preço do ticket |
| Cabin | Cabine |
| Home.dest | Destino do passageiro |
| Embarked | Porto de embarque |
Vamos analisar as estatísticas descritivas e características das variáveis conforme elas estavam originalmente no banco de dados (sem nenhum tratamento):
summary(titanic)## pclass survived name sex
## Min. :1.000 Min. :0.000 Length:1309 Length:1309
## 1st Qu.:2.000 1st Qu.:0.000 Class :character Class :character
## Median :3.000 Median :0.000 Mode :character Mode :character
## Mean :2.295 Mean :0.382
## 3rd Qu.:3.000 3rd Qu.:1.000
## Max. :3.000 Max. :1.000
##
## age sibsp parch ticket
## Min. : 0.17 Min. :0.0000 Min. :0.000 Length:1309
## 1st Qu.:21.00 1st Qu.:0.0000 1st Qu.:0.000 Class :character
## Median :28.00 Median :0.0000 Median :0.000 Mode :character
## Mean :29.56 Mean :0.4992 Mean :0.385
## 3rd Qu.:38.00 3rd Qu.:1.0000 3rd Qu.:0.000
## Max. :80.00 Max. :8.0000 Max. :9.000
## NA's :9 NA's :1
## fare cabin embarked
## Min. : 0 Length:1309 Length:1309
## 1st Qu.: 14 Class :character Class :character
## Median : 74 Mode :character Mode :character
## Mean : 130656
## 3rd Qu.: 78958
## Max. :5123292
## NA's :1
## boat body home.dest PassengerId
## Length:1309 Min. : 1.0 Length:1309 Min. : 1.0
## Class :character 1st Qu.: 72.0 Class :character 1st Qu.: 327.0
## Mode :character Median :155.0 Mode :character Median : 654.0
## Mean :160.8 Mean : 654.4
## 3rd Qu.:256.0 3rd Qu.: 982.0
## Max. :328.0 Max. :1309.0
## NA's :1188
str(titanic)## Classes 'tbl_df', 'tbl' and 'data.frame': 1309 obs. of 15 variables:
## $ pclass : num 3 1 3 1 3 3 1 3 3 2 ...
## $ survived : num 0 1 1 1 0 0 0 0 1 1 ...
## $ name : chr "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
## $ sex : chr "male" "female" "female" "female" ...
## $ age : num 22 38 16 35 35 22 54 2 27 14 ...
## $ sibsp : num 1 1 0 1 0 0 0 3 0 1 ...
## $ parch : num 0 0 0 0 0 0 0 1 2 0 ...
## $ ticket : chr "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...
## $ fare : num 7.25 7.13e+05 7.92e+03 5.31e+01 8.05 ...
## $ cabin : chr NA "C85" NA "C123" ...
## $ embarked : chr "S" "C" "S" "S" ...
## $ boat : chr NA "4" NA "D" ...
## $ body : num NA NA NA NA NA NA 175 4 NA NA ...
## $ home.dest : chr "UK" "USA" "FINLAND" "USA" ...
## $ PassengerId: num 1 2 3 4 5 6 7 8 9 10 ...
Verifica-se que várias variáveis categóricas não estão classificadas como factor. Além disso, algumas delas apresentam valores em branco (NA). Dessa forma, será realizado abaixo o tratamento necessário dessas variáveis.
Transformamos as variáveis categóticas em factor, substituimos os NA’s na coluna Fare pela mediana das células com valor, tratamos a variável name para extrair dados que sejam úteis na regressão ou na geração da nova variável (o título do passageiro: Title) e excluímos algumas variveis que não contribuiriam para a previsão, como o número do ticket.
combi <- titanic
combi$name <- as.character(combi$name)
strsplit(combi$name[1], split='[,.]')## [[1]]
## [1] "Braund" " Mr" " Owen Harris"
strsplit(combi$name[1], split='[,.]')[[1]]## [1] "Braund" " Mr" " Owen Harris"
strsplit(combi$name[1], split='[,.]')[[1]][2]## [1] " Mr"
combi$Title <- sapply(combi$name, FUN=function(x) {strsplit(x, split='[,.]')[[1]][2]})
combi$Title <- sub(' ', '', combi$Title)
combi$Title[combi$PassengerId == 797] <- 'Mrs' # ajustdo para Mrs.porque era mulher
combi$Title[combi$Title %in% c('Lady', 'the Countess', 'Mlle', 'Mee', 'Ms', 'Mme')] <- 'Miss'
combi$Title[combi$Title %in% c('Capt', 'Don', 'Major', 'Sir', 'Col', 'Jonkheer', 'Rev', 'Dr')] <- 'Mr'
combi$Title[combi$Title %in% c('Dona')] <- 'Mrs'
combi$Title <- as.factor(combi$Title)
unique(combi$Title)## [1] Mr Mrs Miss Master
## Levels: Master Miss Mr Mrs
combi$embarked <- factor(combi$embarked)
combi$pclass <- as.factor(combi$pclass)
combi$survived <- as.factor(combi$survived)
combi$sex <- as.factor(combi$sex)
combi$fare[is.na(combi$fare)] <- median(combi$fare, na.rm=TRUE)
excluir <- c("ticket", "cabin", "boat", "body", "home.dest")
combi <- combi[,!(names(combi)%in% excluir)]Ser rico compensa na hora da sobrevivência? Vamos plotar dois gráficos para podermos entendermos melhor a relação das variáveis Pclass e Title com a sobrevivência.
# Relação entre title e survived
ggplot(combi, aes(x = Title, fill = factor(survived))) +
geom_bar(stat='count', position='dodge') +
labs(x = 'Title') O gráfico acima apresenta a quantidade de pessoas que sobreviveram e que morreram em cada um dos grupos da variável Title. Verificamos que mais mulheres sobreviveram que morreram, tanto entre as solteiras quanto entre as casadas. Entre os homens, a grande maioria morreu. Esse gráfico já antecipa que o gênero será uma variável importante na previsão
# Relação entre pclass e survived
ggplot(combi, aes(x = pclass, fill = factor(survived))) +
geom_bar(stat='count', position='dodge') +
labs(x = 'Classe')No gráfico acima, analisamos a quantidade de pessoas que osbreviveram em cada uma das classes de passageiros. Conclui-se que dentre os passageiros da primeira classe, houve mais sobreviventes que mortos. Na segunda classe, houve mais mortos que sobrevientes. Na terceira classe, aproximadamente 3/4 dos passageiros morreram. Dessa forma, é possível antecipar que a classe do passageiro será uma variável improtante na previsão.
Famílias afundam ou nadam juntas?
Depois de dividir os títulos de cada passageiros, vamos avançar e fazer variáveis familiares. Primeiro, vamos criar a variável family_size baseada no número de irmãos/conjuges e no número de filhos/parentes a bordo.
combi$Surname <- sapply(combi$name,
function(x) strsplit(x, split = '[,.]')[[1]][1])
combi$family_size <- combi$sibsp + combi$parch + 1
# Substituindo os NA's na colune family Size pela mediana das células com valor.
combi$family_size[is.na(combi$family_size)] <- median(combi$family_size, na.rm=TRUE)Vamos plotar esta nova variável family_size para entender melhor como ela pode estar relacionada à sobrevivência.
ggplot(combi[1:891,], aes(x = family_size, fill = factor(survived))) +
geom_bar(stat='count', position='dodge') +
scale_x_continuous(breaks=c(1:11)) +
labs(x = 'Family Size') +
theme_few()Inferimos do gráfico no grupo de solteiros houve mais mortos que sobreviventes. O mesmo aconteceu com famílias com 5 ou mais pessoas. Enquanto isso, nas famílias com 2 a 4 pessoas, houve mais sobreviventes que mortos. Com isso, decidimos criar três novas variáveis categóricas: Solteiros, pequeno (de 1 à 4 familiares) e grande (5 ou mais familiares a bordo) para melhor visualização. O nome da variável será: family_size_discreto
# Tamanho da família discreto
combi$family_size_discreto[combi$family_size == 1] <- 'solteiro'
combi$family_size_discreto[combi$family_size < 5 & combi$family_size > 1] <- 'pequeno'
combi$family_size_discreto[combi$family_size > 4] <- 'grande'
combi$family_size_discreto <- factor(combi$family_size_discreto)
# Mosaico com tamanho familiar por sobrevivente
mosaicplot(table(combi$family_size, combi$survived), main='Tamanho da Família por nº de sobreviventes', shade=TRUE)O mosaico acima ajuda a reforçar a ideia de que famílias pequenas possuem mais chance e sobreviver (porém não os solteiros).
Fazemos a previsão das idades vazias de cada passageiro pelo método de árvore de decisão, utilizando as outras variáveis da amostra. Foi utilizado o method=“anova” que é um método de regression tree, pois estamos prevendo uma variável contínua.
predicted_age <- rpart(age ~ pclass + sex + sibsp + parch + fare + embarked + Title + family_size,
data=combi[!is.na(combi$age),], method="anova")
combi$age[is.na(combi$age)] <- predict(predicted_age, combi[is.na(combi$age),])Vamos analisar o gráfico que apresenta a distribuição das idades dos grupos de sobreviventes e mortos:
#relação entre age e survived
ggplot(combi, aes(x = age)) +
geom_histogram(aes(fill = survived), position = "dodge", stat = "density") +
ylab("Density") +
xlab("Age") +
ggtitle("Distribuição de idade")É possível ver nesse gráfico, que entre as crianças, houve mais sobrevivente que mortos.
O gráfico seguinte mostra a quantidade de sobreviventes e mortos por idade, porém separados por sexo:
# Relação idade x sobrevivência
ggplot(combi, aes(age, fill = factor(survived))) +
geom_histogram() +
facet_grid(.~sex) +
theme_few()Além de reforçar que as crianças possuem boas chances de sobreviver, também reforça que os homens tem mais chances de morrer e que o grupo mais numeroso a bordo era o de homens entre 20 e 50 anos, tendo sobrevivido a menor parte deste grupo.
Agora que temos as idades completas, criaremos mais duas colunas de variáveis categóricas: child e mother. Se o passageiro tiver menos de 18 anos, será considerado crianca, caso contrário adulto. Se o passageiro tiver mais de 18 anos, for do sexo feminino, tiver mais de um membro familiar a bordo e tiver seu Title diferente de Miss (senhorita), será considerado uma mãe.
# Adicionando a variável **Child**
combi$child[combi$age < 18] <- 'crianca'
combi$child[combi$age >= 18] <- 'adulto'
# Tabela com quantidades:
table(combi$child, combi$survived)##
## 0 1
## adulto 716 415
## crianca 93 85
Parece que ser criança não é tão ruim assim, mas não é garantia de sobreviVência também. Como sabemos (pelo filme), mulheres e crianças foram colocados primeiros nos botes salva vidas. Talvez as mães tenham se salvado também, veremos a seguir:
# Adicionando a variável **Mother**
combi$Mother <- 'nao_mae'
combi$Mother[combi$sex == 'female' & combi$parch > 0 & combi$age > 18 & combi$Title != 'Miss'] <- 'mae'
combi$child <- factor(combi$child)
combi$Mother <- factor(combi$Mother)
# Tabela com quantidades:
table(combi$Mother, combi$survived)##
## 0 1
## mae 21 64
## nao_mae 788 436
De fato, ser mãe também ajudou a aumentar as chances de sobreviver.
Depois de todos os ajustes, vamos analisar novamente as estatísticas descritivas e características das variáveis:
summary(combi)## pclass survived name sex age
## 1:323 0:809 Length:1309 female:466 Min. : 0.17
## 2:277 1:500 Class :character male :843 1st Qu.:21.00
## 3:709 Mode :character Median :28.00
## Mean :29.61
## 3rd Qu.:38.00
## Max. :80.00
##
## sibsp parch fare embarked
## Min. :0.0000 Min. :0.000 Min. : 0 C:270
## 1st Qu.:0.0000 1st Qu.:0.000 1st Qu.: 14 Q:123
## Median :0.0000 Median :0.000 Median : 74 S:916
## Mean :0.4992 Mean :0.385 Mean : 130556
## 3rd Qu.:1.0000 3rd Qu.:0.000 3rd Qu.: 78958
## Max. :8.0000 Max. :9.000 Max. :5123292
## NA's :1
## PassengerId Title Surname family_size
## Min. : 1.0 Master: 61 Length:1309 Min. : 1.000
## 1st Qu.: 327.0 Miss :267 Class :character 1st Qu.: 1.000
## Median : 654.0 Mr :782 Mode :character Median : 1.000
## Mean : 654.4 Mrs :199 Mean : 1.884
## 3rd Qu.: 982.0 3rd Qu.: 2.000
## Max. :1309.0 Max. :11.000
##
## family_size_discreto child Mother
## grande : 82 adulto :1131 mae : 85
## pequeno :437 crianca: 178 nao_mae:1224
## solteiro:790
##
##
##
##
str(combi)## Classes 'tbl_df', 'tbl' and 'data.frame': 1309 obs. of 16 variables:
## $ pclass : Factor w/ 3 levels "1","2","3": 3 1 3 1 3 3 1 3 3 2 ...
## $ survived : Factor w/ 2 levels "0","1": 1 2 2 2 1 1 1 1 2 2 ...
## $ name : chr "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
## $ sex : Factor w/ 2 levels "female","male": 2 1 1 1 2 2 2 2 1 1 ...
## $ age : num 22 38 16 35 35 22 54 2 27 14 ...
## $ sibsp : num 1 1 0 1 0 0 0 3 0 1 ...
## $ parch : num 0 0 0 0 0 0 0 1 2 0 ...
## $ fare : num 7.25 7.13e+05 7.92e+03 5.31e+01 8.05 ...
## $ embarked : Factor w/ 3 levels "C","Q","S": 3 1 3 3 3 2 3 3 3 1 ...
## $ PassengerId : num 1 2 3 4 5 6 7 8 9 10 ...
## $ Title : Factor w/ 4 levels "Master","Miss",..: 3 4 2 4 3 3 3 1 4 4 ...
## $ Surname : chr "Braund" "Cumings" "Heikkinen" "Futrelle" ...
## $ family_size : num 2 2 1 2 1 1 1 5 3 2 ...
## $ family_size_discreto: Factor w/ 3 levels "grande","pequeno",..: 2 2 3 2 3 3 3 1 2 2 ...
## $ child : Factor w/ 2 levels "adulto","crianca": 1 1 2 1 1 1 1 2 1 2 ...
## $ Mother : Factor w/ 2 levels "mae","nao_mae": 2 2 2 2 2 2 2 2 1 2 ...
Alguns destaques da estatística descritiva desses dados ajustados: - A maioria das pessoas era da terceira classe; - A maioria morreu; - Os homens eram quase o dobro das mulheres; - A mediana da idade era 28 anos; - A maioria viajava sozinho; - Havia poucas crianças e poucas mães.
No K-Fold Cross Validation, você divide normalmente entre 5–10 grupos o seu conjunto de dados. 1 grupo é o grupo de teste e k-1 grupos juntos são o grupo de treino. O modelo “roda” k vezes, alternando grupo de teste, de formaque seja possível testar em todo o conjunto de dados. Em cada rodada, é gerada uma medida de erro. Neste trabalho, optamos usar Matriz de Confusão. A partir dela, extraímos uma medida de acurácia, que é o percentual de acerto da prevsião. A medida final do modelo é a média desta acurácia em cada uma das k rodadas. Utilizaremos essa técnica em todos os modelos.
k_folds <- 5
folds <- createFolds(combi$survived, k = k_folds, list = FALSE)
useful_cols = setdiff(colnames(combi), c("name", "PassengerId", "Surname", "family_size"))
accuracy <- numeric(k_folds)Primeiramente criamos uma àrvore de Decisão com o CP padrão (0.01)
accuracy_tree <- numeric(k_folds)
for (i in 1:k_folds) {
data_train_tree = combi[folds != i, useful_cols]
data_test_tree = combi[folds == i, useful_cols]
Tree <- rpart(survived ~
pclass+ sex+ age+
fare+
embarked+
Title+
family_size_discreto+
child+
Mother, data = data_train_tree)
cast_tree <- predict(Tree, newdata = data_test_tree)
prediction_tree <- table(data_test_tree$survived, cast_tree[ ,"1"] > 0.5)
TP_tree <- prediction_tree["1", "TRUE"]
FP_tree <- prediction_tree["0", "TRUE"]
TN_tree <- prediction_tree["0", "FALSE"]
FN_tree <- prediction_tree["1", "FALSE"]
accuracy_tree[i] = (TP_tree + TN_tree)/(TP_tree + TN_tree + FP_tree + FN_tree)}
paste("Acurácia média", toString(k_folds), "folds", toString(round(mean(accuracy_tree), 4)))## [1] "Acurácia média 5 folds 0.8113"
Visualizando a árvore de decisão
fancyRpartPlot(Tree)Vamos agora buscar o melhor CP (como menor erro de validação):
#Escolha valores razoáveis
possible_values <- seq(from = 0.0001, to = 0.1, length.out = 60)
cp_error <- numeric(length(possible_values))
#Escolha a quantidade de dados que serão alocado para teste
p <- 0.2
test_idx <- sample(1:nrow(combi), size = floor(p*nrow(combi)))
data_test_cp <- combi[test_idx, useful_cols]
data_train_val_cp <- combi[-test_idx, useful_cols]
iteration <- 1
for (val in possible_values) {
validation_errors <- numeric(k_folds)
# Para cada valor do parametro cp teremos a seguinte rotina
for (run in 1:k_folds) {
# A cada rodada de validação, separamos em dados de treino e de validação
df_train <- data_train_val_cp[folds != run, useful_cols]
df_val <- data_train_val_cp[folds == run, useful_cols]
# Treinamos o modelo
tree_cp <- rpart(survived ~
pclass+ sex+ age+
fare+
embarked+
Title+
family_size_discreto+
child+
Mother, data = df_train, cp = val)
# Fazemos a previsão no conjunto de validação
pred_cp <- predict(tree_cp, newdata = df_val, type = "class")
# Computamos uma métrica de avaliação do erro. Exemplo: porcentagem de acerto
right <- pred_cp == df_val$survived
validation_errors[run] = length(right[right == FALSE])/nrow(df_val)}
# Depois de computar a métrica de erro em todos os folds, tomamos uma média e guardamos
cp_error[iteration] = mean(validation_errors)
iteration <- iteration + 1}
# Plotar o erro de validação
qplot(possible_values, cp_error, geom = "line")O gráfico acima nos ajuda a ver a relação entre os CPs e os respectivos erros de validação.
Agora estimamos o modelo na união dos dados de treino e validação com o melhor CP:
best <- possible_values[which.min(cp_error)]
best## [1] 0.02211186
best_tree <- rpart(survived ~
pclass+ sex+ age+
fare+
embarked+
Title+
family_size_discreto+
child+
Mother, data = data_train_val_cp, cp = best)
fancyRpartPlot(best_tree)Estimamos o erro do modelo fora da amostra computando o erro no conjunto de teste
pred_best_tree <- predict(best_tree, newdata = data_test_cp, type = "class")
right_best_tree <- pred_best_tree == data_test_cp$survived
final_error <- length(right_best_tree[right_best_tree == FALSE])/nrow(data_test_cp)
paste("Erro final (%)", round(100 * final_error, 4))## [1] "Erro final (%) 18.0077"
Finalmente, vamos estimar uma nova Árvore de Decisão com o melhor CP, repetindo o procedimento do k-fold cross validation:
accuracy_tree2 <- numeric(k_folds)
for (i in 1:k_folds) {
data_train_tree2 = combi[folds != i, useful_cols]
data_test_tree2 = combi[folds == i, useful_cols]
Tree2 <- rpart(survived ~
pclass+ sex+ age+
fare+
embarked+
Title+
family_size_discreto+
child+
Mother, data = data_train_tree2, cp=best)
cast_tree2 <- predict(Tree2, newdata = data_test_tree2)
prediction_tree2 <- table(data_test_tree2$survived, cast_tree2[ ,"1"] > 0.5)
TP_tree2 <- prediction_tree2["1", "TRUE"]
FP_tree2 <- prediction_tree2["0", "TRUE"]
TN_tree2 <- prediction_tree2["0", "FALSE"]
FN_tree2 <- prediction_tree2["1", "FALSE"]
accuracy_tree2[i] = (TP_tree2 + TN_tree2)/(TP_tree2 + TN_tree2 + FP_tree2 + FN_tree2)}
paste("A Acurácia média em", toString(k_folds), "folds é", toString(round(mean(accuracy_tree2), 4)))## [1] "A Acurácia média em 5 folds é 0.8143"
fancyRpartPlot(Tree2) Essa representação gráfica da árvore de decisão é de fácil interpretação. A primeira caixinha representa 100% dos dados. Dentro dela, na primeira linha, você lê o zero (sinônimo de “morreu”) porque, no grupo com todos os passageiros, a maior probabilidade é de morrer. Isso vem explicitado na segunda linha da caixinha, que traz as probabilidades: 62% de chances de morrer e 38% de chances de sobreviver. Isso também se reflete na cor da caixinha (verde para quem tem mais chances de morrer e azul para quem tem mais chances de sobreviver). A terceira linha da caixinha traz o percentual que aquela caixinha representa do total de passageiros (nesse caso, 100%). Abaixo dela, vem a condição para abrir o nó em dois caminhos. Nesse caso, a pergunta é se o título do passageiro é igual a “Mr.”. Caso positivo, segue alinha da esquerda e, caso negativo, segue a linha da direita. A árvore deve ser lida seguindo essa lógica até o final. O resultado dessa árvore condiz com as percepções geradas a partir da leitura dos gráficos e das estatísticas descritivas
Utilizando o modelo LOGIT para prever os sobreviventes:
for (i in 1:k_folds) {
data_train = combi[folds != i, useful_cols]
data_test = combi[folds == i, useful_cols]
Logit <- glm(survived ~ I(pclass==1)+I(pclass==2)+
I(sex=="female")+
age+
fare+
I(embarked=="C")+I(embarked=="Q")+
I(Title=="Master")+I(Title=="Miss")+I(Title=="Mr")+
I(family_size_discreto == "solteiro")+I(family_size_discreto == "grande")+
I(child=="crianca")+
I(Mother== "mae"),
data = data_train, family=binomial())
cast <- predict(Logit, newdata = data_test, type = "response")
prediction <- table(data_test$survived, cast > 0.5)
TP <- prediction["1", "TRUE"]
FP <- prediction["0", "TRUE"]
TN <- prediction["0", "FALSE"]
FN <- prediction["1", "FALSE"]
accuracy[i] = (TP + TN)/(TP + TN + FP + FN)}
paste("A Acurácia média em", toString(k_folds), "folds é", toString(round(mean(accuracy), 4)))## [1] "A Acurácia média em 5 folds é 0.8182"
Abaixo, segue o resumo do modelo Logit:
summary(Logit)##
## Call:
## glm(formula = survived ~ I(pclass == 1) + I(pclass == 2) + I(sex ==
## "female") + age + fare + I(embarked == "C") + I(embarked ==
## "Q") + I(Title == "Master") + I(Title == "Miss") + I(Title ==
## "Mr") + I(family_size_discreto == "solteiro") + I(family_size_discreto ==
## "grande") + I(child == "crianca") + I(Mother == "mae"), family = binomial(),
## data = data_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.3056 -0.5940 -0.4043 0.5777 3.0727
##
## Coefficients: (1 not defined because of singularities)
## Estimate Std. Error z value
## (Intercept) -1.758e+00 3.428e-01 -5.129
## I(pclass == 1)TRUE 2.015e+00 2.655e-01 7.590
## I(pclass == 2)TRUE 9.624e-01 2.286e-01 4.210
## I(sex == "female")TRUE 3.282e+00 3.370e-01 9.739
## age -2.977e-02 8.910e-03 -3.341
## fare 2.398e-07 2.309e-07 1.038
## I(embarked == "C")TRUE 5.118e-01 2.279e-01 2.245
## I(embarked == "Q")TRUE 1.513e-01 3.046e-01 0.497
## I(Title == "Master")TRUE 2.488e+00 4.815e-01 5.168
## I(Title == "Miss")TRUE -5.983e-01 3.734e-01 -1.603
## I(Title == "Mr")TRUE NA NA NA
## I(family_size_discreto == "solteiro")TRUE 1.283e-01 2.109e-01 0.608
## I(family_size_discreto == "grande")TRUE -2.096e+00 4.105e-01 -5.106
## I(child == "crianca")TRUE -3.026e-01 3.540e-01 -0.855
## I(Mother == "mae")TRUE 8.254e-01 5.129e-01 1.609
## Pr(>|z|)
## (Intercept) 2.92e-07 ***
## I(pclass == 1)TRUE 3.20e-14 ***
## I(pclass == 2)TRUE 2.55e-05 ***
## I(sex == "female")TRUE < 2e-16 ***
## age 0.000834 ***
## fare 0.299130
## I(embarked == "C")TRUE 0.024747 *
## I(embarked == "Q")TRUE 0.619454
## I(Title == "Master")TRUE 2.37e-07 ***
## I(Title == "Miss")TRUE 0.109017
## I(Title == "Mr")TRUE NA
## I(family_size_discreto == "solteiro")TRUE 0.543027
## I(family_size_discreto == "grande")TRUE 3.30e-07 ***
## I(child == "crianca")TRUE 0.392593
## I(Mother == "mae")TRUE 0.107592
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1392.63 on 1046 degrees of freedom
## Residual deviance: 887.08 on 1033 degrees of freedom
## AIC: 915.08
##
## Number of Fisher Scoring iterations: 5
AGora, vamos utilizar o modelo PROBIT para prever os sobreviventes:
accuracy2 <- numeric(k_folds)
for (i in 1:k_folds) {
data_train2 = combi[folds != i, useful_cols]
data_test2 = combi[folds == i, useful_cols]
Probit <- glm(survived ~ I(pclass==1)+I(pclass==2)+
I(sex=="female")+
age+
fare+
I(embarked=="C")+I(embarked=="Q")+
I(Title=="Master") + I(Title=="Miss") + I(Title=="Mr") +
I(family_size_discreto == "solteiro")+I(family_size_discreto == "grande")+
I(child=="crianca")+
I(Mother== "mae"),
data = data_train2, family=binomial(link = "probit"))
cast2 <- predict(Probit, newdata = data_test2, type = "response")
prediction2 <- table(data_test2$survived, cast2 > 0.5)
TP2 <- prediction2["1", "TRUE"]
FP2 <- prediction2["0", "TRUE"]
TN2 <- prediction2["0", "FALSE"]
FN2 <- prediction2["1", "FALSE"]
accuracy2[i] = (TP2 + TN2)/(TP2 + TN2 + FP2 + FN2)}
paste("A Acurácia média em", toString(k_folds), "folds é", toString(round(mean(accuracy2), 4)))## [1] "A Acurácia média em 5 folds é 0.8197"
Abaixo, segue o resumo do modelo Probit:
summary(Probit)##
## Call:
## glm(formula = survived ~ I(pclass == 1) + I(pclass == 2) + I(sex ==
## "female") + age + fare + I(embarked == "C") + I(embarked ==
## "Q") + I(Title == "Master") + I(Title == "Miss") + I(Title ==
## "Mr") + I(family_size_discreto == "solteiro") + I(family_size_discreto ==
## "grande") + I(child == "crianca") + I(Mother == "mae"), family = binomial(link = "probit"),
## data = data_train2)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.3264 -0.6162 -0.4117 0.5882 3.3519
##
## Coefficients: (1 not defined because of singularities)
## Estimate Std. Error z value
## (Intercept) -9.756e-01 1.904e-01 -5.125
## I(pclass == 1)TRUE 1.107e+00 1.471e-01 7.528
## I(pclass == 2)TRUE 4.968e-01 1.265e-01 3.928
## I(sex == "female")TRUE 1.923e+00 1.869e-01 10.286
## age -1.705e-02 4.970e-03 -3.431
## fare 1.561e-07 1.339e-07 1.166
## I(embarked == "C")TRUE 2.847e-01 1.292e-01 2.204
## I(embarked == "Q")TRUE 4.010e-02 1.731e-01 0.232
## I(Title == "Master")TRUE 1.447e+00 2.767e-01 5.230
## I(Title == "Miss")TRUE -3.483e-01 2.113e-01 -1.648
## I(Title == "Mr")TRUE NA NA NA
## I(family_size_discreto == "solteiro")TRUE 7.346e-02 1.196e-01 0.614
## I(family_size_discreto == "grande")TRUE -1.218e+00 2.305e-01 -5.282
## I(child == "crianca")TRUE -2.093e-01 2.004e-01 -1.044
## I(Mother == "mae")TRUE 4.461e-01 2.804e-01 1.591
## Pr(>|z|)
## (Intercept) 2.98e-07 ***
## I(pclass == 1)TRUE 5.14e-14 ***
## I(pclass == 2)TRUE 8.55e-05 ***
## I(sex == "female")TRUE < 2e-16 ***
## age 0.000602 ***
## fare 0.243759
## I(embarked == "C")TRUE 0.027531 *
## I(embarked == "Q")TRUE 0.816791
## I(Title == "Master")TRUE 1.69e-07 ***
## I(Title == "Miss")TRUE 0.099250 .
## I(Title == "Mr")TRUE NA
## I(family_size_discreto == "solteiro")TRUE 0.539207
## I(family_size_discreto == "grande")TRUE 1.28e-07 ***
## I(child == "crianca")TRUE 0.296367
## I(Mother == "mae")TRUE 0.111594
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1392.63 on 1046 degrees of freedom
## Residual deviance: 891.23 on 1033 degrees of freedom
## AIC: 919.23
##
## Number of Fisher Scoring iterations: 5
Agora faremos a comparação final dos três modelos:
###COMPARANDO OS TRÊS MODELOS
RESULT_LOGIT <- paste("Acurácia média", toString(k_folds), "folds", toString(round(mean(accuracy), 4)))
RESULT_PROBIT <- paste("Acurácia média", toString(k_folds), "folds", toString(round(mean(accuracy2), 4)))
RESULT_ARVORE <-paste("Acurácia média", toString(k_folds), "folds", toString(round(mean(accuracy_tree2), 4)))RESULT_LOGIT ## [1] "Acurácia média 5 folds 0.8182"
RESULT_PROBIT ## [1] "Acurácia média 5 folds 0.8197"
RESULT_ARVORE## [1] "Acurácia média 5 folds 0.8143"
A conclusão é que a acurácia dos modelos é muito parecida, não havendo diferença significtiva que justifique a escolha de um deles.