Python 我可以为sklearn SVM显式设置可能的类列表吗?
我有一个使用sklearn中SVC类的程序。实际上,我使用的是使用SVC类的OneVsRestClassifier类。我的问题是predict_proba()方法有时返回的向量太短。这是因为classes_u属性缺少一个类,这是在培训期间标签不存在时发生的 考虑以下示例(代码如下所示)。假设所有可能的类都是1、2、3和4。现在假设训练数据恰好不包含任何标有class 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 我可以为sklearn SVM显式设置可能的类列表吗?,python,scikit-learn,classification,svm,Python,Scikit Learn,Classification,Svm,我有一个使用sklearn中SVC类的程序。实际上,我使用的是使用SVC类的OneVsRestClassifier类。我的问题是predict_proba()方法有时返回的向量太短。这是因为classes_u属性缺少一个类,这是在培训期间标签不存在时发生的 考虑以下示例(代码如下所示)。假设所有可能的类都是1、2、3和4。现在假设训练数据恰好不包含任何标有class 3的数据。这很好,除非调用predict_proba()时需要长度为4的向量。相反,我得到一个长度为3的向量。也就是说,predi
# 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)
正如评论中所说,scikit learn没有提供显式设置可能的类标签的方法 我发现了你的解决方法:
import sklearn
import sklearn.svm
import numpy as np
np.random.seed(3) # for reproducibility
def predict_proba_ordered(probs, classes_, all_classes):
"""
probs: list of probabilities, output of predict_proba
classes_: clf.classes_
all_classes: all possible classes (superset of classes_)
"""
proba_ordered = np.zeros((probs.shape[0], all_classes.size), dtype=np.float)
sorter = np.argsort(all_classes) # http://stackoverflow.com/a/32191125/395857
idx = sorter[np.searchsorted(all_classes, classes_, sorter=sorter)]
proba_ordered[:, idx] = probs
return proba_ordered
# Prepare the data set
all_classes = np.array([1,2,3,4]) # explicitly set the possible class labels.
X_train = [[1], [2], [4]] * 3
print('X_train: {0}'.format(X_train))
y = [1, 2, 4] * 3 # Label 3 is missing.
print('y: {0}'.format(y))
X_test = [[1], [2], [3]]
print('X_test: {0}'.format(X_test))
# Train
clf = sklearn.svm.SVC(probability=True, kernel="linear")
clf.fit(X_train, y)
print('clf.classes_: {0}'.format(clf.classes_))
# Predict
probs = clf.predict_proba(X_test) #As label 3 isn't in train set, the probs' size is 3, not 4
proba_ordered = predict_proba_ordered(probs, clf.classes_, all_classes)
print('proba_ordered: {0}'.format(proba_ordered))
输出:
X_train: [[1], [2], [4], [1], [2], [4], [1], [2], [4]]
y: [1, 2, 4, 1, 2, 4, 1, 2, 4]
X_test: [[1], [2], [3]]
clf.classes_: [1 2 4]
proba_ordered: [[ 0.81499201 0.08640176 0. 0.09860622]
[ 0.21105955 0.63893181 0. 0.15000863]
[ 0.08965731 0.49640147 0. 0.41394122]]
请注意,您可以在
sklearn.metrics
中显式设置可能的类标签(例如,使用标签
参数:
labels : array
Integer array of labels.
例如:
# Score
y_pred = clf.predict(X_test)
y_true = np.array([1,2,3])
precision = sklearn.metrics.precision_score(y_true, y_pred, labels=all_classes, average=None)
print('precision: {0}'.format(precision))
recall = sklearn.metrics.recall_score(y_true, y_pred, labels=all_classes, average=None)
print('recall: {0}'.format(recall))
f1_score = sklearn.metrics.f1_score(y_true, y_pred, labels=all_classes, average=None)
print('f1_score: {0}'.format(f1_score))
请注意,到目前为止,您将。如果您的任务是多类而不是多标签的,您不需要使用OneVsRestClassifier。为什么您认为在返回中添加额外的列可能会减慢您的程序?没有自动的方法,我想我们决定在某个时候不添加一个列,因为它会在所有cl中添加额外的参数我认为这会很慢,因为我会复制每个调用的概率来预测_proba()。新列必须插入到正确的位置,以保留类的排序顺序。我将放弃OneVsRestClassifier,只使用SVC,谢谢。如果scikit learn可以为您完成这项工作,它也需要进行复制;),而且复制数组的成本与进行预测相比可以忽略不计。您可以从classes_uu属性和np.searchsorted属性中获得需要输入类的位置