在 GridSearchCV 的管道中交替使用不同的模型
Alternate different models in Pipeline for GridSearchCV
我想在 sklearn 中构建一个管道并使用 GridSearchCV 测试不同的模型。
举个例子(请不要关注选择的具体型号):
reg = LogisticRegression()
proj1 = PCA(n_components=2)
proj2 = MDS()
proj3 = TSNE()
pipe = [('proj', proj1), ('reg' , reg)]
pipe = Pipeline(pipe)
param_grid = {
'reg__c': [0.01, 0.1, 1],
}
clf = GridSearchCV(pipe, param_grid = param_grid)
这里如果我想尝试不同的模型进行降维,我需要编写不同的管道并手动进行比较。有简单的方法吗?
我想出的一个解决方案是定义我自己的 class 派生自基础估计器:
class Projection(BaseEstimator):
def __init__(self, est_name):
if est_name == "MDS":
self.model = MDS()
...
...
def fit_transform(self, X):
return self.model.fit_transform(X)
我认为它会起作用,我只是创建一个 Projection 对象并将其传递给 Pipeline,使用估算器的名称作为它的参数。
但对我来说,这种方式有点混乱且不可扩展:每次我想比较不同的模型时,它都会让我定义新的 class。同样要继续这个解决方案,可以实现一个 class 来完成相同的工作,但具有任意一组模型。这对我来说似乎太复杂了。
比较不同模型的最自然和 pythonic 方式是什么?
假设您想使用 PCA 和 TruncatedSVD 作为降维步骤。
pca = decomposition.PCA()
svd = decomposition.TruncatedSVD()
svm = SVC()
n_components = [20, 40, 64]
你可以这样做:
pipe = Pipeline(steps=[('reduction', pca), ('svm', svm)])
# Change params_grid -> Instead of dict, make it a list of dict
# In the first element, pass parameters related to pca, and in second related to svd
params_grid = [{
'svm__C': [1, 10, 100, 1000],
'svm__kernel': ['linear', 'rbf'],
'svm__gamma': [0.001, 0.0001],
'reduction':pca,
'reduction__n_components': n_components,
},
{
'svm__C': [1, 10, 100, 1000],
'svm__kernel': ['linear', 'rbf'],
'svm__gamma': [0.001, 0.0001],
'reduction':svd,
'reduction__n_components': n_components,
'reduction__algorithm':['randomized']
}]
现在只需将管道对象传递给 gridsearchCV
grd = GridSearchCV(pipe, param_grid = params_grid)
调用 grd.fit()
将在 params_grid 列表的两个元素上搜索参数,一次使用 one
中的所有值。
详情请看我的另一个回答:
不需要在参数网格中为估计器名称添加前缀的替代解决方案如下:
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
# the models that you want to compare
models = {
'RandomForestClassifier': RandomForestClassifier(),
'KNeighboursClassifier': KNeighborsClassifier(),
'LogisticRegression': LogisticRegression()
}
# the optimisation parameters for each of the above models
params = {
'RandomForestClassifier':{
"n_estimators" : [100, 200, 500, 1000],
"max_features" : ["auto", "sqrt", "log2"],
"bootstrap": [True],
"criterion": ['gini', 'entropy'],
"oob_score": [True, False]
},
'KNeighboursClassifier': {
'n_neighbors': np.arange(3, 15),
'weights': ['uniform', 'distance'],
'algorithm': ['ball_tree', 'kd_tree', 'brute']
},
'LogisticRegression': {
'solver': ['newton-cg', 'sag', 'lbfgs'],
'multi_class': ['ovr', 'multinomial']
}
}
你可以定义:
from sklearn.model_selection import GridSearchCV
def fit(train_features, train_actuals):
"""
fits the list of models to the training data, thereby obtaining in each
case an evaluation score after GridSearchCV cross-validation
"""
for name in models.keys():
est = models[name]
est_params = params[name]
gscv = GridSearchCV(estimator=est, param_grid=est_params, cv=5)
gscv.fit(train_features, train_actuals)
print("best parameters are: {}".format(gscv.best_estimator_))
基本上运行通过不同的模型,每个模型通过字典引用自己的一组优化参数。当然不要忘记将模型和参数字典传递给 fit
函数,以防您没有将它们作为全局变量。查看 at this GitHub project 以获得更完整的概述。
我想在 sklearn 中构建一个管道并使用 GridSearchCV 测试不同的模型。
举个例子(请不要关注选择的具体型号):
reg = LogisticRegression()
proj1 = PCA(n_components=2)
proj2 = MDS()
proj3 = TSNE()
pipe = [('proj', proj1), ('reg' , reg)]
pipe = Pipeline(pipe)
param_grid = {
'reg__c': [0.01, 0.1, 1],
}
clf = GridSearchCV(pipe, param_grid = param_grid)
这里如果我想尝试不同的模型进行降维,我需要编写不同的管道并手动进行比较。有简单的方法吗?
我想出的一个解决方案是定义我自己的 class 派生自基础估计器:
class Projection(BaseEstimator):
def __init__(self, est_name):
if est_name == "MDS":
self.model = MDS()
...
...
def fit_transform(self, X):
return self.model.fit_transform(X)
我认为它会起作用,我只是创建一个 Projection 对象并将其传递给 Pipeline,使用估算器的名称作为它的参数。
但对我来说,这种方式有点混乱且不可扩展:每次我想比较不同的模型时,它都会让我定义新的 class。同样要继续这个解决方案,可以实现一个 class 来完成相同的工作,但具有任意一组模型。这对我来说似乎太复杂了。
比较不同模型的最自然和 pythonic 方式是什么?
假设您想使用 PCA 和 TruncatedSVD 作为降维步骤。
pca = decomposition.PCA()
svd = decomposition.TruncatedSVD()
svm = SVC()
n_components = [20, 40, 64]
你可以这样做:
pipe = Pipeline(steps=[('reduction', pca), ('svm', svm)])
# Change params_grid -> Instead of dict, make it a list of dict
# In the first element, pass parameters related to pca, and in second related to svd
params_grid = [{
'svm__C': [1, 10, 100, 1000],
'svm__kernel': ['linear', 'rbf'],
'svm__gamma': [0.001, 0.0001],
'reduction':pca,
'reduction__n_components': n_components,
},
{
'svm__C': [1, 10, 100, 1000],
'svm__kernel': ['linear', 'rbf'],
'svm__gamma': [0.001, 0.0001],
'reduction':svd,
'reduction__n_components': n_components,
'reduction__algorithm':['randomized']
}]
现在只需将管道对象传递给 gridsearchCV
grd = GridSearchCV(pipe, param_grid = params_grid)
调用 grd.fit()
将在 params_grid 列表的两个元素上搜索参数,一次使用 one
中的所有值。
详情请看我的另一个回答:
不需要在参数网格中为估计器名称添加前缀的替代解决方案如下:
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
# the models that you want to compare
models = {
'RandomForestClassifier': RandomForestClassifier(),
'KNeighboursClassifier': KNeighborsClassifier(),
'LogisticRegression': LogisticRegression()
}
# the optimisation parameters for each of the above models
params = {
'RandomForestClassifier':{
"n_estimators" : [100, 200, 500, 1000],
"max_features" : ["auto", "sqrt", "log2"],
"bootstrap": [True],
"criterion": ['gini', 'entropy'],
"oob_score": [True, False]
},
'KNeighboursClassifier': {
'n_neighbors': np.arange(3, 15),
'weights': ['uniform', 'distance'],
'algorithm': ['ball_tree', 'kd_tree', 'brute']
},
'LogisticRegression': {
'solver': ['newton-cg', 'sag', 'lbfgs'],
'multi_class': ['ovr', 'multinomial']
}
}
你可以定义:
from sklearn.model_selection import GridSearchCV
def fit(train_features, train_actuals):
"""
fits the list of models to the training data, thereby obtaining in each
case an evaluation score after GridSearchCV cross-validation
"""
for name in models.keys():
est = models[name]
est_params = params[name]
gscv = GridSearchCV(estimator=est, param_grid=est_params, cv=5)
gscv.fit(train_features, train_actuals)
print("best parameters are: {}".format(gscv.best_estimator_))
基本上运行通过不同的模型,每个模型通过字典引用自己的一组优化参数。当然不要忘记将模型和参数字典传递给 fit
函数,以防您没有将它们作为全局变量。查看 at this GitHub project 以获得更完整的概述。