Меня зовут Лукас, и я относительно новичок в области машинного обучения. Я написал этот код с помощью онлайн-документации и руководств. Однако мне нужна помощь в понимании правильности интеграции RFE() с GBM().
def evaluateAlgorithm(X_train, X_test, y_train, y_test, dataset):
Kfold = StratifiedKFold(n_splits=20, shuffle=True)
GBM = GradientBoostingClassifier(
loss='log_loss', learning_rate=0.01,
n_estimators=1000, subsample=0.9,
min_samples_split=2, min_samples_leaf=1,
min_weight_fraction_leaf=0.0, max_depth=8,
init=None, random_state=None,
max_features=None, verbose=0,
max_leaf_nodes=None, warm_start=False)
pipeline = Pipeline(steps=[['feature_selection', RFE(GBM)], ['model', GBM]])
parameters = {'model__learning_rate': [0.01, 0.02, 0.03],
'model__subsample': [0.9, 0.5, 0.3, 0.1],
'model__n_estimators': [100, 500, 1000],
'model__max_depth': [1, 2, 3],
'feature_selection__n_features_to_select': [7, 14, 27]}
grid_GBM = GridSearchCV(estimator=pipeline, param_grid=parameters, cv=Kfold,
verbose=1, n_jobs=-1, refit=True, scoring='accuracy')
grid_GBM.fit(X_train, y_train)
print("\n======================================================================== = ")
print(" Results from Grid Search Gradient Boosting")
print("======================================================================== = ")
print("\n The best estimator across ALL searched params: \n", grid_GBM.best_estimator_)
print("\n The best score across ALL searched params: \n", grid_GBM.best_score_)
print("\n The best parameters across ALL searched params: \n", grid_GBM.best_params_)
print("\n======================================================================== = ")
# Obtain features selected by RFE
rfe_selected_features_indices = grid_GBM.best_estimator_['feature_selection'].support_
rfe_selected_features_names = X_train.columns[rfe_selected_features_indices]
print("Features selected by RFE:", rfe_selected_features_names)
model_GBM = grid_GBM.best_estimator_
# Cross-validation
cv_results_GBM = cross_val_score(model_GBM, X_train, y_train, cv=Kfold, scoring='accuracy', n_jobs=-1, verbose=0)
print()
print("Cross Validation results Gradient Boosting: ", cv_results_GBM)
prt_string = "CV Mean accuracy: %f (Std: %f)" % (cv_results_GBM.mean(), cv_results_GBM.std())
print(prt_string)
trained_Model_GBM = model_GBM.fit(X_train, y_train)
print();
print('========================================================')
print();
print(trained_Model_GBM.get_params(deep=True))
print();
print('=========================================================')
# Make predictions on the test set
pred_Labels_GBM = trained_Model_GBM.predict(X_test)
pred_proba_GBM = trained_Model_GBM.predict_proba(X_test)
# Evaluate performance
print();
print('Evaluation of the trained model Gradient Boosting: ')
accuracy = accuracy_score(y_test, pred_Labels_GBM)
print();
print('Accuracy Gradient Boosting: ', accuracy)
precision = precision_score(y_test, pred_Labels_GBM, pos_label='positive')
print();
print('Precision Gradient Boosting: ', precision)
recall = recall_score(y_test, pred_Labels_GBM, pos_label='positive')
print();
print('Recall Score Gradient Boosting: ', recall)
f1 = f1_score(y_test, pred_Labels_GBM, pos_label='positive')
print();
print('f1 Score Gradient Boosting: ', f1)
confusion_mat = confusion_matrix(y_test, pred_Labels_GBM)
classReport = classification_report(y_test, pred_Labels_GBM)
print();
print('Classification Report Gradient Boosting: \n', classReport)
kappa_score = cohen_kappa_score(y_test, pred_Labels_GBM)
print();
print('Kappa Score Gradient Boosting: ', kappa_score)
skplt.estimators.plot_learning_curve(model_GBM, X_train, y_train, figsize=(8, 6))
plt.show()
skplt.metrics.plot_roc(y_test, pred_proba_GBM, figsize=(8, 6));
plt.show()
skplt.metrics.plot_confusion_matrix(y_test, pred_Labels_GBM, figsize=(8, 6));
plt.show()
skplt.metrics.plot_precision_recall(y_test, pred_proba_GBM,
title='Precision-Recall Curve', plot_micro=True,
classes_to_plot=None, ax=None, figsize=(8, 6),
cmap='nipy_spectral', title_fontsize='large',
text_fontsize='medium');
plt.show()
evaluateAlgorithm(X_train, X_test, y_train, y_test, dataset)
Моя цель — использовать RFE для поиска наилучшего сочетания функций наряду с поиском по сетке GBM для лучших гиперпараметров. Однако похоже, что RFE находит только лучшие функции перед гиперпараметрами поиска по сетке. Как я могу решить эту проблему, чтобы оба процесса происходили одновременно? Идея состоит в том, чтобы добиться наилучшего сочетания обоих критериев. Кроме того, есть ли у вас какие-либо предложения по улучшению этого кода?
Основываясь на ответе Бена Рейнигера, я пришел к следующему результату.
pipeline = Pipeline(steps=[['RFE', RFE(estimator=GBM)]])
parameters = {
'RFE__estimator__learning_rate': [0.001, 0.01, 0.05],#0.01, 0.02, 0.03, 0.05
'RFE__estimator__subsample': [0.9, 0.5, 0.1], #0.7, 0.3,
'RFE__estimator__n_estimators': [500, 1000, 2000], #1500
'RFE__estimator__max_depth': [4, 5, 6,], #3, 7, 8
#'RFE__estimator__max_features': ['auto', 'sqrt', 'log2', None],
#'RFE__estimator__min_samples_split': [2, 5, 10],
#'RFE__estimator__min_samples_leaf': [1, 2, 4],
#'RFE__estimator__max_leaf_nodes': [None, 5, 10, 20],
'RFE__n_features_to_select': [5, 10, 20]
}
Как написано, ваш код настраивает гиперпараметры окончательной модели, но не гиперпараметры GBM на этапе выбора функций. Несколько вариантов:
Расширьте пространство поиска, включив в него гиперпараметры select-gbm, например. feature_selection__estimator__max_depth
.
Отбросьте шаг модели. RFE
предоставляет доступ к окончательной модели выбранного набора функций (estimator_
), а методы, которые вам могут понадобиться от нее, становятся доступными непосредственно из объекта RFE
(например, rfe.predict
). Итак, просто измените имена гиперпараметров, как указано выше.
Разница между этими подходами заключается в том, что первый позволяет выбрать ГБМ с гиперпараметрами, отличными от модели-ГБМ. Это будет более затратно в вычислительном отношении, но более гибко. Лично я был бы удивлён, если бы это дало значительные улучшения, поэтому я бы предложил второй подход, если у вас нет времени и желания экспериментировать.
Основываясь на ответе Бена Рейнигера, я добавил новое поле в вопрос с решением.