Calcul de la précision et du rappel dans R

8

Supposons que je construis un classificateur de régression logistique qui prédit si quelqu'un est marié ou célibataire. (1 = marié, 0 = célibataire) Je veux choisir un point sur la courbe précision-rappel qui me donne au moins 75% de précision, donc je veux choisir les seuils et , de sorte que:t1t2

  • Si la sortie de mon classificateur est supérieure à , je produis "marié".t1
  • Si la sortie est inférieure à , je produis "single".t2
  • Si la sortie est entre les deux, je produis "Je ne sais pas".

Quelques questions:

  1. Je pense que dans la définition standard de la précision, la précision mesurera la précision de la classe mariée seule (c.-à-d., Précision = # fois je prédis correctement marié / total # fois je prédis marié). Cependant, ce que je veux vraiment faire, c'est mesurer la précision globale (c.-à-d. Le nombre total de fois où je prédis correctement le mariage ou le célibataire / le nombre total de fois où je prédis le mariage ou le mariage) Est-ce une chose correcte à faire? Sinon, que dois-je faire?
  2. Existe-t-il un moyen de calculer cette courbe de précision / rappel "globale" dans R (par exemple, en utilisant le package ROCR ou une autre bibliothèque)? J'utilise actuellement le package ROCR, mais il ne semble me donner que la précision / le rappel d'une seule classe à la fois.
raegtin
la source

Réponses:

7

J'ai écrit une fonction à cet effet, basée sur l'exercice du livre 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}

Où pour toute tâche de classification binaire, cela renvoie la précision, le rappel et la F-stat pour chaque classification et la précision globale comme suit:

> 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

Le calcul des P, R et F pour chaque classe comme celui-ci vous permet de voir si l'une ou l'autre vous donne plus de difficulté, et il est facile de calculer ensuite les statistiques P, R, F globales. Je n'ai pas utilisé le package ROCR, mais vous pouvez facilement dériver les mêmes courbes ROC en entraînant le classificateur sur la plage de certains paramètres et en appelant la fonction pour les classificateurs aux points le long de la plage.

Robert E Mealey
la source
Je pense que vous avez obtenu un échange de précision et de rappel de code. Il devrait être r [1,5] <- xTab [2,2] / sum (xTab [2,])
danioyuan
6

Comme Robert l'a dit correctement, la précision est la voie à suivre. Je veux juste ajouter qu'il est possible de le calculer avec ROCR. Jetez un œil à l'aide (performances) pour sélectionner différentes mesures.

Par exemple, dans le ROCR, un seul seuil de décision est utilisé, appelé seuil . Le code suivant trace la précision par rapport au seuil et extrait le seuil pour une précision maximale.

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)

ce qui se traduit par

entrez la description de l'image ici

Pour fonctionner avec deux seuils afin de créer une zone médiane d'incertitude (ce qui est une voie valable si les circonstances / l'application cible le permettent), on peut créer deux objets de performance avec ROCR

  1. coupure vs True Positive Rate (tpr) aka précision pour la classe positive
  2. coupure vs True Negative Rate (tnr) aka précision pour la classe négative

Sélectionnez un seuil approprié parmi les vecteurs de performance (en utilisant la méthode R qui) et combinez-les pour atteindre l'équilibre souhaité. Cela devrait être simple, donc je laisse cela comme un exercice au lecteur.

Une dernière remarque: quelle est la différence entre la précision et le calcul de la précision pour les deux classes séparément et par exemple les combiner dans une moyenne (pondérée)?

La précision calcule une moyenne pondérée, où le poids pour la classe c est équivalent au nombre d'instances avec la classe c. Cela signifie que si vous souffrez d'une asymétrie de classe importante (98% de négatifs par exemple), vous pouvez simplement "optimiser" la précision en définissant prédire le négatif de l'étiquette pour toutes les instances. Dans un tel cas, une moyenne simple non pondérée des deux précisions de classe empêche le jeu de la métrique. Dans le cas d'une classe équilibrée, les deux méthodes de calcul conduisent bien sûr au même résultat.

steffen
la source