sklearn.metrics.r2_score计算原始R²,公式为1-SS_res/SS_tot,不自动加截距,y_true与y_pred需等长且y_true不能全为常数;调整R²需手动计算,公式为1-(1-R²)(n-1)/(n-p-1),注意截距项处理;statsmodels可直接获取完整统计量但需显式添加常数列。

用 sklearn.metrics.r2_score 计算原始 R²
直接调用 r2_score 是最常用方式,它计算的是决定系数(coefficient of determination),公式为 1 - SS_res / SS_tot。注意:它不自动加截距项,输入的预测值 y_pred 必须来自你已拟合好的模型(比如 LinearRegression().fit(X, y).predict(X))。
常见错误是把未拟合模型的随机预测传进去,结果可能为负——R² 本身可以小于 0,说明模型比用均值预测还差。
-
y_true和y_pred长度必须一致,否则抛ValueError: Found array with dim 3. Expected 2类似错误 - 如果
y_true全是常数(方差为 0),r2_score返回-inf或nan,需提前检查 - 示例:
from sklearn.metrics import r2_score<br>y_true = [3, -0.5, 2, 7]<br>y_pred = [2.5, 0.0, 2, 8]<br>print(r2_score(y_true, y_pred)) # ≈ 0.948
手动计算调整 R²(adjusted R²)更可靠
sklearn 没有内置调整 R² 函数,但公式明确:1 - (1 - R²) * (n - 1) / (n - p - 1),其中 n 是样本数,p 是特征数(不含截距)。关键点在于:必须知道模型是否显式包含截距项。
如果你用 LinearRegression(fit_intercept=True)(默认),就按上述公式;若 fit_intercept=False,分母要改成 n - p,否则会高估模型表现。
- 别依赖第三方封装函数(如某些
statsmodels的快捷属性),它们对 intercept 处理逻辑可能不透明 - 推荐自己写一行计算,避免歧义:
n, p = X.shape<br>r2 = r2_score(y, y_pred)<br>adj_r2 = 1 - (1 - r2) * (n - 1) / (n - p - 1)
- 当
p接近n时,调整 R² 会急剧下降,这是正常惩罚——不是 bug
用 statsmodels 一次拿到完整回归统计量
如果你需要标准误、p 值、F 统计量等配套指标,statsmodels.api.OLS 是更合适的选择。它默认带截距,且 .summary() 输出里 R-squared 和 Adj. R-squared 都直接给出,数值与手动计算一致。
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
注意:statsmodels 要求显式添加常数列,否则会忽略截距——哪怕你心里认为“应该有”,代码不会猜。
- 必须调用
sm.add_constant(X),否则Adj. R-squared按无截距公式算 -
OLS(y, X_with_const).fit().rsquared和.rsquared_adj返回的是 float,可直接参与后续逻辑 - 性能上比
sklearn略慢,但对百万元素以下数据几乎无感
为什么不能直接用 LinearRegression.score() 当调整 R²?
LinearRegression.score() 返回的就是 R²(和 r2_score 结果一致),不是调整 R²。有人误以为它是“模型自带的优化分数”,其实它没考虑特征数量膨胀带来的过拟合风险。
尤其在做特征筛选或对比不同维度模型时,只看 .score() 会误导你选中冗余变量——因为 R² 永远随特征增加而上升(或不变),而调整 R² 可能下降。
- 多一个无关特征,
.score()可能从 0.821 升到 0.823,但调整 R² 可能从 0.815 降到 0.812 - 交叉验证中,应同时监控
r2_score和手动计算的调整 R²,二者趋势不一致时要查特征工程逻辑 - 没有“自动适配”的调整版
score方法,别试图 monkey patch
实际用的时候,R² 看拟合能力,调整 R² 看泛化潜力。前者告诉你“现在拟得怎么样”,后者提醒你“加了这个特征,值不值得”。两者的差值大小,往往就是你该回头检查特征重要性的信号。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










