我正在处理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
分类器,人们可以期望访问或观察每个标签的性能。但是,在上面的示例中,如何从GridSearchCV
对象中获取L
分数?
编辑
为了简化问题并帮助自己更多地了解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]==fp
、gp.T[1]==sp
和gp.T[2]==tp
。因此,"全局"预测只是单个预测L
"顺序",第二个问题就解决了。
但是,如果一个元分类器OneVsRestClassifier
包含L
个分类器,GridSearchCV
怎么能只返回一个最佳分数,对应于 4*2*4 组参数之一,对于具有L
分类器的元分类器OneVsRestClassifier
?
如能看到任何评论,将不胜感激。
GridSearchCV
从参数值创建网格,它将OneVsRestClassifier
评估为原子分类器(即 GridSearchCV
不知道这个元分类器里面有什么(
第一:0.85 是参数("estimator__C", "estimator__kernel", "estimator__degree")
的所有可能组合(16 种组合,4*2*4(中OneVsRestClassifier
的最佳分数,这意味着GridSearchCV
评估 16 个(同样,仅在这种特殊情况下(可能的OneVsRestClassifier
每个都包含 L SVC
的。一个OneVsRestClassifier
中的所有 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
方法的实现,或者采取这个(应该:)工作(:
# 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))
受到@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
标签的 L
f1 分数,每个标签都是二进制任务的性能。最后,通过取L
f1分数的平均值(宏观或加权平均值,由f1_score中的参数指定(获得单个分数。
然后,GridSearchCV
在 4*2*4 参数集中选择最佳平均 f1 分数,在本例中为 0.85。
虽然将包装器用于多标签问题很方便,但它只能使用用于构建L
分类器的相同参数集来最大化平均 f1 分数。如果要单独优化每个标签的性能,似乎必须在不使用包装器的情况下构建L
分类器。
至于你的第二个问题,你可能想GridSearchCV
与scikit-multilearn的BinaryCorrelation分类器一起使用。像OneVsRestClassifier
一样,二进制相关性创建L单标签分类器,每个标签一个。对于每个标签,如果标签存在,则训练数据为 1,如果不存在,则训练数据为 0。选择最好的分类器集是 GridSearchCV
属性best_estimator_
中的BinaryRelevance
类实例。用于预测概率浮点数使用BinaryRelevance
对象的predict_proba
方法。可以在scikit-multilearn文档中找到一个模型选择示例。
在您的情况下,我将运行以下代码:
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的比较或我最近的论文中找到它们。