网格搜索预处理多个超参数和多个估计器
Posted
技术标签:
【中文标题】网格搜索预处理多个超参数和多个估计器【英文标题】:Grid search preprocess multiple hyperparameters and multiple estimators 【发布时间】:2021-03-19 05:49:04 【问题描述】:长期 R 用户,学习 Python。我正在尝试使用 GridSearch 为管道中的 PCA 步骤以及多个估计器尝试不同数量的组件。我认为下面的代码正在执行这些操作(使用GridSearch
文档和其他来源),但best_params_
的结果没有预处理参数和估计参数;而是打印'prep2__pcadtm__n_components': 3
,这向我表明他的代码没有按照我的想法进行。
MWE
## Dependencies
import seaborn as sns
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.compose import ColumnTransformer
from sklearn.neighbors import KNeighborsClassifier
from imblearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
## load data set
df = sns.load_dataset('mpg').drop(["name"], axis = 1).dropna()
## Factoize the outcome
factor = pd.factorize(df['origin'])
df.origin = factor[0]
definitions = factor[1]
outcome_order = definitions.tolist()
X = df.loc[:, ~df.columns.isin(['origin'])]
y = df.iloc[:,7].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20, random_state = 21)
scaler = StandardScaler()
pca = PCA(n_components = 2)
dtm_i = list(range(2, len(X_train.columns)))
dtm_i2 = list(range(0, len(X_train.columns)-2))
preprocess = ColumnTransformer(transformers=[('scaler', scaler, dtm_i)], remainder='passthrough')
preprocess2 = ColumnTransformer(transformers=[('pcadtm', pca, dtm_i2)], remainder='passthrough')
pipeline = Pipeline([
('prep', preprocess),
('prep2', preprocess2),
('clf', RandomForestClassifier())
])
search_space = [
'prep2__pcadtm__n_components': [2, 3]
,
'clf': [RandomForestClassifier()],
'clf__max_depth': [5, 15]
,
'clf': [KNeighborsClassifier()],
'clf__n_neighbors' : [2, 3]
]
# Create grid search
grid_imba = GridSearchCV(
estimator = pipeline,
param_grid = search_space,
scoring = 'accuracy',
cv = 3,
return_train_score = True
)
## Fit the model using all the different estimators
grid_imba.fit(X_train, y_train);
## Extract best
best_params = grid_imba.best_params_
print(best_params)
##'prep2__pcadtm__n_components': 3
我认为GridSearch
会生成 2 个和 3 个 PCA 组件数据集,然后使用估算器将其传递到下一步。反过来,两个 PCA 输出都将使用随机森林进行测试,然后是 KNN [每个都有 2 个超参数。含义 2(2 和 3 个组件的 PCA 数据集)X 2(估计器)X 2(每个估计器的超参数)= 8 个正在测试的模型]。我认为我不正确。
最后,为了提高效率,最好不要在每次尝试新的估算器时都计算 prep2
步骤。
【问题讨论】:
【参考方案1】:确实,当param_grid
是字典列表时,搜索发生在每个字典生成的网格的联合 上。所以你的代码实际上检查了六个超参数组合:
你需要类似的东西
search_space =
'prep2__pcadtm__n_components': [2, 3],
'clf': [RandomForestClassifier(max_depth=5),
RandomForestClassifier(max_depth=15),
KNeighborsClassifier(n_neighbors=2),
KNeighborsClassifier(n_neighbors=3)],
根据您的实际需求,列出每个不同模型所需的所有超参数组合当然可能会变得笨拙。在这种情况下,嵌套搜索可能是最简单的:
rf_gs = GridSearchCV(
estimator=RandomForestClassifier(),
param_grid='max_depth': [5, 15],
)
kn_gs = GridSearchCV(
estimator=KNeighborsClassifier(),
param_grid='n_neighbors': [2, 3],
)
pipeline = Pipeline([
('prep', preprocess),
('prep2', preprocess2),
('clf', RandomForestClassifier())
])
search = GridSearchCV(
estimator=pipeline,
param_grid=
'prep2__pcadtm__n_components': [2, 3],
'clf': [rf_gs, kn_gs],
,
scoring = 'accuracy',
cv = 3,
return_train_score = True
)
这还具有减少预处理器计算次数的效果。但另请参阅Pipeline
的memory
参数。
另外,请注意,这种方法相当显着地改变了 cv 折叠。如果您想要“平面”搜索,可以编写一个快速脚本以在第一种方法中生成更长的列表。
【讨论】:
完美!感谢您提供正确的方法,一种替代方法(第二种方法对我来说在精神上更容易),特别是解释实际发生的事情。对塑造我的心理概念非常有帮助的答案。感谢您花时间传递您的知识和经验。非常感谢!以上是关于网格搜索预处理多个超参数和多个估计器的主要内容,如果未能解决你的问题,请参考以下文章
你能从 sklearn 网格搜索 (GridSearchCV) 中获得所有估计器吗?