如何在Pipeline中使用OneVsRestClassifier嵌套的估计器进行网格搜索

我在使用GridSearchCV进行模型选择和超参数调优。从初步实验来看,使用rbf核的SVC表现最佳。但问题是它的速度太慢(样本量20万+)。使用OneVsRestClassifier可以并行化SVC(通过n_jobs参数)。然而,当我使用Pipeline同时测试多个估计器时,GridSearchCV对这种嵌套的估计器不起作用。

pipe = Pipeline([('clf', SVC())]) # 占位估计器# 候选学习算法及其超参数search_space = [{'clf': [OneVsRestClassifier(SVC(tol=0.1, gamma='scale', probability=True), n_jobs=-1)],                 'clf__kernel': ['rbf', 'linear'],                 'clf__C': [1, 10, 100]},                {'clf': [LogisticRegression(tol=0.1, penalty='l1', solver='saga', multi_class='multinomial', n_jobs=8)],                  'clf__C': [1, 10, 100]},                {'clf': [RandomForestClassifier(n_jobs=8)],                 'clf__n_estimators': [50, 100, 200, 300, 400],                 'clf__max_depth': [10, 20, 30],                 'clf__min_samples_leaf': [1, 2, 4],                 'clf__min_samples_split': [2, 5, 10]},                {'clf': [MultinomialNB()],                 'clf__alpha': [0.1, 0.5, 1]}]gs = GridSearchCV(pipe, search_space, cv=skf, scoring='accuracy', verbose=10)

我遇到了错误

Invalid Parameter __kernel

但根据GridSearch for an estimator inside a OneVsRestClassifier,这种方法应该可行。我认为是Pipeline搞乱了,因为它基本上在OneVsRestClassifier之上又加了一层。如何对这种嵌套的估计器进行gridsearchcv呢?


回答:

目前,Pipeline在OneVsRestClassifier中寻找参数kernel,找不到(不出所料,因为该模块没有此参数),并引发错误。由于您实际上想要的是SVC的参数kernel(以及后续的C),您应该深入一层:将search_space的前三个条目更改为:

{'clf': [OneVsRestClassifier(SVC(tol=0.1, gamma='scale', probability=True), n_jobs=-1], 'clf__estimator__kernel': ['rbf', 'linear'], 'clf__estimator__C': [1, 10, 100]}

这样应该就没问题了。

然而,无论错误如何,您使用这种方法的理由:

问题在于它速度太慢(样本量20万+)。使用OneVsRestClassifier可以并行化SVC(通过n_jobs参数)。

是不正确的。OneVsRestClassifier会并行化拟合n_classes个不同的SVC估计器,而不是SVC本身。实际上,您试图通过包装其他东西(这里是OneVsRestClassifier)来避免一个瓶颈(SVC),结果却发现自己又遇到了瓶颈(不出所料)。

我们可以通过一些虚拟数据的时间测量来证明这一点——让我们尝试一个相对现实的数据集,1万个样本,5个特征,3个类别:

from sklearn.multiclass import OneVsRestClassifierfrom sklearn.svm import SVCfrom sklearn.datasets import make_classificationX, y = make_classification(n_samples = 10000, n_features=5, n_redundant=0, n_informative=5,                             n_classes = 3, n_clusters_per_class=1, random_state=42)%timeit for x in range(10): SVC().fit(X,y)# 1 loop, best of 3: 7.72 s per loop%timeit for x in range(10): OneVsRestClassifier(SVC()).fit(X, y)# 1 loop, best of 3: 21.1 s per loop

这是您的基准差异;现在设置n_jobs=-1会有所帮助:

%timeit for x in range(10): OneVsRestClassifier(SVC(), n_jobs=-1).fit(X, y)# 1 loop, best of 3: 19 s per loop

但不出所料,这只是相对于未并行化的OneVsRestClassifier而言,而不是相对于SVC本身。

随着特征和类别的增加,差异会变得更糟;在不达到您的完整案例的情况下,这里是10个特征和5个类别的情况(样本数相同,1万):

X1, y1 = make_classification(n_samples = 10000, n_features=10, n_redundant=0, n_informative=10,                             n_classes = 5, n_clusters_per_class=1, random_state=42)%timeit for x in range(10): SVC().fit(X1,y1)# 1 loop, best of 3: 10.3 s per loop%timeit for x in range(10): OneVsRestClassifier(SVC()).fit(X1, y1)# 1 loop, best of 3: 30.7 s per loop%timeit for x in range(10): OneVsRestClassifier(SVC(), n_jobs=-1).fit(X1, y1)# 1 loop, best of 3: 24.9 s per loop

因此,我强烈建议您重新考虑这里的方法(和目标)。

(所有时间测量都在Google Colab上进行)。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注