cross_val_score对回归模型默认使用r2_score,但若未显式指定scoring且estimator为回归器,可能fallback到neg_mean_squared_error等负损失指标,结果天然为负;所有以neg_开头的scoring字符串均返回负损失值,数值越小(越负)表示模型越差。
cross_val_score 默认用 regression 的 neg_ 指标
当你没传 scoring 参数,而 estimator 是回归模型(比如 RandomForestRegressor、DecisionTreeRegressor),cross_val_score 会自动调用其 .score() 方法——对回归器来说,这默认是 r2_score,可能为负;更常见的是,它 fallback 到 sklearn 内置的损失类指标,如 neg_mean_squared_error 或 neg_mean_absolute_error,这些本身就是带负号的设计,结果天然为负。
这不是 bug,是 sklearn 的约定:所有以 neg_ 开头的 scoring 字符串,返回值都是「负的损失」,数值越小(越负)代表模型越差。
- 别看输出叫 “score”,它不一定是 [0,1] 区间内的“准确率”
- 分类器(如
LogisticRegression)默认用accuracy,所以通常为正 - 回归器默认不用
accuracy——因为回归没有“准确率”概念,强行用会报错或返回无意义值
scoring 参数写错或没写,导致指标和任务类型不匹配
最典型的错误是:拿回归模型去跑分类指标,或者反过来。例如:
- 用
RandomForestRegressor+scoring='accuracy'→ 报错或返回荒谬负值(如 -276.8) - 用
LogisticRegression+scoring='r2_score'→ 返回超出 [0,1] 的浮点数,甚至负值 - 把字符串标签(如
['cat', 'dog'])直接喂给回归器 →y被隐式转成序号,但评估时仍按连续值算r2,结果失真
验证方式很简单:print(np.unique(y)) 看标签是否为整数/浮点数;from sklearn.metrics import SCORERS; list(SCORERS.keys()) 查你写的 scoring 是否真实存在且语义匹配。
KFold 创建时漏掉 shuffle 和 random_state
KFold 默认 shuffle=False,意味着数据按原始顺序切分。如果你的数据自带强顺序(比如时间序列、按标签聚类排列的样本),某几折可能全是没有正例的子集,导致模型在那折上完全失效,r2 或损失函数剧烈恶化,拉出极端负值。
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
- 正确写法:
KFold(n_splits=10, shuffle=True, random_state=42) - 不设
random_state会导致每次运行结果不同,不利于复现和调试 - 哪怕用了
cross_val_score(..., cv=10)这种简写,背后也是KFold,同样受此影响
特征与标签长度不一致或索引错位
清洗、过滤、重采样后忘了重置索引,容易造成 X 和 y 行数相同但实际对不上。比如:
-
X = df.dropna().iloc[:, :-1],但y = df['target']没同步 dropna → 长度不等,cross_val_score可能静默截断或广播错位 - 用
pandas做布尔索引后未调用.reset_index(drop=True)→ 索引空洞,KFold 切分时取到 NaN 行 - 检查手段:
assert len(X) == len(y)+assert X.index.equals(y.index)
这种错位不会直接报错,但会让某几折训练/验证数据严重失真,r2 或损失瞬间崩塌为极大负值——这也是为什么看到 -300 多的“准确率”时,第一反应不该是换模型,而是查数据对齐。
负得分本身不是失败信号,它是 sklearn 对“任务-指标-数据”三者是否自洽的一次硬校验。真正危险的,是忽略负值、强行取绝对值、或只盯着平均分而跳过单折明细。