相同的数据,使用 MASS 和 caret 进行判别分析的不同结果

Same data, different results on discriminant analysis with MASS and caret

关于 R 中预测分析的一个非常简短的问题。 为什么使用 MASS 包线性判别分析获得的交叉验证结果与使用 caret 获得的结果如此不同?

#simulate data
set.seed(4321)

training_data = as.data.frame(matrix(rnorm(10000, sd = 12), 100, 10))
training_data$V1 = as.factor(sample(c(1,0), size = 100, replace = T))
names(training_data)[1] = 'outcome'

#MASS LDA
fit.lda_cv_MASS = lda(outcome~.
            , training_data
            , CV=T)
pred = fit.lda_cv_MASS$class
caret::confusionMatrix(pred, training_data$outcome)

这给出了~0.53

的准确度
#caret interface LDA
lg.fit_cv_CARET = train(outcome ~ .
               , data=training_data
               , method="lda"
               , trControl = trainControl(method = "LOOCV")
              )
pred = predict(lg.fit_cv_CARET, training_data)
caret::confusionMatrix(pred, training_data$outcome)

现在这导致准确度约为 0.63。

我会假设它们是相同的,因为它们都使用留一法交叉验证。

为什么不同?

这里有两点,一是你的错误,二是细微的差别。

第 1 点。

当您对插入符号火车对象调用预测时,您实际上是在对适合所有训练数据的模型调用预测,因此您获得的准确度不是 LOOCV,而是训练准确度。要获得 re-sample 的准确度,您只需调用:

lg.fit_cv_CARET$results
#output:
  parameter Accuracy       Kappa
1      none     0.48 -0.04208417

而不是 0.63,它只是在对训练数据调用 predict 时获得的训练准确度。

然而这仍然不符合LDA获得的0.53。了解原因:

要点2.在拟合模型时,lda也使用参数prior:

the prior probabilities of class membership. If unspecified, the class proportions for the training set are used. If present, the probabilities should be specified in the order of the factor levels

so ldaCV = TRUE 使用与完整训练集相同的先验。而 caret::train 使用由 re-sample 确定的 prior。对于 LOOCV,这应该无关紧要,因为先验变化只是一点点,但是您的数据 类 的分离度非常低,因此先验对后验概率的影响比平常大一些。为了证明这一点,两种方法都使用相同的先验:

fit.lda_cv_MASS <- lda(outcome~.,
                      training_data,
                      CV=T,
                      prior = c(0.5, 0.5))
pred = fit.lda_cv_MASS$class

lg.fit_cv_CARET <- train(outcome ~ .,
                         data=training_data,
                         method="lda",
                         trControl = trainControl(method = "LOOCV"),
                         prior = c(0.5, 0.5)
)

all.equal(lg.fit_cv_CARET$pred$pred, fit.lda_cv_MASS$class)
#output
TRUE

caret::confusionMatrix(pred, training_data$outcome)
#output
Confusion Matrix and Statistics

          Reference
Prediction  0  1
         0 27 25
         1 24 24

               Accuracy : 0.51           
                 95% CI : (0.408, 0.6114)
    No Information Rate : 0.51           
    P-Value [Acc > NIR] : 0.5401         

                  Kappa : 0.0192         
 Mcnemar's Test P-Value : 1.0000         

            Sensitivity : 0.5294         
            Specificity : 0.4898         
         Pos Pred Value : 0.5192         
         Neg Pred Value : 0.5000         
             Prevalence : 0.5100         
         Detection Rate : 0.2700         
   Detection Prevalence : 0.5200         
      Balanced Accuracy : 0.5096         

       'Positive' Class : 0 

lg.fit_cv_CARET$results
#output
  parameter Accuracy      Kappa
1      none     0.51 0.01921537