for - logistic regression example
caret train() predice muy diferente y luego predice.glm() (1)
Estoy tratando de estimar una regresión logística, utilizando la validación cruzada de 10 veces.
#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
El objetivo es estimar un modelo de glm que predice el resultado del voto "Y" o "N" dependiendo de las variables explicativas relevantes y, con base en el modelo final, calcular una matriz de confusión y una curva ROC para captar el comportamiento de los modelos para diferentes niveles de umbral .
La selección del modelo lleva a:
res.chileIII <- glm(vote ~
sex +
education +
statusquo ,
family = binomial(),
data = chile)
#prediction
chile.pred <- predict.glm(res.chileIII, type = "response")
genera:
> head(chile.pred)
1 2 3 4 5 6
0.974317861 0.008376988 0.992720134 0.095014139 0.040348115 0.090947144
Comparar lo observado con la estimación:
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
matriz de confusión para 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
y la curva de roc:
roc.plot(chile.v, chile.pred)
Lo que parece ser un modelo razonable.
Ahora, en lugar de utilizar la función predict.glm () "normal", quiero probar la diferencia de rendimiento en una estimación de validación cruzada de 10 veces.
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
Todos los parámetros significativos.
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
que obviamente es muy diferente de la matriz de confusión anterior. Mi expectativa era que los resultados de validación cruzada no deberían ser mucho peores que el primer modelo. Sin embargo, los resultados muestran algo más.
Supongo que hay un error con la configuración de los parámetros de train () pero no puedo entender de qué se trata.
Realmente agradecería alguna ayuda, gracias de antemano.
Está intentando hacerse una idea del ajuste en la muestra utilizando una matriz de confusión. Tu primer acercamiento usando la función glm()
está bien.
El problema con el segundo enfoque que utiliza train()
encuentra en el objeto devuelto. Está intentando extraer los valores ajustados de la muestra mediante fit$pred$pred
. Sin embargo, fit$pred
no contiene los valores ajustados que están alineados con chile.v
o chile$vote
. Contiene las observaciones y valores ajustados de los diferentes (10) pliegues:
> 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
Por lo tanto, debido a la aleatoriedad de los pliegues y al predecir 0 o 1, obtienes una precisión de aproximadamente el 50%.
Los valores ajustados en la muestra que busca están en los valores fit$finalModel$fitted.values
. Usando esos:
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
Ahora la precisión está alrededor del valor esperado. Al establecer el umbral en 0.5 se obtiene aproximadamente la misma precisión que la estimación de la validación cruzada de 10 veces:
> 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
Además, con respecto a su expectativa "de que los resultados validados en forma cruzada no deberían ser mucho peores que el primer modelo", verifique el summary(res.chileIII)
y el summary(fit)
. Los modelos y coeficientes ajustados son exactamente iguales, por lo que darán los mismos resultados.
PD: Sé que mi respuesta a esta pregunta es tardía, es decir, esta es una pregunta bastante antigua. ¿Está bien responder a estas preguntas de todos modos? Soy nuevo aquí y no encontré nada sobre "respuestas tardías" en la ayuda.