Material de apoio para o curso Análise de Dados 1, em Computação@UFCG.
Pacotes e fixando os números aleatórios que serão gerados.
require(caret)
## Loading required package: caret
## Warning: package 'caret' was built under R version 3.1.3
## Loading required package: lattice
## Loading required package: ggplot2
require(dplyr)
## Loading required package: dplyr
##
## Attaching package: 'dplyr'
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
require(kernlab)
## Loading required package: kernlab
set.seed(3456)
Separação de dados em treino e teste. Estamos usando os mesmos dados de spam do problema de regressão logística.
emails <- read.table("./email.txt", sep = "\t", header = T)
emails <- select(emails, spam, to_multiple, from, cc, sent_email, image, dollar, password, num_char, line_breaks, format, exclaim_mess)
emails$spam <- as.factor(emails$spam)
trainIndex <- createDataPartition(emails$spam, p = .75,
list = FALSE,
times = 1)
head(trainIndex)
## Resample1
## [1,] 1
## [2,] 2
## [3,] 3
## [4,] 4
## [5,] 5
## [6,] 6
emailsTrain <- emails[ trainIndex,]
emailsTest <- emails[-trainIndex,]
Para treinar o modelo, é importante entender o algoritmo que o caret usa:
Repare que ele precisa de: 1. os conjuntos de valores para os parâmetros que testará, 2. um método para decidir as amostras em que ele testará cada conjunto de valores dos parâmetros (ressampling) 3. (opcional) do pre-processamento que deve ser feito para cada atributo dos dados antes do fit em cada amostra
Depois de avaliar os valores dos parâmetros em várias amostras, ele escolhe o melhor conjunto e treina um modelo com todos os dados. Esse é o modelo final que usaremos. Para avaliá-lo, podemos usar os dados de teste que separamos mais acima.
Fazendo na prática. Primeiro criamos um objeto com algumas “configurações” para o algoritmo acima:
fitControl <- trainControl(## 10-fold CV
method = "cv",
number = 10)
Aqui estamos usando validação cruzada (cross-validation) que divide os dados em 10 partes e roda o modelo 10 vezes, cada vez usando uma das partes diferentes como validação. Dê uma explorada nas possibilidades do parâmetro ‘method’. repeatedcv é um bom começo.
Sobre o pré-processamento, como vamos usar primeiro knn, e há variáveis numéricas, é preciso pré-processá-las. Isso é feito mais abaixo. Primeiro, como o dataset é muito desbalanceado, precisamos balanceá-lo:
table(emailsTrain$spam)
##
## 0 1
## 2666 276
probs_balanceads <- ifelse(emailsTrain$spam == 0, .1 / 2666, .9 / 276)
is <- sample(1:NROW(emailsTrain), 500, prob = probs_balanceads, replace = F)
emailsTrain_b <- emailsTrain[is, ]
table(emailsTrain_b$spam)
##
## 0 1
## 224 276
Agora vamos estimar o melhor k do knn com essa configuração de treinamento.
# o treinamento pode demorar... aqui por exemplo:
ptm <- proc.time()
knnFit1 <- train(spam ~ ., data = emailsTrain_b,
method = "knn",
trControl = fitControl,
preProcess = c("center","scale"),
tuneGrid = data.frame(.k = 2:15))
proc.time() - ptm
## user system elapsed
## 1.741 0.042 2.292
knnFit1
## k-Nearest Neighbors
##
## 500 samples
## 11 predictor
## 2 classes: '0', '1'
##
## Pre-processing: centered, scaled
## Resampling: Cross-Validated (10 fold)
##
## Summary of sample sizes: 451, 449, 450, 449, 451, 449, ...
##
## Resampling results across tuning parameters:
##
## k Accuracy Kappa Accuracy SD Kappa SD
## 2 0.7915110 0.5774484 0.05869125 0.11851145
## 3 0.7919520 0.5762433 0.04561655 0.09467405
## 4 0.7977935 0.5861272 0.04789043 0.10047463
## 5 0.7896727 0.5683705 0.04675646 0.09941960
## 6 0.7957919 0.5829874 0.03470413 0.07300186
## 7 0.8155958 0.6235336 0.04349820 0.08908015
## 8 0.8075926 0.6081355 0.03885852 0.07792319
## 9 0.8174358 0.6283976 0.04791410 0.09670586
## 10 0.8194766 0.6327796 0.04618713 0.09391225
## 11 0.8214390 0.6366529 0.04860560 0.09915409
## 12 0.8174374 0.6276019 0.04882094 0.10104391
## 13 0.8135974 0.6195562 0.04475565 0.09348686
## 14 0.8094766 0.6113425 0.05439212 0.11325701
## 15 0.8114750 0.6162050 0.05037744 0.10382115
##
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was k = 11.
Repare que a variação é pequena…
plot(knnFit1)
Avaliando o modelo com os dados de teste:
knnPredict <- predict(knnFit1,newdata = emailsTest)
confusionMatrix(knnPredict, emailsTest$spam)
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 666 7
## 1 222 84
##
## Accuracy : 0.7661
## 95% CI : (0.7383, 0.7923)
## No Information Rate : 0.907
## P-Value [Acc > NIR] : 1
##
## Kappa : 0.3267
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.7500
## Specificity : 0.9231
## Pos Pred Value : 0.9896
## Neg Pred Value : 0.2745
## Prevalence : 0.9070
## Detection Rate : 0.6803
## Detection Prevalence : 0.6874
## Balanced Accuracy : 0.8365
##
## 'Positive' Class : 0
##
mosaicplot(table(knnPredict, emailsTest$spam), xlab = "knn", ylab = "dados")
Bem mais ou menos. Veja também que não nos preocupamos com o fato de que os falsos positivos são piores que os falsos negativos.
Tentemos com uma SVM. Aqui não precisamos balancear os dados de treino:
# Aqui demora mais ainda :)
ptm <- proc.time()
svmFit <- train(spam ~ ., data = emailsTrain_b,
method = "svmRadial",
trControl = fitControl,
preProcess = c("center","scale"),
tuneLength = 8,
metric = "Kappa") # outra opção além de accuracy
proc.time() - ptm
## user system elapsed
## 3.156 0.056 3.484
svmFit
## Support Vector Machines with Radial Basis Function Kernel
##
## 500 samples
## 11 predictor
## 2 classes: '0', '1'
##
## Pre-processing: centered, scaled
## Resampling: Cross-Validated (10 fold)
##
## Summary of sample sizes: 451, 450, 451, 451, 450, 449, ...
##
## Resampling results across tuning parameters:
##
## C Accuracy Kappa Accuracy SD Kappa SD
## 0.25 0.7956271 0.5884748 0.06027119 0.1226626
## 0.50 0.7975878 0.5914668 0.05643274 0.1158216
## 1.00 0.8135910 0.6216148 0.06546872 0.1344724
## 2.00 0.8096695 0.6127901 0.06673562 0.1379402
## 4.00 0.7978263 0.5870305 0.06936767 0.1445179
## 8.00 0.8079112 0.6077786 0.06603478 0.1369330
## 16.00 0.8119520 0.6159082 0.06517210 0.1357424
## 32.00 0.8099520 0.6117370 0.06382676 0.1329561
##
## Tuning parameter 'sigma' was held constant at a value of 2.531382
## Kappa was used to select the optimal model using the largest value.
## The final values used for the model were sigma = 2.531382 and C = 1.
svmPredict <- predict(svmFit,newdata = emailsTest)
confusionMatrix(svmPredict, emailsTest$spam)
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 697 14
## 1 191 77
##
## Accuracy : 0.7906
## 95% CI : (0.7637, 0.8157)
## No Information Rate : 0.907
## P-Value [Acc > NIR] : 1
##
## Kappa : 0.337
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.7849
## Specificity : 0.8462
## Pos Pred Value : 0.9803
## Neg Pred Value : 0.2873
## Prevalence : 0.9070
## Detection Rate : 0.7120
## Detection Prevalence : 0.7263
## Balanced Accuracy : 0.8155
##
## 'Positive' Class : 0
##
mosaicplot(table(svmPredict, emailsTest$spam), xlab = "svm", ylab = "dados")
Bem melhor, embora ruim também. Parece que as características que escolhemos dos dados realmente não ajudam…