当 classProbs=TRUE 时,在 R 中使用 Caret 的 SVM 的不同结果

Different results for SVM using Caret in R when classProbs=TRUE

当我尝试使用支持向量机 (SVM) 提取预测概率时,我遇到了以下问题。通常 classification 算法的概率截止值为 0.5。但我需要分析 SVM 机器学习算法的准确度如何随概率截止值变化。

我在 R 中使用了 caret 包和留一法交叉验证 (LOOCV)

首先,我在不提取 class 概率的情况下拟合了常规 svm 模型。所以它只会存储预测的 class 标签。

数据来源:https://www.kaggle.com/uciml/pima-indians-diabetes-database

require(caret)
set.seed(123)
diabetes <- read.csv("C:/Users/Downloads/228_482_bundle_archive/diabetes.csv")
fitControl1 <- trainControl( method = "LOOCV",savePredictions = T,search = "random")
diabetes$Outcome=factor(diabetes$Outcome)
modelFitlassocvintm1 <- train((Outcome) ~ Pregnancies+BloodPressure+Glucose +
                                BMI+DiabetesPedigreeFunction +Age
                              , data=diabetes, 
                              method = "svmRadialSigma", 
                              trControl = fitControl1,
                              preProcess = c("center", "scale"),
                              tuneGrid=expand.grid(
                                .sigma=0.004930389,
                                .C=9.63979626))

要提取预测概率,我需要在 trainControl 中指定 classProbs = T

set.seed(123)
fitControl2 <- trainControl( method = "LOOCV",savePredictions = T,classProbs = T)
diabetes$Outcome=factor(diabetes$Outcome)
modelFitlassocvintm2 <- train(make.names(Outcome) ~ Pregnancies+BloodPressure+Glucose +
                                BMI+DiabetesPedigreeFunction +Age
                              , data=diabetes, 
                              method = "svmRadialSigma", 
                              trControl = fitControl2,
                              preProcess = c("center", "scale"),
                              tuneGrid=expand.grid(
                                .sigma=0.004930389,
                                .C=9.63979626))

modelFitlassocvintm1modelFitlassocvintm2 的唯一区别是在 trainControl.

中包含了 classProbs = T

如果我比较 modelFitlassocvintm1modelFitlassocvintm2 的预测 classes,它在 0.5 概率截止值下应该是相同的。 但事实并非如此。

table(modelFitlassocvintm2$pred$X1 >0.5,modelFitlassocvintm1$pred$pred)
       
          0   1
  FALSE 560   0
  TRUE    8 200

然后当我进一步调查这 8 个不同的值时,我得到了以下结果。

subs1=cbind(modelFitlassocvintm2$pred$X1,modelFitlassocvintm2$pred$pred,modelFitlassocvintm1$pred$pred)
subset(subs1,subs1[,2]!=subs1[,3])
          [,1] [,2] [,3]
[1,] 0.5078631    2    1
[2,] 0.5056252    2    1
[3,] 0.5113336    2    1
[4,] 0.5048708    2    1
[5,] 0.5033003    2    1
[6,] 0.5014327    2    1
[7,] 0.5111975    2    1
[8,] 0.5136453    2    1

看来,当预测概率接近0.5时,modelFitlassocvintm1modelFitlassocvintm2中预测的class似乎存在差异。我也看到 svm 使用不同的数据集也有类似的差异。

这可能是什么原因?我们不能相信 svm 的预测概率吗?通常,svm class 将主题定义为 -1 或 1 ,具体取决于它相对于超平面的一侧。所以依靠 svm 的预测概率不是一件好事吗?

正如 desertnaut 在评论中指出的那样,SVM 不是概率分类器;它们实际上并不产生概率。

创建概率的一种方法是直接使用 logit link 函数和正则化最大似然分数训练核分类器。但是,具有最大似然分数的训练将产生 non-sparse 核机器。相反,在训练 SVM 之后,训练一个额外的 S 型函数的参数以将 SVM 输出映射到概率。参考论文:Probabilistic Outputs for Support Vector Machines and Comparisons to Regularized Likelihood Methods

插入符 method = "svmRadialSigma" 在内部使用 kernlab::ksvm 和参数 kernel = "rbfdot"。为了让这个函数创建概率,需要参数 prob.model = TRUE。来自这个函数的帮助:

prob.model if set to TRUE builds a model for calculating class probabilities or in case of regression, calculates the scaling parameter of the Laplacian distribution fitted on the residuals. Fitting is done on output data created by performing a 3-fold cross-validation on the training data. For details see references. (default: FALSE)

参考详情:

In classification when prob.model is TRUE a 3-fold cross validation is performed on the data and a sigmoid function is fitted on the resulting decision values f.

很明显,当需要后验概率时,分类模型正在发生一些非常具体的事情。这与仅输出决策值不同。

由此可以推导出,根据 sigmoid 函数拟合一些 与 运行 [kernlab::ksvm] 没有 prob.model (prob.model = FALSE) 时相比,决策值可能不同,这就是您在发布的示例中观察到的。

如果超过两个 类,事情会变得更加复杂 类。

进一步阅读:

Including class probabilities might skew a model in caret?

Isn't caret SVM classification wrong when class probabilities are included?

Why are probabilities and response in ksvm in R not consistent?

[R] Inconsistent results between caret+kernlab versions