7

我正在使用 和 处理多标签OneVsRestClassifier分类SVC

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为每个标签构建分类器,人们可以期望访问或观察每个标签的性能。但是,在上面的示例中,如何L从对象中获取分数GridSearchCV

编辑

为了简化问题并帮助自己更多地了解OneVsRestClassifier,在调整模型之前,

model_to_set.fit(X,y)
gp = model_to_set.predict(X) # the "global" prediction
fp = model_to_set.estimators_[0].predict(X) # the first-class prediction
sp = model_to_set.estimators_[1].predict(X) # the second-class prediction
tp = model_to_set.estimators_[2].predict(X) # the third-class prediction

可以证明gp.T[0]==fpgp.T[1]==spgp.T[2]==tp因此,“全局”预测只是“连续”的L个体预测,而第二个问题就解决了。

但是让我感到困惑的是,如果一个元分类器OneVsRestClassifier包含L分类器,那么GridSearchCV对于OneVsRestClassifier具有L

看到任何评论将不胜感激。

4

3 回答 3

5

GridSearchCV从你的参数值创建网格,它评估你OneVsRestClassifier的原子分类器(即GridSearchCV不知道这个元分类器里面有什么)

首先OneVsRestClassifier:0.85 是所有可能的参数组合(在您的情况下为 16 个组合,4*2*4)参数中的最佳分数("estimator__C", "estimator__kernel", "estimator__degree"),这意味着GridSearchCV评估 16 个(同样,仅在这种特殊情况下)可能OneVsRestClassifier的每个包含LSVC的。一个内部的所有 L 个分类器OneVsRestClassifier都具有相同的参数值(但每个分类器都在学习从 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_。您可以OneVsRestClassifiermodel_tunning.best_estimator_属性中获得最佳效果。

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

# Here X, y - your dataset
one_vs_rest = model_tunning.best_estimator_
yT = one_vs_rest.label_binarizer_.transform(y).toarray().T
# Iterate through all L classifiers
for classifier, is_ith_class in zip(one_vs_rest.estimators_, yT):
    print(classifier.score(X, is_ith_class))
于 2015-11-18T22:21:38.040 回答
4

受@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分类器对每个标签进行预测。结果将是标签的Lf1 分数L,每个分数都是二元任务的表现。最后,通过取 f1 分数的平均值(宏观或加权平均,由 f1_score 中的参数指定)获得单个L分数。

然后GridSearchCV在 4*2*4 组参数中选择最好的平均 f1 分数,在本例中为 0.85。

尽管使用包装器解决多标签问题很方便,但它只能使用用于构建L分类器的相同参数集来最大化平均 f1 分数。如果想分别优化每个标签的性能,似乎必须在L不使用包装器的情况下构建分类器。

于 2015-11-19T12:37:44.227 回答
3

至于您的第二个问题,您可能希望GridSearchCVscikit-multilearnBinaryRelevance分类器一起使用。与 类似OneVsRestClassifier,Binary Relevance 创建了 L 个单标签分类器,每个标签一个。对于每个标签,如果标签存在,则训练数据为 1,如果不存在,则为 0。最佳选择的分类器集是 的属性中的BinaryRelevance类实例。用于预测概率的浮点数使用对象的方法。模型选择的 scikit-multilearn 文档中可以找到一个示例。best_estimator_GridSearchCVpredict_probaBinaryRelevance

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

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 的比较我最近的论文中找到它们。

于 2017-02-13T22:38:21.103 回答