Introdução

Essa análise tem como objetivo a construção de modelos preditivos para a votação de candidatos das eleições de 2006 e 2010. Os dados utilizados são os mesmos desse relatório, que contém mais informações sobre eles. Esses valores valores foram separados entre dados de treino e dados de teste, que depois serão utilizados para realizar as predições.

train <- read.csv("data/lab02/train.csv")
test <- read.csv("data/lab02/test.csv")

input <- train %>% 
  select(-cargo, -nome, -ocupacao, -ano, -sequencial_candidato, -uf, -sexo, -estado_civil, -grau, -partido)

Perguntas

Questão 1

  • Usando todas as variáveis disponíveis, tune (usando validação cruzada): (i) um modelo de regressão Ridge, (ii) um modelo de regressão Lasso e (iii) um modelo KNN. Para os modelos de regressão linear, o parâmetro a ser tunado é o lambda (penalização dos coeficientes) e o KNN o número de vizinhos.

Inicialmente é feita uma configuração para a validação cruzada, com k-fold = 10 e realizando 10 repetições. Nesse caso, iremos separar os dados de teste em 10 partições e escolher uma para ser comparada com as outras 9.

#configuracao da validacao cruzada
ctrl <- trainControl(
  method = "repeatedcv",
  number = 10,
  repeats = 10,
  verboseIter = TRUE
  )

Regressão Ridge

O ridge utiliza o lambda como forma de penalizar determinados parâmetros, fazendo com que o modelo seja menos sensível a variáveis com pouca importância. Essa é uma forma de regularizar o modelo, podendo ser útil para que o modelo não seja muito ajustado aos dados de treino - o famoso overfitting. Assim, o bias e a variância são reduzidos.
Para gerar o modelo utilizando esse tipo de regressão, desejamos encontrar um valor para lambda que produza um menor RMSE (nesse caso). A aplicação de validação cruzada será útil para esse propósito.

lambda.range <- expand.grid(lambda = seq(10^-10, 10^-2, length=30))

model.ridge <- caret::train(
  votos ~.,
  data = input, 
  method = "ridge",
  metric = "RMSE",
  trControl = ctrl,
  tuneGrid = lambda.range,
  preProcess = c('scale', 'center')
)

# model.ridge
# plot(model.ridge, xlab = "Lambda", ylab = "RMSE")

ridgeImp <- model.ridge %>% 
  varImp() %>% 
  ggplot()

# predictors(model.ridge)
model.ridge
## Ridge Regression 
## 
## 7476 samples
##   13 predictors
## 
## Pre-processing: scaled (13), centered (13) 
## Resampling: Cross-Validated (10 fold, repeated 10 times) 
## Summary of sample sizes: 6729, 6728, 6729, 6728, 6729, 6728, ... 
## Resampling results across tuning parameters:
## 
##   lambda        RMSE      Rsquared   MAE     
##   0.0000000001  37623.77  0.4031263  16891.03
##   0.0003448277  37603.79  0.4034321  16890.94
##   0.0006896553  37590.24  0.4036527  16891.53
##   0.0010344828  37580.50  0.4038177  16892.14
##   0.0013793104  37573.56  0.4039408  16892.74
##   0.0017241380  37568.74  0.4040314  16893.32
##   0.0020689656  37565.54  0.4040966  16893.91
##   0.0024137932  37563.61  0.4041417  16894.54
##   0.0027586208  37562.69  0.4041704  16895.13
##   0.0031034483  37562.57  0.4041860  16895.63
##   0.0034482759  37563.09  0.4041908  16896.10
##   0.0037931035  37564.14  0.4041868  16896.55
##   0.0041379311  37565.62  0.4041754  16896.97
##   0.0044827587  37567.45  0.4041579  16897.37
##   0.0048275863  37569.58  0.4041354  16897.73
##   0.0051724138  37571.94  0.4041087  16898.03
##   0.0055172414  37574.51  0.4040785  16898.31
##   0.0058620690  37577.24  0.4040453  16898.54
##   0.0062068966  37580.10  0.4040097  16898.75
##   0.0065517242  37583.08  0.4039722  16898.92
##   0.0068965518  37586.15  0.4039329  16899.05
##   0.0072413793  37589.29  0.4038923  16899.20
##   0.0075862069  37592.50  0.4038506  16899.33
##   0.0079310345  37595.75  0.4038080  16899.46
##   0.0082758621  37599.04  0.4037647  16899.59
##   0.0086206897  37602.37  0.4037209  16899.70
##   0.0089655173  37605.72  0.4036767  16899.78
##   0.0093103448  37609.08  0.4036321  16899.85
##   0.0096551724  37612.45  0.4035874  16899.90
##   0.0100000000  37615.84  0.4035426  16899.92
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was lambda = 0.003103448.

Regressão Lasso

Para o lasso, será utilizada a mesma configuração de validação cruzada de modo a encontrar um valor ótimo para lambda.

lambda.range <- expand.grid(fraction = seq(10^-2, 10^-8, length=20))

model.lasso <- caret::train(
  votos ~.,
  data = input, 
  method = "lasso",
  metric = "RMSE",
  trControl = ctrl,
  tuneGrid = lambda.range,
  preProcess = c('scale', 'center')
)

# model.lasso
# plot(model.lasso, xlab = "Lambda", ylab = "RMSE")

lassoImp <- model.lasso %>% 
  varImp() %>% 
  ggplot()

# predictors(model.lasso)
model.lasso
## The lasso 
## 
## 7476 samples
##   13 predictors
## 
## Pre-processing: scaled (13), centered (13) 
## Resampling: Cross-Validated (10 fold, repeated 10 times) 
## Summary of sample sizes: 6728, 6728, 6728, 6728, 6729, 6731, ... 
## Resampling results across tuning parameters:
## 
##   fraction      RMSE      Rsquared   MAE     
##   0.0000000100  46905.96  0.4075335  28607.20
##   0.0005263253  37505.35  0.4027102  19019.12
##   0.0010526405  37397.11  0.4094813  17142.55
##   0.0015789558  37326.99  0.4124451  16915.28
##   0.0021052711  37374.63  0.4117410  16895.73
##   0.0026315863  37422.67  0.4108644  16894.45
##   0.0031579016  37448.18  0.4104471  16897.27
##   0.0036842168  37451.92  0.4103566  16898.38
##   0.0042105321  37455.90  0.4102589  16899.46
##   0.0047368474  37460.32  0.4101522  16900.54
##   0.0052631626  37465.17  0.4100372  16901.61
##   0.0057894779  37470.45  0.4099146  16902.69
##   0.0063157932  37476.14  0.4097850  16903.77
##   0.0068421084  37482.25  0.4096491  16904.84
##   0.0073684237  37488.77  0.4095076  16905.92
##   0.0078947389  37495.69  0.4093610  16907.00
##   0.0084210542  37503.00  0.4092100  16908.08
##   0.0089473695  37510.70  0.4090551  16909.15
##   0.0094736847  37518.77  0.4088969  16910.23
##   0.0100000000  37527.21  0.4087358  16911.31
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was fraction = 0.001578956.

kNN

Para o kNN testaremos os valores para k, que indicam a quantidade de vizinhos que serão testados. O objetivo é encontrar o k que gere o menor RMSE.

knn.range <- expand.grid(k = seq(1, 100, length=100))
 
model.knn <- caret::train(
  votos ~.,
  data = input, 
  method = "knn",
  metric = "RMSE",
  trControl = ctrl,
  tuneGrid = knn.range,
  preProcess = c('scale', 'center')
)

# model.knn
# plot(model.knn)

# predictors(model.knn)
model.knn
## k-Nearest Neighbors 
## 
## 7476 samples
##   13 predictors
## 
## Pre-processing: scaled (13), centered (13) 
## Resampling: Cross-Validated (10 fold, repeated 10 times) 
## Summary of sample sizes: 6728, 6728, 6728, 6728, 6728, 6729, ... 
## Resampling results across tuning parameters:
## 
##   k    RMSE      Rsquared   MAE     
##     1  42818.67  0.3588830  16044.52
##     2  37467.58  0.4315565  14151.73
##     3  35488.04  0.4679769  13423.01
##     4  34520.38  0.4876863  13010.34
##     5  34039.40  0.4987772  12781.93
##     6  33621.41  0.5087950  12595.51
##     7  33349.04  0.5152992  12487.03
##     8  33185.43  0.5189177  12422.72
##     9  33056.37  0.5219060  12373.75
##    10  32926.29  0.5252200  12326.97
##    11  32781.48  0.5290664  12257.58
##    12  32696.42  0.5312349  12211.98
##    13  32653.81  0.5323281  12175.57
##    14  32618.30  0.5332185  12158.86
##    15  32560.71  0.5347149  12131.88
##    16  32480.57  0.5370008  12090.02
##    17  32431.07  0.5383734  12077.64
##    18  32403.50  0.5392215  12058.90
##    19  32393.83  0.5394625  12057.57
##    20  32379.03  0.5398809  12044.21
##    21  32344.60  0.5409529  12029.62
##    22  32302.08  0.5422069  12009.76
##    23  32261.76  0.5434414  11985.06
##    24  32227.30  0.5445275  11971.50
##    25  32200.58  0.5453188  11956.53
##    26  32179.77  0.5459896  11944.09
##    27  32158.77  0.5467301  11925.57
##    28  32133.68  0.5475643  11910.15
##    29  32110.57  0.5483029  11894.20
##    30  32103.41  0.5485909  11885.51
##    31  32097.67  0.5488598  11877.75
##    32  32105.74  0.5487313  11873.75
##    33  32118.69  0.5484108  11877.18
##    34  32126.54  0.5482342  11879.08
##    35  32130.41  0.5481678  11876.64
##    36  32127.42  0.5483476  11873.81
##    37  32127.30  0.5484120  11874.67
##    38  32125.64  0.5485306  11876.69
##    39  32122.37  0.5486757  11876.20
##    40  32119.70  0.5488004  11874.51
##    41  32107.55  0.5492407  11870.10
##    42  32105.18  0.5494020  11868.08
##    43  32103.10  0.5495559  11862.22
##    44  32109.62  0.5494528  11861.04
##    45  32107.68  0.5495961  11861.55
##    46  32109.21  0.5496336  11859.79
##    47  32117.50  0.5494344  11860.66
##    48  32125.11  0.5492937  11859.56
##    49  32131.08  0.5491739  11862.04
##    50  32134.81  0.5491290  11860.60
##    51  32143.45  0.5489615  11860.57
##    52  32149.51  0.5488620  11862.16
##    53  32159.53  0.5486453  11864.93
##    54  32170.79  0.5483967  11866.67
##    55  32169.76  0.5485235  11868.16
##    56  32175.79  0.5484386  11869.04
##    57  32175.51  0.5485494  11867.03
##    58  32178.40  0.5485360  11864.60
##    59  32181.63  0.5485034  11861.09
##    60  32171.86  0.5488453  11856.14
##    61  32170.68  0.5489459  11851.74
##    62  32167.71  0.5491108  11848.07
##    63  32168.81  0.5491390  11845.56
##    64  32161.79  0.5494325  11842.85
##    65  32162.14  0.5494856  11842.98
##    66  32164.59  0.5494751  11841.75
##    67  32170.92  0.5493459  11842.77
##    68  32172.52  0.5493869  11842.81
##    69  32166.85  0.5496495  11842.22
##    70  32165.73  0.5497811  11841.46
##    71  32165.68  0.5498690  11842.32
##    72  32166.13  0.5499371  11841.93
##    73  32159.19  0.5502063  11839.89
##    74  32160.35  0.5502469  11839.47
##    75  32159.32  0.5503308  11835.70
##    76  32160.30  0.5503710  11835.60
##    77  32159.55  0.5504853  11833.78
##    78  32160.31  0.5505571  11832.28
##    79  32164.82  0.5505087  11833.36
##    80  32169.69  0.5504315  11832.70
##    81  32172.50  0.5504183  11831.19
##    82  32175.77  0.5503936  11829.84
##    83  32180.56  0.5503091  11830.54
##    84  32182.14  0.5503184  11829.32
##    85  32189.29  0.5501811  11829.61
##    86  32190.92  0.5501830  11827.79
##    87  32193.52  0.5501653  11827.35
##    88  32197.31  0.5501206  11826.50
##    89  32200.07  0.5501056  11827.29
##    90  32207.08  0.5499797  11828.61
##    91  32211.49  0.5499064  11828.83
##    92  32216.37  0.5498279  11828.41
##    93  32224.26  0.5496420  11829.91
##    94  32223.59  0.5497367  11827.16
##    95  32228.51  0.5496465  11827.23
##    96  32233.97  0.5495548  11825.90
##    97  32236.75  0.5495582  11823.55
##    98  32242.12  0.5494603  11823.68
##    99  32248.56  0.5493222  11823.54
##   100  32253.23  0.5492715  11822.66
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was k = 31.

Questão 2

  • Compare os três modelos em termos do erro RMSE de validação cruzada.
plot.ridge <- plot(model.ridge, ylab = "RMSE", xlab = "Lambda")
plot.lasso <- plot(model.lasso, ylab = "RMSE", xlab = "Lambda")
plot.knn <- plot(model.knn, ylab = "RMSE", xlab = "#Vizinhos")

results <- resamples(list(ridge=model.ridge, lasso=model.lasso, knn=model.knn))
gridExtra::grid.arrange(plot.ridge, plot.lasso, plot.knn, ncol = 3)

results %>% summary("RMSE")
## 
## Call:
## summary.resamples(object = ., metric = "RMSE")
## 
## Models: ridge, lasso, knn 
## Number of resamples: 100 
## 
## RMSE 
##        Min. 1st Qu. Median  Mean 3rd Qu.  Max. NA's
## ridge 25560   30360  35230 37560   41670 65910    0
## lasso 25070   30020  33750 37330   40940 67070    0
## knn   20850   25650  30930 32100   34620 58480    0

Sabendo que todos os modelos utilizaram os mesmos parâmetros de validação cruzada, o que gerou o menor RMSE foi o kNN. Ele foi bem mais eficiente do que os dois primeiros. O ridge e o lasso apresentaram desempenhos similares, no geral. Os valores obtidos foram:

  • Ridge: 37562.57
  • Lasso: 37326.99
  • kNN: 32097.67

Questão 3

  • Quais as variáveis mais importantes segundo o modelo de regressão Ridge e Lasso? Variáveis foram descartadas pelo Lasso? Quais?
gridExtra::grid.arrange(ridgeImp, lassoImp)

As variáveis mais importantes para os dois modelos de regressão são total_receita, total_despesa, recursos_de_pessoas_juridicas e recursos_de_pessoas_fisicas. Nota-se também que ambos apresentam comportamento semelhante em relação a utilização de parâmetros para o modelo.

params.lasso <- predictors(model.lasso)
input %>% 
  select(-votos, -total_receita) %>% 
  select(-params.lasso) %>% 
  names()
## [1] "quantidade_doacoes"

A variável que descartada pelo modelo foi quantidade_doacoes. Outras variáveis não foram utilizadas por terem importância muito baixa, tais como recursos_de_outros_candidatos.comites, media_despesa e recursos_proprios.

Questão 4

  • Re-treine o melhor modelo (usando os melhores valores de parâmetros encontrados em todos os dados, sem usar validação cruzada).
input.final <- input %>% 
  select(votos, total_receita, total_despesa, recursos_de_pessoas_juridicas, recursos_de_pessoas_fisicas, 
         quantidade_fornecedores, quantidade_despesas, media_receita, recursos_de_partido_politico)

knn.range <- expand.grid(k = model.knn$bestTune)
 
model.knn.final <- caret::train(
  votos ~.,
  data = input.final, 
  method = "knn",
  metric = "RMSE",
  trControl = trainControl(method="none", verboseIter = TRUE),
  tuneGrid = knn.range,
  preProcess = c('scale', 'center', 'nzv')
)

# model.knn.final

Bônus

  • Modelo gerado utilizando Random Forest
input.new <- input %>%
  select(-partido, -grau)

model.rf2 <- caret::train(
  votos ~.,
  data = input.new,
  method = "rf",
  metric = "RMSE",
  preProcess = c('scale', 'center'),
  tuneGrid = expand.grid(.mtry=c(1:7)),
  trControl = trainControl(method="repeatedcv", number=10, repeats = 1, search = "grid", verboseIter = TRUE)
)

Nesse caso, mtry é um parâmetro que representa o número de variáveis que será randomicamente escolhida como candidata para a construção da árvore de decisão. Foram testados valores num intervalo de 1 a 7 e o melhor resultado encontrou um RMSE de 30710.04.

model.rf2
## Random Forest 
## 
## 7476 samples
##   13 predictors
## 
## Pre-processing: scaled (13), centered (13) 
## Resampling: Cross-Validated (10 fold, repeated 1 times) 
## Summary of sample sizes: 6729, 6729, 6728, 6728, 6728, 6728, ... 
## Resampling results across tuning parameters:
## 
##   mtry  RMSE      Rsquared   MAE     
##   1     30710.04  0.5866187  11916.82
##   2     30968.75  0.5809194  12089.08
##   3     31256.28  0.5740989  12230.57
##   4     31435.66  0.5702582  12306.81
##   5     31740.22  0.5633713  12412.14
##   6     32028.07  0.5569163  12488.93
##   7     32305.09  0.5512927  12542.26
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was mtry = 1.
plot(model.rf2)

predictors(model.rf2)
##  [1] "quantidade_doacoes"                   
##  [2] "quantidade_doadores"                  
##  [3] "total_receita"                        
##  [4] "media_receita"                        
##  [5] "recursos_de_outros_candidatos.comites"
##  [6] "recursos_de_pessoas_fisicas"          
##  [7] "recursos_de_pessoas_juridicas"        
##  [8] "recursos_proprios"                    
##  [9] "recursos_de_partido_politico"         
## [10] "quantidade_despesas"                  
## [11] "quantidade_fornecedores"              
## [12] "total_despesa"                        
## [13] "media_despesa"

Questão 5

  • Use esse último modelo treinado para prever os dados de teste disponíveis no challenge que criamos na plataforma Kaggle.
pred <- predict(model.rf2, test)
ans <- data.frame(ID = test$sequencial_candidato, votos = pred)
ans$ID <- as.character(ans$ID)
write_csv(ans,"data/lab02/kaggle.csv")