当classProbs = TRUE

问题描述

当我尝试使用支持向量机SVM提取预测概率时,出现了以下问题。通常,分类算法的概率截止值为0.5。但是我需要分析SVM机器学习算法的准确性随概率截止的变化。

我在caret中使用了R程序包,并保留了一个交叉验证(LOOCV)

首先,我在不提取类概率的情况下拟合了常规svm模型。因此,它将仅存储预测的类标签

数据源: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))

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

set.seed(123)
fitControl2 <- trainControl( method = "LOOCV",classprobs = T)
diabetes$Outcome=factor(diabetes$Outcome)
modelFitlassocvintm2 <- train(make.names(Outcome) ~ Pregnancies+BloodPressure+glucose +
                                BMI+DiabetesPedigreeFunction +Age,trControl = fitControl2,.C=9.63979626))

modelFitlassocvintm1modelFitlassocvintm2的唯一区别是在classprobs = T中包含了trainControl

如果我比较modelFitlassocvintm1modelFitlassocvintm2的预测类别,则在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的预测类别中会有差异。而且我也发现svm使用了不同的数据集也有类似的差异。

这可能是什么原因?难道我们相信svm的预测概率吗?通常,svm将对象分类为-1或1,具体取决于对象相对于超平面所处的一侧。因此,依靠svm的预测概率不是一件好事吗?

解决方法

正如desertnaut的评论中所述,SVM不是概率分类器;它是概率分类器。他们实际上并没有产生概率。

创建概率的一种方法是直接使用logit链接函数和规则化的最大似然评分来训练内核分类器。但是,以最大似然分数进行训练将产生非稀疏内核机器。取而代之的是,在训练SVM之后,对另一个Sigmoid函数的参数进行训练,以将SVM输出映射为概率。参考文件:Probabilistic Outputs for Support Vector Machines and Comparisons to Regularized Likelihood Methods

Caret method = "svmRadialSigma"在内部kernlab::ksvm中使用自变量kernel = "rbfdot"。为了使此函数创建概率,需要参数prob.model = TRUE。通过此功能的帮助:

prob.model如果设置为TRUE,则构建用于计算类的模型 概率或回归的情况下,计算比例 残差拟合的拉普拉斯分布的参数。 拟合完成通过执行三折创建的输出数据 对训练数据进行交叉验证。有关详细信息,请参见参考。 (默认:FALSE)

参考的详细信息:

在分类中,当prob.model为TRUE时,三折交叉验证为 在数据上执行S型功能 最终的决策值f。

很明显,当需要后验概率时,分类模型会发生非常特定的事情。与仅输出决策值相比,这是不同的。

由此可以得出,取决于S形函数,一些 决策值可能与不运行kernlab::ksvmprob.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