Scikit-learn Ridge 分类器:提取类别概率
我现在正在使用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 个回答
这个版本是基于 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)
这里提供的解决方案对我来说没用。我认为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)
看一下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
等操作。
进一步的研究让我们使用了softmax函数。
d = clf.decision_function(x)[0]
probs = np.exp(d) / np.sum(np.exp(d))
这个函数可以确保结果在0到1之间,并且所有结果加起来等于1。