机器学习实践项目(二)- 房价预测增强篇 - 模型训练与评估:从多模型对比到小网格微调

好,前述的代码,我们处理了特征工程,下面就正式进入了模型训练阶段了。
我们的策略是——用多个模型进行交叉验证并选出最佳模型
下面来分析对应的代码。


一、评测指标函数:rmse_on_log_space

def rmse_on_log_space(y_true, y_pred):
    try:
        return mean_squared_error(np.log1p(y_true), np.log1p(y_pred), squared=False)
    except TypeError:
        return np.sqrt(mean_squared_error(np.log1p(y_true), np.log1p(y_pred)))
  • 把真实值/预测值先做 log1p 再算 RMSE —— 这是竞赛中常见的做法,能缓解右偏分布。
  • 兼容旧版 sklearn:旧版 mean_squared_error 没有 squared 参数,所以兜底用 sqrt(MSE)

二、核心交叉验证函数:rmse_cv(model)

pipe = Pipeline([
    ("prep", preprocess),
    ("reg", TransformedTargetRegressor(regressor=model, func=np.log1p, inverse_func=np.expm1))
])
...
for tr_idx, va_idx in stratified_splits:
    X_tr, X_va = X.iloc[tr_idx], X.iloc[va_idx]
    y_tr, y_va = y[tr_idx], y[va_idx]
    pipe.fit(X_tr, y_tr)
    pred_va = pipe.predict(X_va)
    rmses.append(rmse_on_log_space(y_va, pred_va))
  • 预处理(preprocess)和模型串成一个 Pipeline
    这样每折都只在训练折上拟合 imputer / 标准化 / One-Hot,避免数据泄漏。
    这个和前面介绍的“分层目标编码”一个概念。
  • TransformedTargetRegressor(TTR)让模型在 log 空间 里训练,预测时自动逆变换
    可以理解成:TTR 是一个小“批处理器”,定义一组操作,执行时顺序完成。
  • 遍历“第0步”生成的 stratified_splits(分层 K 折),
    确保每次试验用同一套折分,各模型结果可公平比较。
  • 最后返回该模型的 平均 RMSE 和标准差(越小越好)。

三、候选模型与“稳收敛”设置

candidates = {
    "RidgeCV": RidgeCV(...),
    "LassoCV": LassoCV(..., max_iter=200_000, tol=1e-3, selection="random"),
    "ElasticNetCV": ElasticNetCV(..., max_iter=200_000, tol=1e-3, selection="random"),
    "HistGBR": HistGradientBoostingRegressor(...)
}
  • 同时用 RidgeCV / LassoCV / ElasticNetCV / HistGBR 四类模型进行评估,选出最优者。
  • 线性稀疏模型给了更大的 max_iter、略放宽的 tol、加上 selection="random"
    是为了减少“不收敛”或“收敛慢”的告警。
  • HistGBR 则采用一组「保守但好用」的参数:
    learning_rate=0.06max_leaf_nodes=31min_samples_leaf=20l2_regularization=1e-3
    强调稳健泛化。

🌱 一句话先讲明白:

“我想比较几种不同的模型,看哪个预测房价最准。
为了防止它们训练不收敛或报错,我给每个模型设置了比较稳定的参数。”


四、模型字典与参数的通俗理解

🧩 四个模型是谁?

candidates = {
    "RidgeCV": RidgeCV(...),
    "LassoCV": LassoCV(...),
    "ElasticNetCV": ElasticNetCV(...),
    "HistGBR": HistGradientBoostingRegressor(...)
}

这其实就是一个“模型字典”:

模型简单理解作用
RidgeCV岭回归线性模型,防止过拟合
LassoCV套索回归线性模型,自动选特征
ElasticNetCV弹性网综合 Ridge 和 Lasso
HistGBR树模型(梯度提升树)捕捉非线性关系

五、模型参数逐个解释(配比喻更好记)

1️⃣ max_iter

训练时最多迭代多少次。
想象模型在不断“试探”参数,直到误差够小。
太少会“没学完”,所以给大一点(如 200000)更稳。

2️⃣ tol

容忍度(容错值)。
越小越严格,模型学得更久。稍放宽(1e-3)就不会老警告。

3️⃣ selection="random"

对 Lasso/ElasticNet 来说,这表示“随机挑选参数更新”。
随机顺序能防止算法卡住,更容易收敛。

4️⃣ learning_rate=0.06

树模型的学习速度。
太大会过拟合,太小会学不完。0.06 是稳健中间值。

5️⃣ max_leaf_nodes=31

每棵树的最大分支数。
分支越多模型越复杂,31 是“刚刚好”的中等复杂度。

6️⃣ min_samples_leaf=20

每个叶子节点至少多少样本。
样本太少容易记住噪声,20 可以防过拟合。

7️⃣ l2_regularization=1e-3

给模型一个“惩罚项”,让它别太激进。
值越大越“温和”,泛化更好。


🧠 类比:模型就像学生

参数比喻调节作用
max_iter给学生复习的次数多学几遍才彻底掌握
tol老师标准放宽点别太抠细节
selection学习顺序随机复习更灵活
learning_rate学习速度太快出错,太慢浪费时间
max_leaf_nodes笔记条数太多=啰嗦,太少=粗糙
min_samples_leaf每条笔记至少几句保证总结有依据
l2_regularization老师的管束防止学得太极端

一句话总结:

这些参数的目的就是:让模型稳稳当当地“学完”,不乱跑、不炸分。
所以叫“稳收敛设置”。


六、模型对比与最优选择

results = {}
for name, model in candidates.items():
    m, s = rmse_cv(model)
    results[name] = (m, s)
    print(f"{name:12s}: {m:.5f} +/- {s:.5f}")

best_name = min(results, key=lambda k: results[k][0])
  • 对每个模型都跑一次 rmse_cv,输出“均值 ± 标准差”;
  • RMSE 最小 的模型作为 best_name
  • 后续可用它进行全量训练或进一步调参。

七、小网格微调(仅当 HistGBR 最优时)

DO_HGB_TUNING = (best_name == "HistGBR")
...
hgb_pipe = Pipeline([
    ("prep", preprocess),
    ("reg", TransformedTargetRegressor(
        regressor=HistGradientBoostingRegressor(random_state=42),
        func=np.log1p, inverse_func=np.expm1))
])
param_grid = {
    "reg__regressor__learning_rate": [0.03, 0.06, 0.1],
    "reg__regressor__max_leaf_nodes": [31, 63, 127],
    "reg__regressor__min_samples_leaf": [10, 20, 40],
    "reg__regressor__l2_regularization": [1e-3, 3e-3, 1e-2]
}

继续沿用同一个管道结构,只在少数关键超参上做“小网格”搜索。
时间可控,却往往能涨一点分。


😵‍💫 什么是“小网格微调”?

好,到这里估计又要懵了。
什么是“网格”?什么是“小网格微调”?难道还有“大网格”?
好吧,我也是懵的,只好让“爱老师”继续上场 😄。


🧩 一句话解释

“小网格微调”就是:
模型已经不错了,再拿出几组可能更好的参数组合
让电脑帮我们试试,看哪组最好。


🌰 举个简单例子

假设你在调一台风扇:

参数档位
风速[1, 2, 3]
风向[固定, 摇头]

3 × 2 = 6 种组合,你挨个试试,看哪种风最舒服。
这,就是“小网格”搜索。


💡 在模型里怎么做?

HistGBR 也一样:
我们给它四个主要“旋钮”:

参数含义可能的值
learning_rate学习速度[0.03, 0.06, 0.1]
max_leaf_nodes每棵树最多叶子数[31, 63, 127]
min_samples_leaf每个叶子最少样本[10, 20, 40]
l2_regularization正则强度[1e-3, 3e-3, 1e-2]

让电脑“自动试” → 共 3×3×3×3 = 81 种组合。
这就是“小网格(Grid)”。


⚙️ GridSearchCV 做的事

  1. 挨个尝试参数组合;
  2. 每组都做交叉验证;
  3. 记录结果(RMSE);
  4. 选出最优组合;
  5. 返回“调好参数的最优模型”。

🧮 为什么叫“小网格”

参数太多会组合爆炸:

参数数每个取值组合数
239
3327
4381
53243

所以我们只在关键参数上取少量值,形成“小网格”,
节省计算,又能有效微调。


一句话总结:

“小网格微调 = 在模型已经不错的情况下,自动帮你试几组最重要的参数,让它更稳、更高分。”


八、最终产物

  • results:每个模型在分层 CV 下的 RMSE 均值/方差。
  • best_name:最好的基础模型名。
  • best_estimator(可选):若做了 HistGBR 微调,则为最优管道(含预处理 + TTR + 最优超参)。

九、一句话总结

这段代码把**“公平、稳定、可复现”**三件事落到实处:

  1. 同一套分层折评所有模型(公平);
  2. 在 log 空间评 RMSE,且每折重拟合预处理(稳定);
  3. 固定随机种子、重用折分、必要时小网格微调(可复现 + 提升)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值