【问题标题】:caret train() predicts very different then predict.glm()插入符号 train() 预测与 predict.glm() 非常不同
【发布时间】:2014-07-11 11:24:03
【问题描述】:

我正在尝试使用 10 倍交叉验证来估计逻辑回归。

#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

目标是估计一个 glm - 模型预测投票结果“Y”或“N”取决于相关的解释变量,并根据最终模型计算混淆矩阵和 ROC 曲线以掌握模型的行为不同的阈值水平。

模型选择导致:

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

生成:

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

将观测值与估计值进行比较:

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

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 

Roc 曲线:

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

这似乎是一个合理的模型。

现在我想测试 10 倍交叉验证估计的性能差异,而不是使用“正常”的 predict.glm() 函数。

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

所有参数都很重要。

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

这显然与之前的混淆矩阵有很大不同。我的期望是交叉验证的结果不应该比第一个模型差很多。但是结果显示了其他内容。

我的假设是 train() 参数的设置有误,但我无法弄清楚它是什么。

非常感谢您的帮助,在此先感谢您。

【问题讨论】:

    标签: r glm r-caret confusion-matrix


    【解决方案1】:

    您正在尝试使用混淆矩阵来了解样本内拟合。您使用glm() 函数的第一种方法很好。

    使用train() 的第二种方法的问题在于返回的对象。您正试图通过fit$pred$pred 从中提取样本内拟合值。但是,fit$pred 不包含与chile.vchile$vote 对齐的拟合值。它包含不同 (10) 折叠的观察值和拟合值:

    > 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 
    

    因此,由于折叠的随机性,并且由于您预测的是 0 或 1,因此您的准确率大约为 50%。

    您要查找的样本内拟合值位于 fit$finalModel$fitted.values 中。使用这些:

    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               
    

    现在准确度在预期值附近。将阈值设置为 0.5 产生的准确度与 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  
    

    此外,关于您期望“交叉验证的结果不应比第一个模型差很多”,请检查summary(res.chileIII)summary(fit)。拟合的模型和系数完全相同,因此它们将给出相同的结果。

    附:我知道我对这个问题的回答迟到了——即这是一个很老的问题。无论如何都可以回答这些问题吗?我是新来的,在帮助中没有找到任何关于“迟到的答案”的信息。

    【讨论】:

    • 您好,非常感谢。好吧,你永远不知道谁在读什么,什么时候读。我读了很多对我有很大帮助的“旧帖子”。
    • 同意,我自己发现这很有用。很好的答案!
    • 哇!这很有帮助!
    • 这个问题和这个答案结合起来是一个关于如何使用插入符号的简洁教程!太棒了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 2019-06-02
    • 2017-05-19
    • 2018-11-11
    • 1970-01-01
    • 2012-07-01
    • 2015-10-28
    相关资源
    最近更新 更多