【发布时间】:2015-07-14 05:07:00
【问题描述】:
我有一个使用 sklearn 中的 SVC 类的程序。真的,我正在使用使用 SVC 类的 OneVsRestClassifier 类。我的问题是 predict_proba() 方法有时会返回一个太短的向量。这是因为 classes_ 属性缺少一个类,当训练期间标签不存在时会发生这种情况。
考虑以下示例(代码如下所示)。假设所有可能的类是 1、2、3 和 4。现在假设训练数据恰好不包含任何标记为类 3 的数据。这很好,除非我调用 predict_proba() 我想要一个长度为 4 的向量。 ,我得到一个长度为 3 的向量。也就是说,predict_proba() 返回 [p(1) p(2) p(4)],但我想要 [p(1) p(2) p(3) p(4 )],其中 p(3) = 0。
我猜 clf.classes_ 是由训练期间看到的标签隐式定义的,在这种情况下是不完整的。有什么方法可以显式设置可能的类标签?我知道一个简单的解决方法是获取 predict_proba() 输出并手动创建我想要的数组。但是,这很不方便,可能会大大降低我的程序速度。
# Python 2.7.6
from sklearn.svm import SVC
from sklearn.multiclass import OneVsRestClassifier
import numpy as np
X_train = [[1], [2], [4]] * 10
y = [1, 2, 4] * 10
X_test = [[1]]
clf = OneVsRestClassifier(SVC(probability=True, kernel="linear"))
clf.fit(X_train, y)
# calling predict_proba() gives: [p(1) p(2) p(4)]
# I want: [p(1) p(2) p(3) p(4)], where p(3) = 0
print clf.predict_proba(X_test)
我想到的解决方法是创建一个新的概率列表,并通过多个 append() 调用一次构建一个元素(参见下面的代码)。与让 predict_proba() 自动返回我想要的东西相比,这似乎会很慢。我还不知道它是否会显着减慢我的程序,因为我还没有尝试过。无论如何,我想知道是否有更好的方法。
def workAround(probs, classes_, all_classes):
"""
probs: list of probabilities, output of predict_proba (but 1D)
classes_: clf.classes_
all_classes: all possible classes; superset of classes_
"""
all_probs = []
i = 0 # index into probs and classes_
for cls in all_classes:
if cls == classes_[i]:
all_probs.append(probs[i])
i += 1
else:
all_probs.append(0.0)
return np.asarray(all_probs)
【问题讨论】:
-
如果您的任务是多类而不是多标签,则不需要使用 OneVsRestClassifier。为什么您认为在回报中添加额外的列可能会减慢您的程序?没有自动的方法,我认为我们决定在某个时候不添加一个,因为它会为所有分类器添加一个额外的参数并使 API 混乱。
-
我认为这会很慢,因为我会复制每次调用 predict_proba() 的概率。必须将新列插入正确的位置以保持类的排序顺序。我将摆脱 OneVsRestClassifier 并仅使用 SVC,谢谢。
-
好吧,如果 scikit-learn 会为你做这件事,它也需要制作副本;)与进行预测相比,复制数组的成本可以忽略不计。您可以从 classes_ 属性和可能 np.searchsorted 中获取需要输入您的类的位置
标签: python scikit-learn classification svm