Scikit-learn Ridge 分类器:提取类别概率

14 投票
4 回答
12120 浏览
提问于 2025-04-17 23:09

我现在正在使用sklearn的Ridge分类器,并想把这个分类器和其他库里的分类器组合在一起。为了做到这一点,理想的情况是能够提取出某个输入属于每个类别的概率。目前,我是把类别和model.decision_function(x)的输出配对在一起,但这样得到的是距离超平面的值,而不是直接的概率。这些距离值大约在-1到1之间变化。

distances = dict(zip(clf.classes_, clf.decision_function(x)[0]))  

我该如何把这些距离转换成更具体的概率值(一系列正值,且总和为1)呢?我希望能找到类似于clf.predict_proba()的功能,这个功能在sklearn的SVC中有实现。

4 个回答

0

这个版本是基于 Emanuel的回答。它不管目标是二分类还是多分类都适用。它引入了一个叫做温度的超参数,这个参数可以在应用softmax函数之前调整logits的大小。

class RidgeClassifierWithProba(RidgeClassifier):
    def __init__(self, temperature=1.0, **kwargs):
        super().__init__(**kwargs)
        self.temperature = temperature

    def predict_proba(self, X):
        d = self.decision_function(X) / self.temperature
        if len(d.shape) == 1:
            d = np.c_[-d, d]
        return softmax(d)
3

这里提供的解决方案对我来说没用。我认为softmax函数是正确的解决办法,所以我在RidgeClassifierCV类中添加了一个predict_proba方法,这个方法和LogisticRegressionCV中的类似。

from sklearn.utils.extmath import softmax
class RidgeClassifierCVwithProba(RidgeClassifierCV):
    def predict_proba(self, X):
        d = self.decision_function(X)
        d_2d = np.c_[-d, d]
        return softmax(d_2d)
12

看一下predict的源代码,你会发现decision_function其实是实际类别概率的对数变换。简单来说,如果decision_function的值是f,那么类别1的概率可以用公式exp(f) / (1 + exp(f))来计算。这在sklearn的源代码中有一个对应的检查:

    scores = self.decision_function(X)
    if len(scores.shape) == 1:
        indices = (scores > 0).astype(np.int)
    else:
        indices = scores.argmax(axis=1)
    return self.classes_[indices]

从这个检查中可以看出,如果decision_function的值大于零,就预测为类别1;否则就预测为类别0。这是一种经典的对数几率方法。

所以,你需要把decision_function转换成类似这样的东西:

d = clf.decision_function(x)[0]
probs = numpy.exp(d) / (1 + numpy.exp(d))

然后再进行适当的zip等操作。

16

进一步的研究让我们使用了softmax函数。

d = clf.decision_function(x)[0]
probs = np.exp(d) / np.sum(np.exp(d))

这个函数可以确保结果在0到1之间,并且所有结果加起来等于1。

撰写回答