将LinearSVC的决策函数转换为概率(Scikit-learn Python)
我在用scikit learn里的线性支持向量机(LinearSVC)来解决二分类问题。我知道LinearSVC可以给我预测的标签和决策分数,但我想要的是概率估计(也就是对标签的信心)。我想继续使用LinearSVC,因为它比sklearn.svm.SVC(线性核)要快。用逻辑函数把决策分数转换成概率,这样做合理吗?
import sklearn.svm as suppmach
# Fit model:
svmmodel=suppmach.LinearSVC(penalty='l1',C=1)
predicted_test= svmmodel.predict(x_test)
predicted_test_scores= svmmodel.decision_function(x_test)
我想看看用[1 / (1 + exp(-x))]来获取概率估计是否有道理,其中x是决策分数。
另外,还有没有其他分类器的选择,可以高效地做到这一点?
谢谢。
5 个回答
就像是对支持向量机(SVM)进行二分类的扩展一样,你可以看看 SGDClassifier,它默认使用梯度下降法来进行SVM的运算。为了估算二分类的概率,它使用了一种修改过的 Huber损失 方法。
(clip(decision_function(X), -1, 1) + 1) / 2)
一个例子可能是这样的:
from sklearn.linear_model import SGDClassifier
svm = SGDClassifier(loss="modified_huber")
svm.fit(X_train, y_train)
proba = svm.predict_proba(X_test)
如果你真正想要的是一种信心的衡量,而不是实际的概率,你可以使用方法 LinearSVC.decision_function()
。详细信息可以查看文档。
如果你想要更快的速度,那就直接把SVM换成sklearn.linear_model.LogisticRegression
。这个方法使用的训练算法和LinearSVC
是一样的,只不过它用的是对数损失,而不是铰链损失。
使用[1 / (1 + exp(-x))]可以得到概率值,严格来说就是介于零和一之间的数字,但这些数字并不符合任何合理的概率模型。
scikit-learn 提供了一个叫做 CalibratedClassifierCV 的工具,可以用来解决这个问题:它可以为 LinearSVC 或任何其他实现了 decision_function 方法的分类器添加概率输出。
svm = LinearSVC()
clf = CalibratedClassifierCV(svm)
clf.fit(X_train, y_train)
y_proba = clf.predict_proba(X_test)
用户指南中有一个很不错的 部分 来介绍这个内容。默认情况下,CalibratedClassifierCV+LinearSVC 会使用 Platt 缩放,但它也提供其他选项(比如等温回归方法),而且不仅限于 SVM 分类器。
我查看了sklearn.svm.*系列中的一些API。这些模型,比如:
- sklearn.svm.SVC
- sklearn.svm.NuSVC
- sklearn.svm.SVR
- sklearn.svm.NuSVR
它们都有一个共同的接口,这个接口提供了一个
probability: boolean, optional (default=False)
参数给模型。如果这个参数设置为True,libsvm会在SVM的输出上训练一个概率转换模型,这个过程是基于Platt Scaling的思想。这个转换的形式类似于你提到的逻辑函数,不过在后处理步骤中会学习到两个特定的常数A
和B
。想了解更多细节,可以查看这个stackoverflow的帖子。
其实我不知道为什么这个后处理步骤在LinearSVC中不可用。否则,你只需要调用predict_proba(X)
就能得到概率估计。
当然,如果你只是简单地应用一个逻辑变换,它的效果不会像使用像Platt Scaling这样的校准方法那么好。如果你能理解Platt Scaling背后的算法,或许你可以自己写一个,或者为scikit-learn的SVM系列做贡献。:) 另外,欢迎使用上面提到的四种支持predict_proba
的SVM变体。