在OneVsRestClassifier中对一个estimator进行GridSearch

49
我希望在SVC模型中执行GridSearchCV,但使用一对多策略。对于后者,我可以只需执行以下操作:
model_to_set = OneVsRestClassifier(SVC(kernel="poly"))

我的问题与参数有关。假设我想尝试以下值:

parameters = {"C":[1,2,4,8], "kernel":["poly","rbf"],"degree":[1,2,3,4]}

为了执行GridSearchCV,我应该像这样做:

 cv_generator = StratifiedKFold(y, k=10)
 model_tunning = GridSearchCV(model_to_set, param_grid=parameters, score_func=f1_score, n_jobs=1, cv=cv_generator)

然而,当我执行它时,我收到:

Traceback (most recent call last):
  File "/.../main.py", line 66, in <module>
    argclass_sys.set_model_parameters(model_name="SVC", verbose=3, file_path=PATH_ROOT_MODELS)
  File "/.../base.py", line 187, in set_model_parameters
    model_tunning.fit(self.feature_encoder.transform(self.train_feats), self.label_encoder.transform(self.train_labels))
  File "/usr/local/lib/python2.7/dist-packages/sklearn/grid_search.py", line 354, in fit
    return self._fit(X, y)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/grid_search.py", line 392, in _fit
    for clf_params in grid for train, test in cv)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/externals/joblib/parallel.py", line 473, in __call__
    self.dispatch(function, args, kwargs)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/externals/joblib/parallel.py", line 296, in dispatch
    job = ImmediateApply(func, args, kwargs)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/externals/joblib/parallel.py", line 124, in __init__
    self.results = func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/grid_search.py", line 85, in fit_grid_point
    clf.set_params(**clf_params)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/base.py", line 241, in set_params
    % (key, self.__class__.__name__))
ValueError: Invalid parameter kernel for estimator OneVsRestClassifier
基本上,由于SVC在OneVsRestClassifier中,并且这是我发送到GridSearchCV的估算器,因此无法访问SVC的参数。
为了实现我想要的功能,我看到两种解决方案:
1.创建SVC时,以某种方式告诉它不要使用一对一策略,而要使用一对所有策略。
2.以某种方式指示GridSearchCV参数对应于OneVsRestClassifier内部的估算器。
我还没有找到执行任何上述替代方案的方法。 您知道是否有一种方法可以执行其中任何一种方法吗? 或者您可以建议另一种获得相同结果的方法吗?
谢谢!
3个回答

81

当您使用嵌套估计器进行网格搜索时,可以使用__作为分隔符来限定参数的范围。在这种情况下,SVC模型将作为名为estimator的属性存储在OneVsRestClassifier模型内部:

from sklearn.datasets import load_iris
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
from sklearn.grid_search import GridSearchCV
from sklearn.metrics import f1_score

iris = load_iris()

model_to_set = OneVsRestClassifier(SVC(kernel="poly"))

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,
                             score_func=f1_score)

model_tunning.fit(iris.data, iris.target)

print model_tunning.best_score_
print model_tunning.best_params_

这将产生:

0.973290762737
{'estimator__kernel': 'poly', 'estimator__C': 1, 'estimator__degree': 2}

嗨,ogrisel,使用SVC时是否需要使用OneVsRestClassifer?SVC本身不能处理多个目标值吗? - Baskaya
2
OneVsRestClassifer可以用于添加多标签支持。SVC默认仅支持多类别。此外,SVC的本地多类别实现基于一种略有不同的OvO方案。 - ogrisel
2
@ogrisel 是否可以在多标签分类的情况下(即如果X,y由make_multilabel_classification创建)显示每个单独类别的最佳分数?在这个例子中,0.97的最佳分数代表什么,是由OneVsRestClassifier中的一个分类器评分还是三个分类器的平均值(因为鸢尾花数据集中有三个类别)? - Francis
只是补充一下,如果你的onevsrest也是管道的一部分,你只需要在管道中加入给onevsrest分类器命名的名称。 - Jordan Mackie
被接受的代码为每个模型选择相同的模型参数,这不是最优的。你应该使用grid_search来确定你正在尝试预测的每个类别的最佳模型。不幸的是,这在sklearn中没有实现,因此你需要使用一个丑陋的循环。 - Philipp Schwarz

6

对于Python 3,应使用以下代码:

from sklearn.datasets import load_iris
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import f1_score

iris = load_iris()

model_to_set = OneVsRestClassifier(SVC(kernel="poly"))

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_weighted')

model_tunning.fit(iris.data, iris.target)

print(model_tunning.best_score_)
print(model_tunning.best_params_)

1
对于那些想知道“有什么变化”的人,唯一不同的是在实例化GridSearchCV时指定要使用的度量方式的方法。 - onofricamila

5
param_grid  = {"estimator__alpha": [10**-5, 10**-3, 10**-1, 10**1, 10**2]}

clf = OneVsRestClassifier(SGDClassifier(loss='log',penalty='l1'))

model = GridSearchCV(clf,param_grid, scoring = 'f1_micro', cv=2,n_jobs=-1)

model.fit(x_train_multilabel, y_train)

1
应该添加一些解释以提供更好的答案。 - Shihe Zhang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接