使用 RandomizedSearchCV 对 XGBClassifier 进行 Python 超参数优化

zad*_*lik 4 python classification bayesian xgboost

我正在尝试为 XGBClassifier 获得最佳超参数,这将导致获得最多的预测属性。我正在尝试使用 RandomizedSearchCV 通过 KFold 进行迭代和验证。

当我总共运行这个过程 5 次 (numFolds=5) 时,我希望将最好的结果保存在一个名为收集器的数据框中(如下所述)。所以每次迭代,我都希望最好的结果和分数附加到收集器数据帧。

 from scipy import stats
 from scipy.stats import randint
 from sklearn.model_selection import RandomizedSearchCV
 from sklearn.metrics import 
 precision_score,recall_score,accuracy_score,f1_score,roc_auc_score

clf_xgb = xgb.XGBClassifier(objective = 'binary:logistic')
param_dist = {'n_estimators': stats.randint(150, 1000),
              'learning_rate': stats.uniform(0.01, 0.6),
              'subsample': stats.uniform(0.3, 0.9),
              'max_depth': [3, 4, 5, 6, 7, 8, 9],
              'colsample_bytree': stats.uniform(0.5, 0.9),
              'min_child_weight': [1, 2, 3, 4]
             }
clf = RandomizedSearchCV(clf_xgb, param_distributions = param_dist, n_iter = 25, scoring = 'roc_auc', error_score = 0, verbose = 3, n_jobs = -1)

numFolds = 5
folds = cross_validation.KFold(n = len(X), shuffle = True, n_folds = numFolds)

collector = pd.DataFrame()
estimators = []
results = np.zeros(len(X))
score = 0.0

for train_index, test_index in folds:
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    clf.fit(X_train, y_train)
    estimators.append(clf.best_estimator_)
    estcoll = pd.DataFrame(estimators)


    estcoll['score'] = score
    pd.concat([collector,estcoll])
    print "\n", len(collector), "\n"
score /= numFolds
Run Code Online (Sandbox Code Playgroud)

由于某种原因,没有任何内容保存到数据框中,请帮忙。

此外,我有大约 350 个属性可以循环使用,训练中有 3.5K 行,测试中有 2K 行。通过贝叶斯超参数优化过程运行它是否有可能改善我的结果?或者它只会节省处理时间?

Max*_*wer 10

RandomizedSearchCV()将为你做的比你意识到的更多。在文档页面探索cv_results适合的 CV 对象的属性

这是您的代码几乎没有变化。我添加的两个更改:

  1. n_iter=5从 25更改。这将执行 5 组参数,这与您的 5 倍交叉验证意味着 25 总拟合。
  2. kfold在 RandomizedSearchCV 之前定义了你的对象,然后在 RandomizedSearchCV 的构建中将它作为cv参数引用

_

clf_xgb = xgb.XGBClassifier(objective = 'binary:logistic')
param_dist = {'n_estimators': stats.randint(150, 1000),
              'learning_rate': stats.uniform(0.01, 0.59),
              'subsample': stats.uniform(0.3, 0.6),
              'max_depth': [3, 4, 5, 6, 7, 8, 9],
              'colsample_bytree': stats.uniform(0.5, 0.4),
              'min_child_weight': [1, 2, 3, 4]
             }

numFolds = 5
kfold_5 = cross_validation.KFold(n = len(X), shuffle = True, n_folds = numFolds)

clf = RandomizedSearchCV(clf_xgb, 
                         param_distributions = param_dist,
                         cv = kfold_5,  
                         n_iter = 5, # you want 5 here not 25 if I understand you correctly 
                         scoring = 'roc_auc', 
                         error_score = 0, 
                         verbose = 3, 
                         n_jobs = -1)
Run Code Online (Sandbox Code Playgroud)

这是我的答案与您的代码明显不同的地方。只适合randomizedsearchcv对象一次,无需循环。它用它的cv参数处理 CV 循环。

clf.fit(X_train, y_train)
Run Code Online (Sandbox Code Playgroud)

您所有的交叉验证结果现在都在clf.cv_results_. 例如,你可以得到交叉验证(平均跨越5倍)列车得分: clf.cv_results_['mean_train_score']或交叉验证测试集(持有出数据)得分clf.cv_results_['mean_test_score']。您还可以获得其他有用的东西,例如mean_fit_time,paramsclf,一旦安装,就会自动记住您best_estimator_的属性。

这些与确定用于模型拟合的最佳超参数集相关。对于从 的单个迭代中使用的 5 折中的每一个,一组超参数是恒定的n_iter,因此您不必查看迭代中各折之间的不同分数。

  • @MaxPower 通过在 scipy 文档中进行挖掘,我找到了正确的答案。如果您希望“colsample_bytree”从 [0.5, 0.9] 均匀分布中采样,则需要指定“stats.uniform(0.5, 0.4)”而不是“stats.uniform(0.5, 0.9)”;我知道有点不直观:) (3认同)
  • @MaxPower指定(0.5,0.4)时范围为[0.5,0.9];从文档中,第一个参数是 loc,第二个参数是比例 - 最终范围是 [loc, loc + scale]。我不确定你是否会得到超出范围的结果;即使在 5M 个样本上我也找不到 - 即使我得到的样本非常接近 9 (0.899999779051796) 。必须事先对分布进行采样还意味着您需要将所有样本存储在内存中。在很多情况下你可能不想这样做 (2认同)