Regressão logística

library(caret)
library(tidyr)
library(dplyr)
library(doParallel)
cls = makeCluster(3)
registerDoParallel(cls)
train <- read.csv("train.csv", encoding="UTF-8")
dataPartition <- createDataPartition(y = train$situacao_final, p=0.80, list=FALSE)
# Se o y for um vector de factor a divisão é feita tentando balancear a distribuição de classes de # y dentro das partições.

treino <- train[ dataPartition, ]
validacao <- train[ -dataPartition, ]

# variáveis envolvidas no  (no momento estou usando todas)
# "situacao_final"" (eleito ou não eleito)
formula = as.formula(situacao_final ~ .)

Retirando variáveis que de cara tem fatores diferentes e não afetam a predição

treino <- treino %>%
  select(-nome, -ID, -numero_cadidato)

validacao <- validacao %>%
  select(-nome, -ID, -numero_cadidato)

1- Há desbalanceamento das classes (isto é, uma classe tem muito mais instâncias que outra)? Em que proporção? Quais efeitos colaterais o desbalanceamento de classes pode causar no classificador?

Sim, podemos ver no gráfico que o número de classes com candidatos não eleitos é bem maior.

total = nrow(train)
dist_classes <- train %>% count(situacao_final)
ggplot(dist_classes, aes(y = dist_classes$n/total * 100, x = dist_classes$situacao_final))+
  geom_bar(stat="identity") +
  labs(title = "Distribuição de classes", x = "Situação final", y = "Proporção (%)") +
  theme(axis.text.x = element_text(angle = 0, hjust = 1), legend.position="none") +
  theme(axis.text=element_text(size=8), axis.title=element_text(size=12,face="bold"))

2 - Treine: um modelo de regressão logística, uma árvore de decisão e um modelo de adaboost. Tune esses modelos usando validação cruzada e controle overfitting se necessário, considerando as particularidades de cada modelo.

formula = as.formula(situacao_final ~ .)

Treinando modelo com regressão linear sem nenhuma tunagem, default é bootstraping com 25 repetições

logReg1 <- train(formula,
                 data = treino,
                 method="glm",
                 preProcess = c('scale', 'center', 'nzv'),
                 family="binomial",      # se a variável for binária
                 na.action = na.omit)

ggplot(varImp(logReg1))

Removendo variáveis não relevantes

formula_glm_melhorada = as.formula(situacao_final ~ +descricao_ocupacao +quantidade_doacoes +despesa_max_campanha +media_despesa
                     +setor_economico_receita +quantidade_despesas)

Tunando modelo com validação cruzada e 5 repetições

fitControl_glm <- trainControl(method = "cv", repeats = 5)

glm_tunada <- train(formula_glm_melhorada,
                 data = treino,
                 trControl = fitControl_glm,
                 method="glm",
                 preProcess = c('scale', 'center', 'nzv'),
                 family="binomial",      # se a variável for binária
                 na.action = na.omit)

Treinando com árvore de decisão padrão, bootstraping 25 repetições

arvore1 <- train(formula,
                 data=treino,
                 method = "rpart",
                 preProcess = c('scale', 'center', 'nzv'),
                 cp=0.001,  # parâmetro de complexidade
                 maxdepth=20)

Retirando as variáveis de menor importância e tunando o modelo com validação cruzada de 5 repetições e mudando parâmetro de complexidade

formula_arvore1_melhorada = as.formula(situacao_final ~ +total_despesa +total_receita +quantidade_despesas +recursos_de_pessoas_juridicas
                     +recursos_de_partidos +descricao_ocupacao)


fitControl_arvore1 <- trainControl(method = "cv", number = 5)

arvore1_tuning <- train(formula_arvore1_melhorada,
                 data=treino,
                 trControl = fitControl_arvore1,
                 method = "rpart",
                preProcess = c('scale', 'center', 'nzv'),
                 cp=0.001,  # parâmetro de complexidade
                 maxdepth=20,
                 na.action = na.omit)

Tunando adaboost com as 5 variáveis mais importantes e validação cruzada 5 repetições

fit_control_ada_tuning <- trainControl(method = "cv", number = 5)

formula_adaboost_tuning = as.formula(situacao_final ~ +total_receita +total_despesa +quantidade_despesas +quantidade_fornecedores +quantidade_doacoes
                                     +media_receita +quantidade_doadores +recursos_de_pessoas_juridicas +recursos_de_pessoas_físicas +media_despesa
                                     +recursos_de_partidos +recursos_de_outros_candidatos.comites +recursos_proprios)

modelo_ada_tuning <- train(formula_adaboost_tuning,
                data=treino,
                trControl = fit_control_ada_tuning,
                preProcess = c('scale', 'center', 'nzv'),
                method = "adaboost",
                na.action = na.omit)

3. Reporte acurácia, precision, recall e f-measure no treino e validação. Como você avalia os resultados? Justifique sua resposta.

Os cálculos foram feitos com o modelo de melhor resultado, o adaboosting tunado

validacao$predicao <- predict(modelo_ada_tuning, validacao)

TP <- validacao %>% filter(situacao_final == "eleito", predicao == "eleito") %>% nrow()
TN <- validacao %>% filter(situacao_final == "nao_eleito" , predicao == "nao_eleito" ) %>% nrow()
FP <- validacao %>% filter(situacao_final == "nao_eleito" , predicao == "eleito") %>% nrow() 
FN <- validacao %>% filter(situacao_final == "eleito", predicao == "nao_eleito" ) %>% nrow()

accuracy <- (TP + TN)/(TP + TN + FP + FN) 
precision <- TP / (TP + FP)
recall <- TP / (TP + FN)

accuracy
## [1] 0.9430993
precision
## [1] 0.7647059
recall
## [1] 0.626506

4. Interprete as saídas dos modelos. Quais atributos parecem ser mais importantes de acordo com cada modelo? Crie pelo menos um novo atributo que não está nos dados originais e estude o impacto desse atributo

glm_tunada
## Generalized Linear Model 
## 
## 3309 samples
##    6 predictor
##    2 classes: 'eleito', 'nao_eleito' 
## 
## Pre-processing: scaled (9), centered (9), remove (202) 
## Resampling: Cross-Validated (10 fold) 
## Summary of sample sizes: 2978, 2979, 2977, 2978, 2979, 2977, ... 
## Resampling results:
## 
##   Accuracy  Kappa    
##   0.931707  0.5789396
ggplot(arvore1_tuning)

ggplot(modelo_ada_tuning)

ggplot(varImp(glm_tunada))

ggplot(varImp(arvore1_tuning))

ggplot(varImp(modelo_ada_tuning))

####Os atributos mais importantes são relacionados as despesas e receitas durante o período de eleições.

5 -Criando novo modelo usando RRF com validação cruzada e 5 repetições, variáveis escolhidas pela importância

fit_control_rrf <- trainControl(method = "cv", number = 5)

formula_rrf = as.formula(situacao_final ~ +total_receita +total_despesa +descricao_ocupacao +idade +recursos_de_pessoas_físicas +recursos_de_pessoas_juridicas
                         +despesa_max_campanha +quantidade_fornecedores +media_despesa +quantidade_doadores +recursos_de_partidos 
                         +recursos_de_outros_candidatos.comites +recursos_proprios +media_receita +quantidade_doacoes +quantidade_despesas)

modelo_rrf <- train(formula_rrf,
                na.action = na.omit,
                data=treino,
                trControl = fit_control_rrf,
                preProcess = c('scale', 'center', 'nzv'),
                method = "RRF")

ggplot(varImp(modelo_rrf))

Terminando paralelismo

stopCluster(cls)

Gerando arquivo de submissão

teste <- read.csv("test.csv", encoding="UTF-8")
predicao <- predict(modelo_rrf, newdata = teste)
predictiondf = data.frame(prediction = predicao)
predictiondf <- predictiondf  %>% mutate( ID = teste$ID ) %>% select(ID, prediction)
write.csv(predictiondf, file = "prediction.csv", row.names = F)