GridSearchCV 评分参数:使用 scoring='f1' 或 scoring=None (默认使用准确度)给出相同的结果

GridSearchCV scoring parameter: using scoring='f1' or scoring=None (by default uses accuracy) gives the same result

我使用的是从书 "Mastering Machine Learning with scikit learn" 中摘录的示例。

它使用决策树来预测网页上的每个图像是否是 广告或文章内容。然后可以使用级联样式表隐藏被归类为广告的图像。数据可从互联网广告数据集公开获得:http://archive.ics.uci.edu/ml/datasets/Internet+Advertisements,其中包含 3,279 张图像的数据。

以下是完成分类任务的完整代码:

import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.cross_validation import train_test_split
from sklearn.metrics import classification_report
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCV
import sys,random

def main(argv):
    df = pd.read_csv('ad-dataset/ad.data', header=None)
    explanatory_variable_columns = set(df.columns.values)
    response_variable_column = df[len(df.columns.values)-1]


    explanatory_variable_columns.remove(len(df.columns.values)-1)
    y = [1 if e == 'ad.' else 0 for e in response_variable_column]
    X = df[list(explanatory_variable_columns)]

    X.replace(to_replace=' *\?', value=-1, regex=True, inplace=True)

    X_train, X_test, y_train, y_test = train_test_split(X, y,random_state=100000)

    pipeline = Pipeline([('clf',DecisionTreeClassifier(criterion='entropy',random_state=20000))])

    parameters = {
        'clf__max_depth': (150, 155, 160),
        'clf__min_samples_split': (1, 2, 3),
        'clf__min_samples_leaf': (1, 2, 3)
    }

    grid_search = GridSearchCV(pipeline, parameters, n_jobs=-1,verbose=1, scoring='f1')
    grid_search.fit(X_train, y_train)
    print 'Best score: %0.3f' % grid_search.best_score_
    print 'Best parameters set:'
    best_parameters = grid_search.best_estimator_.get_params()
    for param_name in sorted(parameters.keys()):
        print '\t%s: %r' % (param_name, best_parameters[param_name])

    predictions = grid_search.predict(X_test)
    print classification_report(y_test, predictions)


if __name__ == '__main__':
  main(sys.argv[1:])

在 GridSearchCV 中使用 scoring='f1' 的结果是:

使用 scoring=None(默认准确度度量)的结果与使用 F1 分数相同:

如果我没记错的话,通过不同的评分函数优化参数搜索应该会产生不同的结果。下面的案例说明使用scoring='precision'时得到的结果是不一样的。

使用 scoring='precision' 的结果与其他两种情况不同。 'recall' 等也是如此:

为什么 'F1' 和 None,默认准确度,给出相同的结果??

已编辑

我同意 Fabian 和 Sebastian 的两个回答。问题应该是小param_grid。但我只是想澄清一下,当我使用完全不同的(不是此处示例中的那个)高度不平衡数据集 100:1(这应该会影响准确性)并使用逻辑回归时,问题激增。在这种情况下,'F1' 和准确度也给出了相同的结果。

在这种情况下,我使用的 param_grid 如下:

parameters = {"penalty": ("l1", "l2"),
    "C": (0.001, 0.01, 0.1, 1, 10, 100),
    "solver": ("newton-cg", "lbfgs", "liblinear"),
    "class_weight":[{0:4}],
}

估计是参数选择太少了

我不同意通过不同的评分函数优化参数搜索必然会产生不同的结果。如果您的数据集是平衡的(每个 class 中的样本数量大致相同),我希望通过准确性和 F1 选择模型会产生非常相似的结果。

此外,请记住 GridSearchCV 会针对离散网格进行优化。也许使用更细的参数网格会产生您正在寻找的结果。

我认为作者没有很好地选择这个例子。我可能在这里遗漏了一些东西,但 min_samples_split=1 对我来说没有意义:它与设置 min_samples_split=2 不一样吗,因为你不能拆分 1 个样本——本质上,这是一种浪费计算时间。

From the documentation: min_samples_split: "The minimum number of samples required to split an internal node."

顺便说一句。这是一个非常小的网格,无论如何也没有太多选择,这可以解释为什么 accuracyf1 给你相同的参数组合,因此有相同的评分表。

如上所述,数据集可能很平衡,这就是为什么 F1 和准确度分数可能更喜欢相同的参数组合。因此,使用 (a) F1 分数和 (b) 准确性进一步查看您的 GridSearch 结果,我得出结论,在这两种情况下,150 的深度效果最佳。由于这是下限,它让您稍稍感觉到较低的 "depth" 值可能效果更好。但是,我怀疑这棵树在这个数据集上什至没有那么深(你甚至可以在达到最大深度之前得到 "pure" 个叶子)。

因此,让我们使用以下参数 grid

以更合理的值重复实验
parameters = {
    'clf__max_depth': list(range(2, 30)),
    'clf__min_samples_split': (2,),
    'clf__min_samples_leaf': (1,)
}

最佳 F1 分数的最佳 "depth" 似乎在 15 左右。

Best score: 0.878
Best parameters set:
    clf__max_depth: 15
    clf__min_samples_leaf: 1
    clf__min_samples_split: 2
             precision    recall  f1-score   support

          0       0.98      0.99      0.99       716
          1       0.92      0.89      0.91       104

avg / total       0.98      0.98      0.98       820

接下来,让我们尝试使用 "accuracy"(或 None)作为我们的评分指标:

> Best score: 0.967
Best parameters set:
    clf__max_depth: 6
    clf__min_samples_leaf: 1
    clf__min_samples_split: 2
             precision    recall  f1-score   support

          0       0.98      0.99      0.98       716
          1       0.93      0.85      0.88       104

avg / total       0.97      0.97      0.97       820

正如你所看到的,你现在得到不同的结果,如果你使用"accuracy."

,"optimal"深度是不同的

在不平衡数据集上使用 f1_score 评分器的 "labels" 参数仅使用您感兴趣的 class 的 f1 分数。或者考虑使用 "sample_weight".