You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解读sklearn GridSearchCV最优分数:分数差异与负值原因咨询

关于GridSearchCV分数与手动计算R²的差异及负分问题解答

一、GridSearchCV返回分数和手动计算R²为啥不一样?

咱们先从最容易踩的坑说起:

  • 评分指标可能完全不同:如果你没给GridSearchCV显式指定scoring='r2',它对回归模型(比如你用的DecisionTreeRegressor)的默认评分是neg_mean_squared_error——也就是负的均方误差。这和你手动用r2_score计算的拟合优度完全是两个概念:前者是误差指标(加负号后,分数越高代表误差越小),后者是衡量模型拟合程度的(范围从负无穷到1,越接近1越好)。
  • 计算逻辑的本质差异:就算你指定了scoring='r2',GridSearchCV的分数是交叉验证每折R²的平均值。比如用5折CV时,它会把数据拆成5份,每次用4份训练、1份测试,计算该测试折的R²,最后取5次结果的平均;而你手动计算的R²,大概率是在整个训练集或者某一个单独划分的测试集上的结果,样本分布不一样,结果自然有差距。比如直接用全量数据训练模型,在训练集上算的R²会偏高(过拟合),和CV的平均分数没法直接对比。
  • 随机性带来的偏差:如果你的GridSearchCV没设置random_state,每次交叉验证的数据集划分都是随机的,这也会导致和你手动固定划分的训练/测试集的R²结果出现出入。

二、为啥GridSearchCV/cross_val_score会出现高度负分?

这种情况在回归任务里挺常见的,尤其是用R²作为评分指标时,主要原因有这些:

  • 模型拟合能力太差:R²的计算公式是1 - (残差平方和 / 总平方和),如果你的模型预测效果还不如直接取目标变量的平均值,那残差平方和就会大于总平方和,R²直接变成负数。比如给决策树设置极小的max_depth(比如1),模型太简单,根本抓不住数据的规律,就会出现这种情况。
  • 数据集本身的特性:像你用的糖尿病数据集,本身就是个比较难拟合的回归任务,特征和目标变量的关联没那么强,要是模型选得不对或者超参数没调好,很容易得到负的R²。
  • 交叉验证折内数据极端:有时候某几折的测试集里集中了很多极端样本,训练集里根本没见过这类数据,模型在这几折上的预测会极差,拉低整体的平均分数,甚至直接变成高度负值。
  • 混淆了负误差指标和R²:如果GridSearchCV用的是默认的neg_mean_squared_error,那分数本身就是负数(因为MSE是正的,取负后自然为负),数值越负代表误差越大。这时候你可能误以为是R²的负分,其实是完全不同的指标。

结合你的代码验证一下

给你改了段代码,跑起来就能直观看到差异和负分的情况:

from sklearn import datasets
from sklearn.model_selection import (cross_val_score, GridSearchCV, train_test_split)
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import r2_score

# 加载糖尿病数据集
diabetes = datasets.load_diabetes()
X, y = diabetes.data, diabetes.target

# 手动划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

# 训练简单模型,手动计算R²
simple_model = DecisionTreeRegressor(max_depth=1, random_state=42)
simple_model.fit(X_train, y_train)
y_pred = simple_model.predict(X_test)
manual_r2 = r2_score(y_test, y_pred)
print(f"手动计算的测试集R²: {manual_r2}")

# 用GridSearchCV指定R²评分,对比不同超参数结果
param_grid = {'max_depth': [1, 3, 5]}
grid_search = GridSearchCV(DecisionTreeRegressor(random_state=42), 
                           param_grid, scoring='r2', cv=5)
grid_search.fit(X, y)
print(f"GridSearchCV的最佳交叉验证平均R²: {grid_search.best_score_}")
print(f"最佳超参数: {grid_search.best_params_}")

你会发现当max_depth=1时,不管是手动测试集的R²还是CV的平均R²,都可能是负数——因为这个过于简单的模型,根本拟合不了糖尿病数据的复杂关系。

最后划个重点

  1. 先确认GridSearchCV的scoring参数是不是'r2',默认值和R²完全不是一回事;
  2. 交叉验证的分数是多折的平均值,和单一训练测试集的R²有差异是正常的;
  3. 高度负分(尤其是R²为负)说明模型还不如直接用均值预测,大概率是超参数设置得太极端,或者模型本身不适合当前任务。

内容的提问来源于stack exchange,提问作者abu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:16:09