Cálculo da precisão e recuperação em R

8

Suponha que eu esteja construindo um classificador de regressão logística que preveja se alguém é casado ou solteiro. (1 = casado, 0 = solteiro) Quero escolher um ponto na curva de precisão-recall que me dê pelo menos 75% de precisão, portanto, desejo escolher os limites e , para que:t 2t1t2

  • Se a saída do meu classificador for maior que , a saída será "casada".t1
  • Se a saída estiver abaixo de , eu "single".t2
  • Se a saída estiver no meio, eu saio "Não sei".

Algumas perguntas:

  1. Penso que, sob a definição padrão de precisão, a precisão medirá a precisão da classe casada sozinha (ou seja, precisão = # vezes que eu prevejo corretamente o número total de vezes que prevejo o casamento). No entanto, o que eu realmente quero fazer é medir a precisão geral (ou seja, o total de # vezes que prevejo corretamente o casamento ou solteiro / total de vezes o número de predições de casado ou solteiro). Isso é bom? Se não, o que devo fazer?
  2. Existe uma maneira de calcular essa curva "geral" de precisão / recall em R (por exemplo, usando o pacote ROCR ou alguma outra biblioteca)? Atualmente, estou usando o pacote ROCR, mas parece apenas fornecer a precisão / recall de classe única de cada vez.
raegtin
fonte

Respostas:

7

Escrevi uma função para esse fim, com base no exercício do livro Data Mining with R:

# Function: evaluation metrics
    ## True positives (TP) - Correctly idd as success
    ## True negatives (TN) - Correctly idd as failure
    ## False positives (FP) - success incorrectly idd as failure
    ## False negatives (FN) - failure incorrectly idd as success
    ## Precision - P = TP/(TP+FP) how many idd actually success/failure
    ## Recall - R = TP/(TP+FN) how many of the successes correctly idd
    ## F-score - F = (2 * P * R)/(P + R) harm mean of precision and recall
prf <- function(predAct){
    ## predAct is two col dataframe of pred,act
    preds = predAct[,1]
    trues = predAct[,2]
    xTab <- table(preds, trues)
    clss <- as.character(sort(unique(preds)))
    r <- matrix(NA, ncol = 7, nrow = 1, 
        dimnames = list(c(),c('Acc',
        paste("P",clss[1],sep='_'), 
        paste("R",clss[1],sep='_'), 
        paste("F",clss[1],sep='_'), 
        paste("P",clss[2],sep='_'), 
        paste("R",clss[2],sep='_'), 
        paste("F",clss[2],sep='_'))))
    r[1,1] <- sum(xTab[1,1],xTab[2,2])/sum(xTab) # Accuracy
    r[1,2] <- xTab[1,1]/sum(xTab[,1]) # Miss Precision
    r[1,3] <- xTab[1,1]/sum(xTab[1,]) # Miss Recall
    r[1,4] <- (2*r[1,2]*r[1,3])/sum(r[1,2],r[1,3]) # Miss F
    r[1,5] <- xTab[2,2]/sum(xTab[,2]) # Hit Precision
    r[1,6] <- xTab[2,2]/sum(xTab[2,]) # Hit Recall
    r[1,7] <- (2*r[1,5]*r[1,6])/sum(r[1,5],r[1,6]) # Hit F
    r}

Onde, para qualquer tarefa de classificação binária, isso retorna a precisão, recall e F-stat para cada classificação e a precisão geral da seguinte forma:

> pred <- rbinom(100,1,.7)
> act <- rbinom(100,1,.7)
> predAct <- data.frame(pred,act)
> prf(predAct)
      Acc     P_0       R_0       F_0       P_1       R_1       F_1
[1,] 0.63 0.34375 0.4074074 0.3728814 0.7647059 0.7123288 0.7375887

O cálculo de P, R e F para cada classe como essa permite ver se uma ou outra está lhe dando mais dificuldade, e é fácil calcular as estatísticas gerais de P, R e F. Eu não usei o pacote ROCR, mas você pode derivar facilmente as mesmas curvas ROC treinando o classificador ao longo de algum parâmetro e chamando a função de classificadores em pontos ao longo do intervalo.

Robert E Mealey
fonte
Eu acho que você tem precisão e código de recall trocados. Deve ser r [1,5] <- xTab [2,2] / soma (xTab [2,])
danioyuan
6

Como Robert colocou corretamente, a precisão é o caminho a percorrer. Eu só quero acrescentar que é possível calculá-lo com o ROCR. Dê uma olhada na ajuda (desempenho) para selecionar diferentes medidas.

Por exemplo, no ROCR, apenas um limite de decisão é usado, chamado de ponto de corte . O código a seguir plota precisão versus ponto de corte e extrai o ponto de corte para máxima precisão.

require(ROCR)

# Prepare data for plotting
data(ROCR.simple)
pred <- with(ROCR.simple, prediction(predictions, labels))
perf <- performance(pred, measure="acc", x.measure="cutoff")

# Get the cutoff for the best accuracy
bestAccInd <- which.max(perf@"y.values"[[1]])
bestMsg <- paste("best accuracy=", perf@"y.values"[[1]][bestAccInd], 
              " at cutoff=", round(perf@"x.values"[[1]][bestAccInd], 4))

plot(perf, sub=bestMsg)

o que resulta em

insira a descrição da imagem aqui

Para operar com dois limites, a fim de criar uma região intermediária de incerteza (que é um caminho válido se as circunstâncias / o aplicativo de destino permitir), é possível criar dois objetos de desempenho com o ROCR

  1. cutoff vs True Positive Rate (tpr), também conhecida como precisão para a classe positiva
  2. cutoff vs True Negative Rate (tnr), também conhecida como precisão para a classe negativa

Selecione um ponto de corte adequado a partir dos vetores de desempenho (usando o método R) e combine-os para obter o equilíbrio desejado. Isso deve ser direto, portanto deixo como um exercício para o leitor.

Uma última observação: qual é a diferença entre Precisão e precisão de cálculo para ambas as classes separadamente e, por exemplo, combiná-las em uma média (ponderada)?

A precisão calcula uma média ponderada, em que o peso da classe c é equivalente ao número de instâncias da classe c. Isso significa que, se você sofrer uma grande distorção de classe (98% negativos, por exemplo), poderá simplesmente "otimizar" a precisão definindo prever o rótulo negativo para todas as instâncias. Nesse caso, uma média simples não ponderada das precisões de ambas as classes impede o jogo da métrica. No caso de classes equilibradas, ambos os métodos de cálculo levam, obviamente, ao mesmo resultado.

Steffen
fonte