问题与目标

残差围绕 0 随机散开时,线性假设暂时没有明显系统问题;弧线或漏斗形则需继续诊断。
线性回归预测连续数值,并提供可解释的线性基线。本篇用自建资源消耗数据完成拟合、残差和正则化比较。
完成标准:能解释系数、截距、MAE、RMSE、R² 和残差,识别外推与共线性风险。
核心概念
模型形式为 ŷ = w₁x₁ + ... + wₙxₙ + b。最小二乘让平方误差尽量小;Ridge 在损失中加入权重平方惩罚,降低大系数和共线性带来的不稳定。
MAE 是平均绝对误差,单位与目标一致;RMSE 更强调大误差;R² 表示相对均值基线解释的变异比例,可能为负。残差是 真实值-预测值,应检查其是否存在系统模式。
从一元到多元回归
一元回归的直线斜率表示输入增加一个单位时预测平均变化多少;多元回归的某个系数表示“其他特征保持不变”时的线性变化。若特征高度相关,例如文件数和输入体积总是同步增加,单个系数会变得不稳定。
最小二乘可通过解析方法求解,也可使用梯度下降。解析法适合规模较小、条件良好的问题;迭代优化更容易扩展到大数据和复杂损失。调用 scikit-learn 时不必手写求解,但应知道训练目标。
四个指标分别回答什么
| 指标 | 解释 | 注意点 |
|---|---|---|
| MAE | 平均偏差多少目标单位 | 对大误差相对温和 |
| MSE | 平方误差均值 | 单位被平方 |
| RMSE | 强调大误差且恢复单位 | 容易受极端值影响 |
| R² | 相比均值基线改善多少 | 不是误差单位,可能为负 |
不能跨不同测试集直接比较这些指标。业务若特别不能接受大误差,应单独报告高分位绝对误差。
可运行实现
import numpy as np
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from sklearn.model_selection import train_test_split
rng = np.random.default_rng(42)
input_mb = rng.uniform(5, 100, 300)
file_count = rng.integers(1, 80, 300)
duration = 1.8 * input_mb + 0.7 * file_count + 15 + rng.normal(0, 12, 300)
X = np.column_stack([input_mb, file_count])
X_train, X_test, y_train, y_test = train_test_split(
X, duration, test_size=0.25, random_state=42,
)
for model in (LinearRegression(), Ridge(alpha=10.0)):
model.fit(X_train, y_train)
prediction = model.predict(X_test)
print(type(model).__name__)
print("coefficients:", np.round(model.coef_, 3))
print("MAE:", round(mean_absolute_error(y_test, prediction), 2))
print("RMSE:", round(np.sqrt(mean_squared_error(y_test, prediction)), 2))
print("R2:", round(r2_score(y_test, prediction), 3))
print("mean residual:", round(float(np.mean(y_test - prediction)), 3))
输入是体积和文件数,输出是耗时预测及四项诊断。系数接近生成规则只是因为数据人为构造;真实数据还要检查残差图和业务混杂因素。
残差诊断
import matplotlib.pyplot as plt
prediction = model.predict(X_test)
residual = y_test - prediction
figure, axis = plt.subplots(figsize=(6, 4))
axis.scatter(prediction, residual, alpha=0.6)
axis.axhline(0, color="black", linewidth=1)
axis.set(xlabel="Prediction", ylabel="Residual", title="Residual check")
figure.tight_layout()
figure.savefig("residuals.png", dpi=150)
plt.close(figure)
残差若随预测值形成弧线,说明线性关系可能不足;呈漏斗形可能表示误差方差随规模变化;少数远离主体的点需要回查数据和业务事件。
Ridge 的 alpha 越大,系数通常越收缩,但偏差也可能增加。它不是默认越大越好,应通过交叉验证选择,并将标准化放入 Pipeline。
用对照实验判断正则化
正则化解决的不是“分数不够高”,而是系数在共线性或小样本下不稳定。可以人为加入一个与 input_mb 高度相关的字段,比较普通回归和 Ridge 的系数:
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X_correlated = np.column_stack(
[input_mb, file_count, input_mb * 1.02 + rng.normal(0, 1, len(input_mb))]
)
X_train_c, X_test_c, y_train_c, y_test_c = train_test_split(
X_correlated, duration, test_size=0.25, random_state=42,
)
ridge = make_pipeline(StandardScaler(), Ridge(alpha=10.0))
ridge.fit(X_train_c, y_train_c)
print("test MAE:", round(mean_absolute_error(y_test_c, ridge.predict(X_test_c)), 2))
print("scaled coefficients:", np.round(ridge.named_steps["ridge"].coef_, 3))
注意,系数变小不代表每个字段都更“真实”。高度相关的特征会分摊信号,模型适合预测,但未必适合做因果解释。
如何读残差图
- 点云在 0 上下随机散开:线性形式暂时没有明显问题。
- 出现弯曲趋势:可能存在非线性关系,先回到数据机制,再考虑交互项、分段特征或树模型。
- 误差幅度随预测值变大:用 MAE/RMSE 之外,还应报告分区间误差,必要时对目标做对数变换。
- 极少数点距离很远:先核对数据,不应为了让图好看直接删除。
进一步验证
- 把噪声标准差从 12 改为 30,观察 MAE、RMSE 和 R² 的变化。
- 添加一个无关特征,比较普通回归与 Ridge 的测试误差。
- 为测试集生成残差图,用一句话记录是否看到系统模式。
结果判断不是得到某个固定分数,而是能用指标和残差图说明模型错在哪里。
常见问题与排查
- R² 高就认为模型可靠:检查测试划分、残差和数据泄漏。
- 直接比较不同量纲系数:先标准化,或结合单位解释。
- 预测远超训练范围:线性外推没有数据支持,应监控输入范围。
- 极端值主导平方损失:检查数据质量,比较 MAE 与稳健模型。
小结
线性回归是连续预测的可解释基线。可信结论来自独立评估、残差检查和输入范围,而不只是一条拟合直线。
许可协议:CC BY-NC 4.0
更新于 43 分钟前
觉得文章有帮助?点个赞吧!
0 条评论


