使用网格搜索获得最佳模型的“并行”管道
Posted
技术标签:
【中文标题】使用网格搜索获得最佳模型的“并行”管道【英文标题】:"Parallel" pipeline to get best model using gridsearch 【发布时间】:2017-07-05 03:19:27 【问题描述】:在 sklearn 中,可以定义串行管道以获得管道所有连续部分的最佳超参数组合。串行流水线可以如下实现:
from sklearn.svm import SVC
from sklearn import decomposition, datasets
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
digits = datasets.load_digits()
X_train = digits.data
y_train = digits.target
#Use Principal Component Analysis to reduce dimensionality
# and improve generalization
pca = decomposition.PCA()
# Use a linear SVC
svm = SVC()
# Combine PCA and SVC to a pipeline
pipe = Pipeline(steps=[('pca', pca), ('svm', svm)])
# Check the training time for the SVC
n_components = [20, 40, 64]
params_grid =
'svm__C': [1, 10, 100, 1000],
'svm__kernel': ['linear', 'rbf'],
'svm__gamma': [0.001, 0.0001],
'pca__n_components': n_components,
但是,如果我想为管道的每个步骤尝试不同的算法怎么办?我怎么能例如网格搜索
主成分分析或奇异值分解与 支持向量机或随机森林
这将需要某种 2 级或“元网格搜索”,因为模型的类型将是超参数之一。这在sklearn中可能吗?
【问题讨论】:
您可以将这两种类型的估算器添加到管道中,并在 gridSearchCV 中将它们设置为None
。
听起来是一个务实的解决方案。您能否将其集成到上面的示例代码中并将其作为答案发布?
【参考方案1】:
管道在其steps
(估算器列表)中支持None
,通过它可以关闭管道的某些部分。
您可以将 None
参数传递给管道的 named_steps
,以通过在传递给 GridSearchCV 的参数中设置它来不使用该估算器。
假设您想使用PCA
和TruncatedSVD
。
pca = decomposition.PCA()
svd = decomposition.TruncatedSVD()
svm = SVC()
n_components = [20, 40, 64]
在管道中添加svd
pipe = Pipeline(steps=[('pca', pca), ('svd', svd), ('svm', svm)])
# Change params_grid -> Instead of dict, make it a list of dict**
# In the first element, pass `svd = None`, and in second `pca = None`
params_grid = [
'svm__C': [1, 10, 100, 1000],
'svm__kernel': ['linear', 'rbf'],
'svm__gamma': [0.001, 0.0001],
'pca__n_components': n_components,
'svd':[None]
,
'svm__C': [1, 10, 100, 1000],
'svm__kernel': ['linear', 'rbf'],
'svm__gamma': [0.001, 0.0001],
'pca':[None],
'svd__n_components': n_components,
'svd__algorithm':['randomized']
]
现在只需将管道对象传递给 gridsearchCV
grd = GridSearchCV(pipe, param_grid = params_grid)
调用grd.fit()
将在params_grid
列表的两个元素上搜索参数,一次使用一个中的所有值。
参数同名时的简化
如果“OR”中的两个估计器与本例中的参数名称相同,其中PCA
和TruncatedSVD
具有n_components
(或者您只想搜索此参数,这可以简化为:
#Here I have changed the name to `preprocessor`
pipe = Pipeline(steps=[('preprocessor', pca), ('svm', svm)])
#Now assign both estimators to `preprocessor` as below:
params_grid =
'svm__C': [1, 10, 100, 1000],
'svm__kernel': ['linear', 'rbf'],
'svm__gamma': [0.001, 0.0001],
'preprocessor':[pca, svd],
'preprocessor__n_components': n_components,
该方案的推广
我们可以创建一个函数,它可以使用适当的值自动填充我们的param_grid
以提供给GridSearchCV
:-
def make_param_grids(steps, param_grids):
final_params=[]
# Itertools.product will do a permutation such that
# (pca OR svd) AND (svm OR rf) will become ->
# (pca, svm) , (pca, rf) , (svd, svm) , (svd, rf)
for estimator_names in itertools.product(*steps.values()):
current_grid =
# Step_name and estimator_name should correspond
# i.e preprocessor must be from pca and select.
for step_name, estimator_name in zip(steps.keys(), estimator_names):
for param, value in param_grids.get(estimator_name).iteritems():
if param == 'object':
# Set actual estimator in pipeline
current_grid[step_name]=[value]
else:
# Set parameters corresponding to above estimator
current_grid[step_name+'__'+param]=value
#Append this dictionary to final params
final_params.append(current_grid)
return final_params
并在任意数量的转换器和估算器上使用此函数
# add all the estimators you want to "OR" in single key
# use OR between `pca` and `select`,
# use OR between `svm` and `rf`
# different keys will be evaluated as serial estimator in pipeline
pipeline_steps = 'preprocessor':['pca', 'select'],
'classifier':['svm', 'rf']
# fill parameters to be searched in this dict
all_param_grids = 'svm':'object':SVC(),
'C':[0.1,0.2]
,
'rf':'object':RandomForestClassifier(),
'n_estimators':[10,20]
,
'pca':'object':PCA(),
'n_components':[10,20]
,
'select':'object':SelectKBest(),
'k':[5,10]
# Call the method on the above declared variables
param_grids_list = make_param_grids(pipeline_steps, all_param_grids)
现在用上面pipeline_steps
中使用的名称初始化一个管道对象
# The PCA() and SVC() used here are just to initialize the pipeline,
# actual estimators will be used from our `param_grids_list`
pipe = Pipeline(steps=[('preprocessor',PCA()), ('classifier', SVC())])
现在,终于设置了gridSearchCV对象和拟合数据
grd = GridSearchCV(pipe, param_grid = param_grids_list)
grd.fit(X, y)
【讨论】:
我认为您在 svc 和 randomforest 之间也不需要“或”。我可能会编辑这个答案,以便更概括地处理更多的估算器。 谢谢,我明白了。以上是关于使用网格搜索获得最佳模型的“并行”管道的主要内容,如果未能解决你的问题,请参考以下文章