Sklearn:在GridSearchCV中评估OneVsRestClassifier的每个分类器的性能

2024-05-04 22:43:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我用OneVsRestClassifierSVC处理多标签分类

from sklearn.datasets import make_multilabel_classification
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
from sklearn.grid_search import GridSearchCV

L=3
X, y = make_multilabel_classification(n_classes=L, n_labels=2,
                                  allow_unlabeled=True,
                                  random_state=1, return_indicator=True)    
model_to_set = OneVsRestClassifier(SVC())

parameters = {
    "estimator__C": [1,2,4,8],
    "estimator__kernel": ["poly","rbf"],
    "estimator__degree":[1, 2, 3, 4],
}

model_tunning = GridSearchCV(model_to_set, param_grid=parameters,
                             scoring='f1')

model_tunning.fit(X, y)

print model_tunning.best_score_
print model_tunning.best_params_

#0.855175822314
#{'estimator__kernel': 'poly', 'estimator__C': 1, 'estimator__degree': 3}

第一个问题

数字0.85代表什么?它是L分类器中最好的还是平均的?同样,参数集是否代表L分类器中的最佳记分器?在

第二个问题

基于这样一个事实,如果我是对的,OneVsRestClassifier实际上为每个标签构建了L分类器,人们可以期望访问或观察每个标签的性能。但是,在上面的例子中,如何从GridSearchCV对象获得{}分数?在

编辑

为了简化问题并帮助自己了解更多关于OneVsRestClassifier的信息,在优化模型之前

^{pr2}$

可以证明gp.T[0]==fpgp.T[1]==sp和{}。所以“全局”预测只是“顺序”的L个别预测,第二个问题就解决了。在

但我仍然感到困惑的是,如果一个元分类器OneVsRestClassifier包含L分类器,GridSearchCV对于一个拥有L分类器的元分类器OneVsRestClassifier如何只返回一个与4*2*4组参数集之一相对应的最佳分数?在

如有任何评论,我们将不胜感激。在


Tags: fromimportmakemodel分类器标签sklearngrid
3条回答

至于您的第二个问题,您可能希望将GridSearchCVscikit-multilearn的{a2}分类器一起使用。与OneVsRestClassifier一样,二进制相关性创建L个单标签分类器,每个标签一个。对于每个标签,如果存在标签,则培训数据为1;如果不存在,则为0。最佳选择的分类器集是BinaryRelevance类实例,它位于GridSearchCVbest_estimator_属性中。用于预测概率的浮动使用predict_proba对象的predict_proba方法。一个例子可以在scikit-multilearn docs for model selection中找到。在

在您的情况下,我将运行以下代码:

from skmultilearn.problem_transform import BinaryRelevance
from sklearn.model_selection import GridSearchCV
import sklearn.metrics

model_to_set = BinaryRelevance(SVC())

parameters = {
    "classifier__estimator__C": [1,2,4,8],
    "classifier__estimator__kernel": ["poly","rbf"],
    "classifier__estimator__degree":[1, 2, 3, 4],
}

model_tunning = GridSearchCV(model_to_set, param_grid=parameters,
                             scoring='f1')

model_tunning.fit(X, y)

# for some X_test testing set
predictions = model_tunning.best_estimator_.predict(X_test)

# average=None gives per label score
metrics.f1_score(y_test, predictions, average = None) 

请注意,有比二进制相关性更好的多标签分类方法:)您可以在madjarov's comparisonmy recent paper中找到它们。在

受到@Olologin的答案的启发,我意识到0.85是通过L预测得到的f1分数(在本例中)的最佳加权平均值。在下面的代码中,我使用f1分数的宏平均值通过内部测试评估模型:

# Case A, inspect F1 score using the meta-classifier
F_A = f1_score(y, model_tunning.best_estimator_.predict(X), average='macro')

# Case B, inspect F1 scores of each label (binary task) and collect them by macro average
F_B = []
for label, clc in zip(y.T, model_tunning.best_estimator_.estimators_):
    F_B.append(f1_score(label, clf.predict(X)))
F_B = mean(F_B)

F_A==F_B # True

因此,这意味着GridSearchCV应用4*2*4组参数中的一组来构建元分类器,而元分类器又使用L分类器对每个标签进行预测。结果将是L标签的Lf1分数,每个分数都是一个二进制任务的执行。最后,通过取Lf1分数的平均值(宏或加权平均值,由f1分数中的参数指定)得到单个分数。在

{*4}在这个例子中,选择哪个参数的平均值是。在

虽然使用包装器解决多标签问题很方便,但它只能在构建L分类器的相同参数下最大化f1平均分数。如果要单独优化每个标签的性能,似乎必须构建L分类器,而不使用包装器。在

GridSearchCV从您的参数值创建网格,它将您的OneVsRestClassifier作为原子分类器进行计算(即GridSearchCV不知道这个元分类器中有什么)

首先:0.85是参数OneVsRestClassifier的所有可能组合(在您的例子中是16个组合,4*2*4)中的最佳得分,这意味着GridSearchCV对16个可能的OneVsRestClassifier求值,每个可能的OneVsRestClassifier都包含LSVC。一个{}内的所有L分类器都是相同的参数的值(但每个参数都在学习如何从L可能中识别自己的类)

即从

{OneVsRestClassifier(SVC(C=1, kernel="poly", degree=1)),
 OneVsRestClassifier(SVC(C=1, kernel="poly", degree=2)),
 ...,
 OneVsRestClassifier(SVC(C=8, kernel="rbf", degree=3)),
 OneVsRestClassifier(SVC(C=8, kernel="rbf", degree=4))}

它选择一个得分最高的。在

model_tunning.best_params_这里表示OneVsRestClassifier(SVC())的参数,它将使用这些参数来实现model_tunning.best_score_。 您可以从model_tunning.best_estimator_属性得到最好的OneVsRestClassifier。在

第二:没有现成的代码可以从OneVsRestClassifier获得L分类器的单独分数,但是您可以查看OneVsRestClassifier.fit方法的实现,或者采用以下方法(应该可以:):

^{pr2}$

相关问题 更多 >