【问题标题】:Hyperparameter tuning on the whole dataset?对整个数据集进行超参数调整?
【发布时间】:2018-09-21 11:44:20
【问题描述】:

这可能是一个奇怪的问题,因为我还没有完全理解超参数调整。

目前我正在使用sklearngridSearchCV 来调整randomForestClassifier 的参数,如下所示:

gs = GridSearchCV(RandomForestClassifier(n_estimators=100, random_state=42), param_grid={'max_depth': range(5, 25, 4), 'min_samples_leaf': range(5, 40, 5),'criterion': ['entropy', 'gini']}, scoring=scoring, cv=3, refit='Accuracy', n_jobs=-1)
gs.fit(X_Distances, Y)
results = gs.cv_results_

之后,我检查gs 对象中的best_paramsbest_score。现在我使用best_params 实例化RandomForestClassifier 并再次使用分层验证来记录指标并打印混淆矩阵:

rf = RandomForestClassifier(n_estimators=1000, min_samples_leaf=7, max_depth=18, criterion='entropy', random_state=42)
accuracy = []
metrics = {'accuracy':[], 'precision':[], 'recall':[], 'fscore':[], 'support':[]}
counter = 0

print('################################################### RandomForest ###################################################')
for train_index, test_index in skf.split(X_Distances,Y):
    X_train, X_test = X_Distances[train_index], X_Distances[test_index]
    y_train, y_test = Y[train_index], Y[test_index]
    rf.fit(X_train, y_train)
    y_pred = rf.predict(X_test)

    precision, recall, fscore, support = np.round(score(y_test, y_pred), 2)
    metrics['accuracy'].append(round(accuracy_score(y_test, y_pred), 2))
    metrics['precision'].append(precision)
    metrics['recall'].append(recall)
    metrics['fscore'].append(fscore)
    metrics['support'].append(support)

    print(classification_report(y_test, y_pred))
    matrix = confusion_matrix(y_test, y_pred)
    methods.saveConfusionMatrix(matrix, ('confusion_matrix_randomforest_distances_' + str(counter) +'.png'))
    counter = counter+1

meanAcc= round(np.mean(np.asarray(metrics['accuracy'])),2)*100
print('meanAcc: ', meanAcc)

这是一个合理的方法还是我完全错了?

编辑:

我刚刚测试了以下内容:

gs = GridSearchCV(RandomForestClassifier(n_estimators=100, random_state=42), param_grid={'max_depth': range(5, 25, 4), 'min_samples_leaf': range(5, 40, 5),'criterion': ['entropy', 'gini']}, scoring=scoring, cv=3, refit='Accuracy', n_jobs=-1)
gs.fit(X_Distances, Y)

这会在best_index = 28 产生best_score = 0.5362903225806451。当我检查索引 28 处 3 折的准确性时,我得到:

  1. split0: 0.5185929648241207
  2. split1:0.526686807653575
  3. split2:0.5637651821862348

这导致平均测试准确度:0.5362903225806451。 best_params:{'criterion': 'entropy', 'max_depth': 21, 'min_samples_leaf': 5}

现在我运行这段代码,它使用提到的 best_params 和分层的 3 折拆分(如 GridSearchCV):

rf = RandomForestClassifier(n_estimators=100, min_samples_leaf=5, max_depth=21, criterion='entropy', random_state=42)
accuracy = []
metrics = {'accuracy':[], 'precision':[], 'recall':[], 'fscore':[], 'support':[]}
counter = 0
print('################################################### RandomForest_Gini ###################################################')
for train_index, test_index in skf.split(X_Distances,Y):
    X_train, X_test = X_Distances[train_index], X_Distances[test_index]
    y_train, y_test = Y[train_index], Y[test_index]
    rf.fit(X_train, y_train)
    y_pred = rf.predict(X_test)

    precision, recall, fscore, support = np.round(score(y_test, y_pred))
    metrics['accuracy'].append(accuracy_score(y_test, y_pred))
    metrics['precision'].append(precision)
    metrics['recall'].append(recall)
    metrics['fscore'].append(fscore)
    metrics['support'].append(support)

    print(classification_report(y_test, y_pred))
    matrix = confusion_matrix(y_test, y_pred)
    methods.saveConfusionMatrix(matrix, ('confusion_matrix_randomforest_distances_' + str(counter) +'.png'))
    counter = counter+1

meanAcc= np.mean(np.asarray(metrics['accuracy']))
print('meanAcc: ', meanAcc)

指标字典产生完全相同的准确度(split0:0.5185929648241207,split1:0.526686807653575,split2:0.5637651821862348)

但是平均计算有点偏离:0.5363483182213101

【问题讨论】:

    标签: python machine-learning hyperparameters


    【解决方案1】:

    虽然这似乎是一种很有前途的方法,但您正在冒险: 您正在调整,然后使用相同的数据集评估此调整的结果。

    虽然在某些情况下这是一种合法的方法,但我会仔细检查您最后得到的指标与报告的 best_score 之间的差异。如果这些距离很远,你应该只在训练集上调整你的模型(你现在正在使用所有东西进行调整)。在实践中,这意味着预先执行拆分并确保GridSearchCV 看不到测试集。

    这可以这样完成:

    train_x, train_y, val_x, val_y = train_test_split(X_distances, Y, test_size=0.3, random_state=42)
    

    然后您将在 train_x, train_y 上运行调整和训练。

    另一方面,如果两个分数接近,我想你很高兴。

    【讨论】:

    • 分数非常接近。您的建议意味着,如果我想使用交叉验证进行验证,我将运行 GridSearchCV 三次(1/fold)?
    • 我做了一个代码示例(不幸的是没有测试)。一般来说,这是不需要的,因为您的验证分数接近best_score,但您仍然可以记住它何时不会:)
    • 好的,谢谢!不幸的是,我仍然不明白为什么这是一个问题。 GridSearchCV 创建模型并使用交叉验证(训练/测试数据拆分)对其进行测试。最后,我有一个参数集,用于定义和训练一个新模型,该模型再次通过交叉验证进行验证。
    • 想象一下您正在手动调整。您尝试一组参数并获得分数(在另一个数据集上,因为正如您正确指出的那样,GridSearchCV 会这样做)。然后你尝试降低学习率,你会得到一个更好的分数。所以现在你决定保留这个learning rate。现在想象你做了很多很多次。现在您的数据集还没有直接看到测试数据集,但是看到了,并且您根据它做出了设计决策!这意味着您的模型实际上通过其程序员的眼睛看到了测试数据
    • 我用一个说明性的例子更新了我的初始帖子。最后,我想复制使用 gridSearchCV 找到的 best_estimator 的预测。为此,我使用 best_params 在分类器上执行分层交叉验证(与 gridSearch 相同的选项)。因此,我能够重现混淆矩阵的最佳估计器的预测。
    猜你喜欢
    • 2019-07-25
    • 2018-03-07
    • 2021-08-11
    • 2018-12-07
    • 2021-06-14
    • 2022-08-16
    • 2020-11-13
    • 2020-07-24
    • 1970-01-01
    相关资源
    最近更新 更多