【问题标题】:Converting LinearSVC's decision function to probabilities (Scikit learn python )将 LinearSVC 的决策函数转换为概率(Scikit learn python)
【发布时间】:2023-04-07 13:40:01
【问题描述】:

我使用来自 scikit learn (LinearSVC) 的线性 SVM 来解决二元分类问题。我知道 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 是决策分数。

或者,我可以使用分类器的其他选项来有效地做到这一点吗?

谢谢。

【问题讨论】:

    标签: python machine-learning scikit-learn svm


    【解决方案1】:

    我查看了 sklearn.svm.* 系列中的 api。以下所有模型,例如,

    • sklearn.svm.SVC
    • sklearn.svm.NuSVC
    • sklearn.svm.SVR
    • sklearn.svm.NuSVR

    有一个共同的interface 提供一个

    probability: boolean, optional (default=False) 
    

    模型的参数。如果此参数设置为 True,libsvm 将根据 Platt Scaling 的思想在 SVM 的输出之上训练概率转换模型。正如您所指出的,转换的形式类似于逻辑函数,但是在后处理步骤中学习了两个特定常量 AB。另请参阅此stackoverflow 帖子了解更多详情。

    我实际上不知道为什么此后处理不适用于 LinearSVC。否则,您只需致电predict_proba(X) 即可获得概率估计。

    当然,如果您只是应用一个简单的逻辑变换,它的性能将不如 Platt Scaling 这样的校准方法。如果你能理解 platt scaling 的下划线算法,或许你可以自己编写或为 scikit-learn svm 家族做出贡献。 :) 也可以随意使用上述四种支持predict_proba 的 SVM 变体。

    【讨论】:

    • 感谢@greeness 的回复。你上面所说的一切都是完全有道理的,我已经接受了它作为答案。然而,我没有使用任何其他分类器的原因是因为它们的速度通常远低于 sklearn.svm.LinearSVC。我会继续寻找一段时间,如果我发现了什么会在这里更新..
    • 它不可用,因为它没有内置到实现LinearSVC的Liblinear中,还因为LogisticRegression已经可用(尽管线性SVM + Platt缩放可能比直接LR有一些好处,我从来没有尝试过)。 SVC 中的 Platt 缩放来自 LibSVM。
    • 另一个可能的问题是使用 LinearSVC 允许选择与默认“l2”不同的惩罚。 SVC 不允许这样做,因为我猜 LibSVM 不允许这样做。
    • 我同时使用了SVC(kernel='linear', **kwargs)CalibratedClassifier(LinearSVC(**kwargs)),但我得到了不同的结果...
    【解决方案2】:

    如果您想要速度,那么只需替换 SVM 为sklearn.linear_model.LogisticRegression。它使用与LinearSVC 完全相同的训练算法,但使用对数损失而不是铰链损失。

    使用 [1 / (1 + exp(-x))] 将产生正式意义上的概率(零到一之间的数字),但它们不会遵守任何合理的概率模型。

    【讨论】:

    • 这是有道理的。感谢您的澄清
    • 这个应该是真正的答案。我用 sklearn.linear_model.LogisticRegression 替换了我的 sklearn.svm.SVC,不仅得到了相似的 ROC 曲线,而且我的数据集的时间差异如此之大(秒与小时),甚至不值得花时间。值得注意的是,您可以将求解器指定为“liblinear”,这实际上会使其与 LinearSVC 完全相同。
    • 等式 [1 / (1 + exp(-x))] 中的 x 值是多少?
    • 我不认为这是使用 SVM 获得概率的合适解决方案,正如 Fred 所指出的那样。 LR 旨在通过逻辑函数对独立信号进行概率估计。 SVM 旨在提供更好的准确性并尝试不过度拟合,但通过铰链函数获得的概率估计不太准确。它惩罚错误的预测。读者,请理解权衡并选择最适合您的学习目标的函数。我个人将使用 LinearSVC+CalibratedClassifierCV。
    • @thefourtheye:LinearSVC 声明:“类似于带有参数 kernel='linear' 的 SVC,但根据 liblinear 而不是 libsvm 实现,因此它在选择惩罚和损失函数和应该更好地扩展到大量样本。”因此,如果您像 OP 那样使用 LinearSVC,您将使用 liblinear(就像您的 LogisticRegression 一样),而且速度也会很快。所以它不是让它快速的方法:你使用了错误的实现后端。
    【解决方案3】:

    scikit-learn 提供了CalibratedClassifierCV 可以用来解决这个问题:它允许将概率输出添加到LinearSVC 或任何其他实现decision_function 方法的分类器:

     svm = LinearSVC()
     clf = CalibratedClassifierCV(svm) 
     clf.fit(X_train, y_train)
     y_proba = clf.predict_proba(X_test)
    

    用户指南上有一个很好的section。默认情况下,CalibratedClassifierCV+LinearSVC 会为您提供 Platt 缩放,但它也提供其他选项(等渗回归方法),并且不限于 SVM 分类器。

    【讨论】:

    • 知道如何在网格搜索中使用它吗?尝试设置参数,例如base_estimator__CGridSearchCV 不接受。
    • base_estimator__C 看起来正确。我建议提供一个完整的示例并打开一个新的 SO 问题。
    • 不适合svm 当我适合clf 时会导致我出错。我必须训练两者。我认为没有什么改变。对吗?
    • 天哪,这真是太快了(在我的情况下性能相似)
    【解决方案4】:

    如果您真正想要的是置信度而不是实际概率,您可以使用LinearSVC.decision_function() 方法。请参阅documentation

    【讨论】:

      猜你喜欢
      • 2018-04-25
      • 2021-09-28
      • 2018-12-01
      • 2017-12-30
      • 2015-10-25
      • 2020-09-25
      • 1970-01-01
      • 2016-05-14
      相关资源
      最近更新 更多