2017-08-18 1 views
0

J'utilise la fonction twoClassSummary de caret pour déterminer les hyper-paramètres optimaux du modèle afin de maximiser Spécificité. Cependant, comment la fonction détermine-t-elle le seuil de probabilité qui maximise la spécificité?Comment caret train détermine le seuil de probabilité pour maximiser Spécificité

Est-ce que le caret essentiellement pour chaque hyper-paramètre/pli de modèle évalue chaque seuil entre 0 et 1 et renvoie la Spécificité maximale? Dans l'exemple ci-dessous, vous pouvez voir que le modèle a atterri sur cp = 0.01492537.

# load libraries 
library(caret) 
library(mlbench) 
# load the dataset 
data(PimaIndiansDiabetes) 
# prepare resampling method 
control <- trainControl(method="cv", 
         number=5, 
         classProbs=TRUE, 
         summaryFunction=twoClassSummary) 

set.seed(7) 
fit <- train(diabetes~., 
      data=PimaIndiansDiabetes, 
      method="rpart", 
      tuneLength= 5, 
      metric="Spec", 
      trControl=control) 

print(fit) 


CART 

768 samples 
    8 predictor 
    2 classes: 'neg', 'pos' 

No pre-processing 
Resampling: Cross-Validated (5 fold) 
Summary of sample sizes: 614, 614, 615, 615, 614 
Resampling results across tuning parameters: 

    cp   ROC  Sens Spec  
    0.01305970 0.7615943 0.824 0.5937806 
    0.01492537 0.7712055 0.824 0.6016073 
    0.01741294 0.7544469 0.830 0.5976939 
    0.10447761 0.6915783 0.866 0.5035639 
    0.24253731 0.6437820 0.884 0.4035639 

Spec was used to select the optimal model using the largest value. 
The final value used for the model was cp = 0.01492537. 

Répondre

1

Non, twoClassSummary n'évalue pas tous les seuil entre 0 et 1. Il ne retourne que les valeurs d'un seuil standard de 0,5.

Le twoClassSummary est défini comme:

function (data, lev = NULL, model = NULL) 
{ 
    lvls <- levels(data$obs) 
    if (length(lvls) > 2) 
     stop(paste("Your outcome has", length(lvls), "levels. The twoClassSummary() function isn't appropriate.")) 
    requireNamespaceQuietStop("ModelMetrics") 
    if (!all(levels(data[, "pred"]) == lvls)) 
     stop("levels of observed and predicted data do not match") 
    rocAUC <- ModelMetrics::auc(ifelse(data$obs == lev[2], 0, 
     1), data[, lvls[1]]) 
    out <- c(rocAUC, sensitivity(data[, "pred"], data[, "obs"], 
     lev[1]), specificity(data[, "pred"], data[, "obs"], lev[2])) 
    names(out) <- c("ROC", "Sens", "Spec") 
    out 
} 

Pour vérifier ma déclaration, essayez l'exemple suivant une coutume summaryFunction où je mets excplicitly le seuil à 0,5 et vous verrez que les deux valeurs Spec (la spécificité d'origine rapporté par twoClassSummary) et Spec2 (spécificité seuil fixé manuellement à 0,5) sera exactement le même:

# load libraries 
library(caret) 
library(mlbench) 
# load the dataset 
data(PimaIndiansDiabetes) 

# define custom summaryFunction 
customSummary <- function (data, lev = NULL, model = NULL){ 
    spec <- specificity(data[, "pred"], data[, "obs"], lev[2]) 
    pred <- factor(ifelse(data[, "neg"] > 0.5, "neg", "pos")) 
    spec2 <- specificity(pred, data[, "obs"], "pos") 
    out <- c(spec, spec2) 

    names(out) <- c("Spec", "Spec2") 
    out 
} 

# prepare resampling method 
control <- trainControl(method="cv", 
         number=5, 
         classProbs=TRUE, 
         summaryFunction=customSummary) 

set.seed(7) 
fit <- train(diabetes~., 
      data=PimaIndiansDiabetes, 
      method="rpart", 
      tuneLength= 5, 
      metric="Spec", 
      trControl=control) 

print(fit) 
CART 

768 samples 
    8 predictor 
    2 classes: 'neg', 'pos' 

No pre-processing 
Resampling: Cross-Validated (5 fold) 
Summary of sample sizes: 615, 615, 614, 614, 614 
Resampling results across tuning parameters: 

    cp   Spec  Spec2  
    0.01305970 0.5749825 0.5749825 
    0.01492537 0.5411600 0.5411600 
    0.01741294 0.5596785 0.5596785 
    0.10447761 0.4932215 0.4932215 
    0.24253731 0.2837177 0.2837177 

Spec was used to select the optimal model using the largest value. 
The final value used for the model was cp = 0.0130597. 

en outre, si vous souhaitez caret pour calculer la spécificité maximale pour un cadre de hyperparam'etres pour un seuil et de faire rapport à cette valeur, vous pouvez définir un summaryFunction personnalisé comme ce qui suit, qui essayera tous les seuils entre 0,1 et 0,95 étapes de 0,05:

# define custom summaryFunction 
customSummary <- function (data, lev = NULL, model = NULL){ 
    spec <- specificity(data[, "pred"], data[, "obs"], lev[2]) 
    pred <- factor(ifelse(data[, "neg"] > 0.5, "neg", "pos")) 
    spec2 <- specificity(pred, data[, "obs"], "pos") 
    speclist <- as.numeric() 
    for(i in seq(0.1, 0.95, 0.05)){ 
    predi <- factor(ifelse(data[, "neg"] > i, "neg", "pos")) 
    singlespec <- specificity(predi, data[, "obs"], "pos") 
    speclist <- c(speclist, singlespec) 
    } 
    max(speclist) -> specmax 

    out <- c(spec, spec2, specmax) 

    names(out) <- c("Spec", "Spec2", "Specmax") 
    out 
}