Cálculo de precisión y recuperación en R

8

Supongamos que estoy construyendo un clasificador de regresión logística que predice si alguien está casado o soltero. (1 = casado, 0 = soltero) Quiero elegir un punto en la curva de recuperación de precisión que me brinde al menos un 75% de precisión, por lo que quiero elegir umbralest1 y t2, así que eso:

  • Si la salida de mi clasificador es mayor que t1, Salgo "casado".
  • Si la salida es inferior t2, Salgo "single".
  • Si la salida está en el medio, saco "No sé".

Un par de preguntas:

  1. Creo que, según la definición estándar de precisión, la precisión medirá la precisión de la clase de casados ​​solo (es decir, precisión = # veces predigo correctamente casado / total # veces predigo casado). Sin embargo, lo que realmente quiero hacer es medir la precisión general (es decir, el total de # veces que predigo correctamente casado o soltero / total de # veces que predigo casado o soltero). ¿Es esto algo correcto? Si no, ¿qué debo hacer?
  2. ¿Hay alguna manera de calcular esta curva de precisión / recuperación "general" en R (por ejemplo, usando el paquete ROCR o alguna otra biblioteca)? Actualmente estoy usando el paquete ROCR, pero parece que solo me da la precisión / recuperación de una sola clase a la vez.
raegtin
fuente

Respuestas:

7

Escribí una función para este propósito, basada en el ejercicio en el libro 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}

Donde para cualquier tarea de clasificación binaria, esto devuelve la precisión, la recuperación y la estadística F para cada clasificación y la precisión general de esta manera:

> 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

Calcular el P, R y F para cada clase de esta manera te permite ver si uno u otro te está dando más dificultad, y es fácil calcular las estadísticas generales de P, R y F. No he usado el paquete ROCR, pero podría derivar fácilmente las mismas curvas ROC entrenando al clasificador sobre el rango de algún parámetro y llamando a la función para clasificadores en puntos a lo largo del rango.

Robert E Mealey
fuente
Creo que se cambió la precisión y el código de recuperación. Debería ser r [1,5] <- xTab [2,2] / sum (xTab [2,])
danioyuan el
6

Como Robert lo expresó correctamente, la precisión es el camino a seguir. Solo quiero agregar que es posible calcularlo con ROCR. Consulte la ayuda (rendimiento) para seleccionar diferentes medidas.

Por ejemplo, en ROCR solo se usa un umbral de decisión que se llama corte . El siguiente código traza la precisión frente al corte y extrae el corte para obtener la máxima precisión.

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)

lo que resulta en

ingrese la descripción de la imagen aquí

Para operar con dos umbrales con el fin de crear una región intermedia de incertidumbre (que es una forma válida de hacerlo si las circunstancias / aplicación de destino lo permite) se pueden crear dos objetos de rendimiento con ROCR

  1. corte frente a la verdadera tasa positiva (tpr), también conocida como precisión para la clase positiva
  2. punto de corte vs True Negative Rate (tnr) también conocido como precisión para la clase negativa

Seleccione un límite adecuado de los vectores de rendimiento (utilizando el método R que) y combínelos para lograr el equilibrio deseado. Esto debería ser sencillo, por lo tanto, lo dejo como un ejercicio para el lector.

Una última nota: ¿Cuál es la diferencia entre precisión y cálculo de precisión para ambas clases por separado y, por ejemplo, combinarlas en un promedio (ponderado)?

La precisión calcula un promedio ponderado, donde el peso para la clase c es equivalente al número de instancias con la clase c. Esto significa que si sufre una fuerte desviación de clase (98% negativas, por ejemplo) puede simplemente "optimizar" la precisión configurando predecir la etiqueta negativa para todas las instancias. En tal caso, un promedio simple no ponderado de ambas precisiones de clase impide el juego de la métrica. En el caso de clases equilibradas, ambos métodos de cálculo conducen, por supuesto, al mismo resultado.

steffen
fuente