使用R语言中的Caret包进行SVM建模时,classProbs=TRUE参数导致不同结果

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

我在R中使用了caret包,并采用了留一法交叉验证(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))

为了提取预测概率,我需要在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的预测类别,在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后,会训练一个额外的S形函数的参数,将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,将构建一个用于计算类别概率的模型,或者在回归情况下,计算拟合在残差上的拉普拉斯分布的缩放参数。拟合是在通过对训练数据进行3折交叉验证创建的输出数据上完成的。详细信息请参见参考文献。(默认值:FALSE)

参考的详细信息:

在分类中,当prob.model为TRUE时,会对数据进行3折交叉验证,并对结果决策值f拟合一个S形函数。

显然,当需要后验概率时,分类模型会发生一些非常具体的变化。这与仅输出决策值是不同的。

由此可以推导出,根据S形函数的拟合,一些决策值可能会与在没有prob.modelprob.model = FALSE)的情况下运行[kernlab::ksvm]时不同,这就是你在发布的示例中观察到的现象。

如果有两个以上的类别,情况会变得更加复杂。

进一步阅读:

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

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注