【问题标题】:Negative cross_val_score with decision_tree_regressor model带有 decision_tree_regressor 模型的负 cross_val_score
【发布时间】:2017-12-14 17:50:13
【问题描述】:

我正在使用 cross_val_score 方法评估 desicion_tree_regressor 预测模型。问题是,分数似乎是负数,我真的不明白为什么。

这是我的代码:

all_depths = []
all_mean_scores = []
for max_depth in range(1, 11):
    all_depths.append(max_depth)
    simple_tree = DecisionTreeRegressor(max_depth=max_depth)
    cv = KFold(n_splits=2, shuffle=True, random_state=13)
    scores = cross_val_score(simple_tree, df.loc[:,'system':'gwno'], df['gdp_growth'], cv=cv)
    mean_score = np.mean(scores)
    all_mean_scores.append(np.mean(scores))
    print("max_depth = ", max_depth, scores, mean_score, sem(scores))

结果:

max_depth =  1 [-0.45596988 -0.10215719] -0.2790635315340 0.176906344162 
max_depth =  2 [-0.5532268 -0.0186984] -0.285962600541 0.267264196259 
max_depth =  3 [-0.50359311  0.31992411] -0.0918345038141 0.411758610421 max_depth =  4 [-0.57305355  0.21154193] -0.180755811466 0.392297741456 max_depth =  5 [-0.58994928  0.21180425] -0.189072515181 0.400876761509 max_depth =  6 [-0.71730634  0.22139877] -0.247953784441 0.469352551213 max_depth =  7 [-0.60118621  0.22139877] -0.189893720551 0.411292487323 max_depth =  8 [-0.69635044  0.13976584] -0.278292298411 0.418058142228 max_depth =  9 [-0.78917478  0.30970763] -0.239733577455 0.549441204178 max_depth =  10 [-0.76098227  0.34512503] -0.207928623044 0.553053649792

我的问题如下:

1) 分数返回 MSE 对吗?如果是,怎么会是负数?

2) 我有约 40 个观察值和约 70 个变量的小样本。这可能是问题吗?

提前致谢。

【问题讨论】:

    标签: python pandas machine-learning scikit-learn


    【解决方案1】:

    TL,DR:

    1) 不,除非您明确指定,否则它是估计器的默认 .score 方法。既然你没有,它默认为DecisionTreeRegressor.score,它返回决定系数,即R^2。这可能是负面的。

    2) 是的,这是个问题。它解释了为什么你会得到一个负的决定系数。

    详情:

    你使用过这样的函数:

    scores = cross_val_score(simple_tree, df.loc[:,'system':'gwno'], df['gdp_growth'], cv=cv)
    

    所以您没有明确传递“评分”参数。来看看docs

    评分:字符串,可调用或无,可选,默认:无

    一个字符串(参见模型评估文档)或带有签名 scorer(estimator, X, y) 的 scorer 可调用对象/函数。

    所以它没有明确说明这一点,但这可能意味着它使用了您的估算器的默认 .score 方法。

    为了证实这个假设,让我们深入了解source code。我们看到最终使用的记分器如下:

    scorer = check_scoring(estimator, scoring=scoring)
    

    那么,让我们看看source for check_scoring

    has_scoring = scoring is not None
    if not hasattr(estimator, 'fit'):
        raise TypeError("estimator should be an estimator implementing "
                        "'fit' method, %r was passed" % estimator)
    if isinstance(scoring, six.string_types):
        return get_scorer(scoring)
    elif has_scoring:
        # Heuristic to ensure user has not passed a metric
        module = getattr(scoring, '__module__', None)
        if hasattr(module, 'startswith') and \
           module.startswith('sklearn.metrics.') and \
           not module.startswith('sklearn.metrics.scorer') and \
           not module.startswith('sklearn.metrics.tests.'):
            raise ValueError('scoring value %r looks like it is a metric '
                             'function rather than a scorer. A scorer should '
                             'require an estimator as its first parameter. '
                             'Please use `make_scorer` to convert a metric '
                             'to a scorer.' % scoring)
        return get_scorer(scoring)
    elif hasattr(estimator, 'score'):
        return _passthrough_scorer
    elif allow_none:
        return None
    else:
        raise TypeError(
            "If no scoring is specified, the estimator passed should "
            "have a 'score' method. The estimator %r does not." % estimator)
    

    请注意,scoring=None 已被执行,所以:

    has_scoring = scoring is not None
    

    暗示has_scoring == False。另外,估计器有一个.score 属性,所以我们通过这个分支:

    elif hasattr(estimator, 'score'):
        return _passthrough_scorer
    

    这很简单:

    def _passthrough_scorer(estimator, *args, **kwargs):
        """Function that wraps estimator.score"""
        return estimator.score(*args, **kwargs)
    

    所以最后,我们现在知道scorer 是您的估算器的默认score。让我们查看docs for the estimator,其中明确指出:

    返回预测的决定系数 R^2。

    系数R^2定义为(1 - u/v),其中u是回归 平方和 ((y_true - y_pred) ** 2).sum() 和 v 是残差 平方和 ((y_true - y_true.mean()) ** 2).sum()。最好的 score 是 1.0,它可以是负数(因为模型可以 任意更坏)。始终预测预期的常数模型 y 的值,忽略输入特征,将得到 R^2 分数 0.0.

    所以看起来你的分数实际上是决定系数。因此,基本上,如果 R^2 为负值,则意味着您的模型表现非常很差。比我们只预测每个输入的期望值(即平均值)更糟糕。这是有道理的,因为正如您所说:

    我有约 40 个观察值和约 70 个变量的小样本。可能 这是问题所在?

    个问题。当你只有 40 个观察值时,对 70 维问题空间做出有意义的预测实际上是没有希望的。

    【讨论】:

    • 非常感谢这个详尽的回答。我将尝试减少维度并使用评分参数。
    • @Toutsos 不用担心。 pandas 文档通常很有帮助,如果您仍然不明白,它提供了指向必要源代码的非常方便的链接。如果您觉得这有帮助,您可以接受/点赞。
    • 已尝试但声望低于 15,因此不会公开显示。 Pandas 文档非常好。我已经发现评分参数只是没有足够的统计解释,我只是从机器学习开始。所以这不是python的问题,而是理解结果是什么以及如何解释它的问题。
    【解决方案2】:

    它可能发生。已在此post 中回答!

    实际的 MSE 只是你得到的数字的正数。

    统一评分 API 始终最大化分数,因此需要最小化的分数被取反,以便统一评分 API 正常工作。因此,返回的分数在应该最小化的分数时被否定,如果是应该最大化的分数,则保留为正数。

    【讨论】:

    • 谢谢。我真的搜索了但没有找到帖子。
    猜你喜欢
    • 2022-06-10
    • 2018-07-17
    • 2019-09-01
    • 2020-10-25
    • 2020-07-04
    • 1970-01-01
    • 2016-07-12
    • 2019-07-05
    • 2013-04-11
    相关资源
    最近更新 更多