web-dev-qa-db-fra.com

caret train () prédit très différent, alors prédit.glm ()

J'essaie d'estimer une régression logistique, en utilisant la validation croisée 10 fois.

#import libraries
library(car); library(caret); library(e1071); library(verification)

#data import and preparation
data(Chile)              
chile        <- na.omit(Chile)  #remove "na's"
chile        <- chile[chile$vote == "Y" | chile$vote == "N" , ] #only "Y" and "N" required
chile$vote   <- factor(chile$vote)      #required to remove unwanted levels 
chile$income <- factor(chile$income)  # treat income as a factor

Le but est d'estimer un modèle glm qui prédit le résultat du vote "Y" ou "N" en fonction des variables explicatives pertinentes et, sur la base du modèle final, de calculer une matrice de confusion et une courbe ROC pour saisir le comportement des modèles pour différents niveaux de seuil .

La sélection du modèle conduit à:

res.chileIII <- glm(vote ~
                           sex       +
                           education +
                           statusquo ,
                           family = binomial(),
                           data = chile)
#prediction
chile.pred <- predict.glm(res.chileIII, type = "response")

génère:

> head(chile.pred)
          1           2           3           4           5           6 
0.974317861 0.008376988 0.992720134 0.095014139 0.040348115 0.090947144 

pour comparer l'observé avec l'estimation:

chile.v     <- ifelse(chile$vote == "Y", 1, 0)          #to compare the two arrays
chile.predt <- function(t) ifelse(chile.pred > t , 1,0) #t is the threshold for which the confusion matrix shall be computed

matrice de confusion pour t = 0,3:

confusionMatrix(chile.predt(0.3), chile.v)

> confusionMatrix(chile.predt(0.3), chile.v)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 773  44
         1  94 792

               Accuracy : 0.919          
                 95% CI : (0.905, 0.9315)
    No Information Rate : 0.5091         
    P-Value [Acc > NIR] : < 2.2e-16 

et la courbe Roc:

roc.plot(chile.v, chile.pred)

ce qui semble être un modèle raisonnable.

Maintenant, au lieu d'utiliser la fonction "normale" de Predict.glm (), je veux tester la différence de performances avec une estimation de validation croisée 10 fois.

tc <- trainControl("cv", 10, savePredictions=T)  #"cv" = cross-validation, 10-fold
fit <- train(chile$vote ~ chile$sex            +
                          chile$education      +
                          chile$statusquo      ,
                          data      = chile    ,
                          method    = "glm"    ,
                          family    = binomial ,
                          trControl = tc)

> summary(fit)$coef
                      Estimate Std. Error   z value      Pr(>|z|)
(Intercept)          1.0152702  0.1889646  5.372805  7.752101e-08
`chile$sexM`        -0.5742442  0.2022308 -2.839549  4.517738e-03
`chile$educationPS` -1.1074079  0.2914253 -3.799971  1.447128e-04
`chile$educationS`  -0.6827546  0.2217459 -3.078996  2.076993e-03
`chile$statusquo`    3.1689305  0.1447911 21.886224 3.514468e-106

tous les paramètres sont significatifs.

fitpred <- ifelse(fit$pred$pred == "Y", 1, 0) #to compare with chile.v

> confusionMatrix(fitpred,chile.v)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 445 429
         1 422 407

 Accuracy : 0.5003          
                 95% CI : (0.4763, 0.5243)
    No Information Rate : 0.5091          
    P-Value [Acc > NIR] : 0.7738

ce qui est évidemment très différent de la matrice de confusion précédente. Je m'attendais à ce que les résultats de la validation croisée ne soient pas beaucoup moins bons que le premier modèle. Cependant, les résultats montrent autre chose.

Mon hypothèse est qu'il y a une erreur avec les réglages des paramètres train () mais je ne peux pas comprendre ce que c'est.

J'apprécierais vraiment de l'aide, merci d'avance.

30
Vincent

Vous essayez de vous faire une idée de l'ajustement dans l'échantillon à l'aide d'une matrice de confusion. Votre première approche utilisant la fonction glm() est très bien.

Le problème avec la deuxième approche utilisant train() réside dans l'objet renvoyé. Vous essayez d'en extraire les valeurs ajustées dans l'échantillon par fit$pred$pred. Cependant, fit$pred Ne contient pas les valeurs ajustées qui sont alignées sur chile.v Ou chile$vote. Il contient les observations et les valeurs ajustées des différents (10) plis:

> head(fit$pred)
  pred obs rowIndex parameter Resample
1    N   N        2      none   Fold01
2    Y   Y       20      none   Fold01
3    Y   Y       28      none   Fold01
4    N   N       38      none   Fold01
5    N   N       55      none   Fold01
6    N   N       66      none   Fold01
> tail(fit$pred)
     pred obs rowIndex parameter Resample
1698    Y   Y     1592      none   Fold10
1699    Y   N     1594      none   Fold10
1700    N   N     1621      none   Fold10
1701    N   N     1656      none   Fold10
1702    N   N     1671      none   Fold10
1703    Y   Y     1689      none   Fold10 

Donc, en raison du caractère aléatoire des plis, et parce que vous prédisez 0 ou 1, vous obtenez une précision d'environ 50%.

Les valeurs ajustées dans l'échantillon que vous recherchez sont dans fit$finalModel$fitted.values. En utilisant ceux-ci:

fitpred <- fit$finalModel$fitted.values
fitpredt <- function(t) ifelse(fitpred > t , 1,0)
> confusionMatrix(fitpredt(0.3),chile.v)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 773  44
         1  94 792

               Accuracy : 0.919          
                 95% CI : (0.905, 0.9315)
    No Information Rate : 0.5091         
    P-Value [Acc > NIR] : < 2.2e-16      

                  Kappa : 0.8381         
 Mcnemar's Test P-Value : 3.031e-05      

            Sensitivity : 0.8916         
            Specificity : 0.9474         
         Pos Pred Value : 0.9461         
         Neg Pred Value : 0.8939         
             Prevalence : 0.5091         
         Detection Rate : 0.4539         
   Detection Prevalence : 0.4797         
      Balanced Accuracy : 0.9195         

       'Positive' Class : 0               

Maintenant, la précision se situe autour de la valeur attendue. La définition du seuil à 0,5 donne à peu près la même précision que l'estimation de la validation croisée multipliée par 10:

> confusionMatrix(fitpredt(0.5),chile.v)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 809  64
         1  58 772

               Accuracy : 0.9284          
                 95% CI : (0.9151, 0.9402)
[rest of the output omitted]            

> fit
Generalized Linear Model 

1703 samples
   7 predictors
   2 classes: 'N', 'Y' 

No pre-processing
Resampling: Cross-Validated (10 fold) 

Summary of sample sizes: 1533, 1532, 1532, 1533, 1532, 1533, ... 

Resampling results

  Accuracy  Kappa  Accuracy SD  Kappa SD
  0.927     0.854  0.0134       0.0267  

De plus, en ce qui concerne votre attente "que les résultats de la validation croisée ne fonctionnent pas bien moins bien que le premier modèle", veuillez vérifier summary(res.chileIII) et summary(fit). Les modèles ajustés et les coefficients sont exactement les mêmes, ils donneront donc les mêmes résultats.

P.S. Je sais que ma réponse à cette question est tardive - c'est-à-dire. c'est une question assez ancienne. Est-il acceptable de répondre à ces questions de toute façon? Je suis nouveau ici et je n'ai rien trouvé sur les "réponses tardives" dans l'aide.

62
thie1e