Data Science, Machine Learning, Recuperação da Informação

Validação Cruzada: Conceito e Exemplo em R

O que é validação cruzada (cross-validation)?

No Aprendizado de Máquina, a validação cruzada é um método de re-amostragem usado para avaliação de modelo para evitar o teste de um modelo no mesmo conjunto de dados no qual ele foi treinado. Este é um erro comum, especialmente que um conjunto de dados de teste separado nem sempre está disponível. No entanto, isso geralmente leva a medidas de desempenho imprecisas (já que o modelo terá uma pontuação quase perfeita, pois está sendo testado nos mesmos dados em que foi treinado). Para evitar esse tipo de erro, a validação cruzada é geralmente preferida.

O conceito de validação cruzada é realmente simples: em vez de usar todo o conjunto de dados para treinar e, em seguida, testar nos mesmos dados, poderíamos dividir aleatoriamente nossos dados em conjuntos de dados de treinamento e teste.

Existem vários tipos de métodos de validação cruzada  (LOOCV – validação cruzada de saída única,  o método holdout validação cruzada k-fold). Aqui, vou discutir o método de validação cruzada K-Fold.

K-Fold consiste basicamente nas etapas abaixo:

  1. Divida aleatoriamente os dados em k subconjuntos, também chamados de dobras.
  2. Encaixe o modelo nos dados de treinamento (ou k-1 dobras).
  3. Use a parte restante dos dados como conjunto de testes para validar o modelo. (Normalmente, nesta etapa, a precisão ou o erro de teste do modelo é medido).
  4. Repita o procedimento k vezes.

Abaixo está uma ilustração simples do procedimento retirado da Wikipedia.

k-fold_cross_validation_en

Como isso pode ser feito com R?

No exercício abaixo, estou usando a regressão logística para prever se um passageiro do famoso conjunto de dados Titanic sobreviveu ou não. O objetivo é encontrar um limite ideal nas previsões para saber se deve classificar o resultado como 1 ou 0.

Exemplo de Limiar:  Considere que o modelo previu os seguintes valores para dois passageiros: p1 = 0,7 e p2 = 0,4. Se o  limite  for 0,5, então p1>  limiar  e passageiro 1 estão na categoria de sobrevivência  . Considerando que p2 <  limiar,  assim o passageiro 2 está na categoria não sobrevivida .

No entanto, e dependendo dos nossos dados, o   limite 0,5 ‘padrão’ não garante sempre o máximo do número de classificações corretas. Nesse contexto, poderíamos usar a validação cruzada  para determinar o melhor limite para cada dobra com base nos resultados da execução do modelo no conjunto de validação .

Na minha implementação, segui os passos abaixo:

  1. Divida os dados aleatoriamente em 80 (treinamento e validação),  20 (teste com dados não vistos) .
  2. Execute a validação cruzada em 80% dos dados, que serão usados ​​para treinar validar o modelo. 
  3. Obtenha o limite ideal depois de executar o modelo no conjunto de dados de validação de acordo com a melhor precisão em cada iteração de dobra.
  4. Armazene a melhor precisão e o limite ideal resultante das iterações de dobra em um dataframe.
  5. Encontre o melhor limite (aquele que possui a maior precisão) e use-o como um limite ao testar o modelo em relação ao conjunto de dados de teste.

Nota: O ROC é geralmente o melhor método a ser usado para encontrar uma probabilidade de ‘corte’ ideal, mas por questão de simplicidade, estou usando a precisão no código abaixo.   

O método cross_validation abaixo irá:

  1. Crie um dataframe ‘ perf ‘ que armazene os resultados do teste do modelo nos dados de validação.
  2. Use o método createFolds para criar  nbfolds  número de dobras.
  3. Em cada uma das dobras:
    • Treine o modelo em dobras k-1
    • Teste o modelo na parte restante dos dados
    • Meça a precisão do modelo usando o  método de desempenho  .
    • Adicione o limite ideal e sua precisão ao dataframe perf .
  4. Procure no dataframe perf  para optThresh –  o limite com a maior precisão.
  5. Use-o como corte ao testar o modelo no conjunto de teste  (20% dos dados originais).
  6. Use pontuação F1 para medir a precisão do modelo.
library(ROCR)
cross_validation = function(nbfolds, split){
 perf = data.frame()
 #create folds
 folds = createFolds(split$trainset$survived, nbfolds, list = TRUE, returnTrain = TRUE)
#loop nbfolds times to find optimal threshold
 for(i in 1:nbfolds)
   {
      #train the model on part of the data
      model = glm(survived~., data=split$trainset[folds[[i]],], family = "binomial")
      #validate on the remaining part of the data
      probs = predict(model, type="response", newdata = split$trainset[-folds[[i]],])
      #Threshold selection based on Accuracy
      #create a prediction object based on the predicted values
      pred = prediction(probs,split$trainset[-folds[[i]],]$survived)
      #measure performance of the prediction
      acc.perf = performance(pred, measure = "acc")
      #Find index of most accurate threshold and add threshold in data frame
      ind = which.max( slot(acc.perf, "y.values")[[1]] )
      acc = slot(acc.perf, "y.values")[[1]][ind]
      optimalThreshold = slot(acc.perf, "x.values")[[1]][ind]
      row = data.frame(threshold = optimalThreshold, accuracy = acc)
      #Store the best thresholds with their performance in the perf dataframe
      perf = rbind(perf, row)
   }
 #Get the threshold with the max accuracy among the nbfolds and predict based on it on the unseen test set
 indexOfMaxPerformance = which.max(perf$accuracy)
 optThresh = perf$threshold[indexOfMaxPerformance]
 probs = predict(model, type="response", newdata = split$testset)
 predictions = data.frame(survived=split$testset$survived, pred=probs)
 T = table(predictions$survived, predictions$pred &amp;amp;gt; optThresh)
 F1 = (2*(T[1,1]))/((2*(T[1,1]))+T[2,1]+T[1,2])
 F1
}

Então, se executarmos esse método 100 vezes, poderemos medir a precisão máxima do nosso modelo ao usar a validação cruzada:

for(i in 1:100){
 #split the data into 80-20
 split = splitdf(df, i, 0.8)
 #perform feature selection at each iteration on the training data
 split = easyFeatureSelection(split)
 #get optimal performance from 10 folds at each iteration
 performance = cross_validation(10, split)
}
screen-shot-2017-03-03-at-11-30-25-am-e1488537482448
Podemos ver que temos um desempenho máximo de cerca de 0,885 ao usar o método de acurácia para seleção de limite, o que não é nada mau, levando em consideração que o modelo está sendo testado em dados não vistos.
Exemplo de Cross-validation no Python (link)

Este artigo foi escrito por Sondos Atwi (todos os direitos reservados ao autor)

ValidacaoCruzada

 

Vejam também:
A Gentle Introduction to k-fold Cross-Validation

Um comentário sobre “Validação Cruzada: Conceito e Exemplo em R

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s