使用 Imblearn 管道和 GridSearchCV 进行交叉验证
Posted
技术标签:
【中文标题】使用 Imblearn 管道和 GridSearchCV 进行交叉验证【英文标题】:Cross Validating With Imblearn Pipeline And GridSearchCV 【发布时间】:2020-03-07 22:43:09 【问题描述】:我正在尝试使用imblearn
和GridSearchCV
中的Pipeline
类来获得对不平衡数据集进行分类的最佳参数。根据here 提到的答案,我想省略验证集的重新采样,而只重新采样训练集,imblearn
的Pipeline
似乎正在这样做。但是,在实施公认的解决方案时出现错误。请让我知道我做错了什么。下面是我的实现:
def imb_pipeline(clf, X, y, params):
model = Pipeline([
('sampling', SMOTE()),
('classification', clf)
])
score='AUC':'roc_auc',
'RECALL':'recall',
'PRECISION':'precision',
'F1':'f1'
gcv = GridSearchCV(estimator=model, param_grid=params, cv=5, scoring=score, n_jobs=12, refit='F1',
return_train_score=True)
gcv.fit(X, y)
return gcv
for param, classifier in zip(params, classifiers):
print("Working on ...".format(classifier[0]))
clf = imb_pipeline(classifier[1], X_scaled, y, param)
print("Best parameter for is ".format(classifier[0], clf.best_params_))
print("Best `F1` for is ".format(classifier[0], clf.best_score_))
print('-'*50)
print('\n')
参数:
['penalty': ('l1', 'l2'), 'C': (0.01, 0.1, 1.0, 10),
'n_neighbors': (10, 15, 25),
'n_estimators': (80, 100, 150, 200), 'min_samples_split': (5, 7, 10, 20)]
分类器:
[('Logistic Regression',
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, l1_ratio=None, max_iter=100,
multi_class='warn', n_jobs=None, penalty='l2',
random_state=None, solver='warn', tol=0.0001, verbose=0,
warm_start=False)),
('KNearestNeighbors',
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=None, n_neighbors=5, p=2,
weights='uniform')),
('Gradient Boosting Classifier',
GradientBoostingClassifier(criterion='friedman_mse', init=None,
learning_rate=0.1, loss='deviance', max_depth=3,
max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=100,
n_iter_no_change=None, presort='auto',
random_state=None, subsample=1.0, tol=0.0001,
validation_fraction=0.1, verbose=0,
warm_start=False))]
错误:
ValueError: Invalid parameter C for estimator Pipeline(memory=None,
steps=[('sampling',
SMOTE(k_neighbors=5, kind='deprecated',
m_neighbors='deprecated', n_jobs=1,
out_step='deprecated', random_state=None, ratio=None,
sampling_strategy='auto', svm_estimator='deprecated')),
('classification',
LogisticRegression(C=1.0, class_weight=None, dual=False,
fit_intercept=True, intercept_scaling=1,
l1_ratio=None, max_iter=100,
multi_class='warn', n_jobs=None,
penalty='l2', random_state=None,
solver='warn', tol=0.0001, verbose=0,
warm_start=False))],
verbose=False). Check the list of available parameters with `estimator.get_params().keys()`. """
【问题讨论】:
你做了 estimator.get_params().keys() 吗? 对不起,我不明白。你的意思是?怎么办? 【参考方案1】:请查看此示例如何在管道中使用参数: - https://scikit-learn.org/stable/auto_examples/compose/plot_compare_reduction.html#sphx-glr-auto-examples-compose-plot-compare-reduction-py
无论何时使用管道,您都需要以某种方式发送参数,以便管道可以了解哪个参数用于列表中的哪个步骤。为此,它使用您在管道初始化期间提供的名称。
在你的代码中,例如:
model = Pipeline([
('sampling', SMOTE()),
('classification', clf)
])
要将参数 p1 传递给 SMOTE,您可以使用 sampling__p1
作为参数,而不是 p1
。
您使用"classification"
作为clf
的名称,因此将其附加到应该转到clf
的参数中。
试试:
['classification__penalty': ('l1', 'l2'), 'classification__C': (0.01, 0.1, 1.0, 10),
'classification__n_neighbors': (10, 15, 25),
'classification__n_estimators': (80, 100, 150, 200), 'min_samples_split': (5, 7, 10, 20)]
确保名称和参数之间有两个下划线。
【讨论】:
顺便说一句,你知道Pipeline
在将SMOTE
与GridSeachCV
配对时如何排除对KFold
简历的重新采样?
@KrishnangKDalal 这就是 imblearn 管道的设计方式。它仅在调用fit
时重新采样,而不是在调用predict
时。
知道了!非常感谢。
我有一个问题:如果我使用 gcv.best_estimator_ ,在你刚才描述的过程之后,我得到的模型是用过采样数据训练的?以上是关于使用 Imblearn 管道和 GridSearchCV 进行交叉验证的主要内容,如果未能解决你的问题,请参考以下文章
如何参考管道步骤,在管道上使用 feature_importance_?
ModuleNotFoundError:没有名为“imblearn”的模块