当前位置: 首页 > news >正文

机器学习实践项目(二)- 房价预测增强篇 - 特征工程四

好的,上一篇文章我们提到了独热编码(One-Hot)是一个非常妙的对于分类类型字段的处理方式,它把模型不能识别的字符型的类别字段,转换成了0/1为值的新列,既解决了模型不能识别分类值的问题,又不去“错误暗示”分类之间有大小关系。但是妙则妙矣,这么多0/1值,其实也挺难理解的,而且多了n个字段,其中只有一个字段是1,其余全部为0,有点傻傻的。

解决这个问题的方法之一就是分层目标编码。老规矩,解释知识让AI来:

「目标编码(Target Encoding)」的安全实现版本(带 OOF + 平滑)

我们来一步步拆解,让你完全理解它的作用、原理👇

🌟 一句话解释:

它用目标值(SalePrice)的平均水平来数值化一个类别特征,并且通过 K 折分层来避免“信息泄漏”。

换句话说:
这个函数的任务就是把一个类别型变量(如 Neighborhood)
转换成一个与房价相关的数值特征(类别对应的平均房价)
并保证这个过程不会在训练中“偷看答案”。


🧠 一、目标编码(Target Encoding)是啥?

假设我们有一个类别特征:

NeighborhoodSalePrice
CollgCr200000
CollgCr220000
OldTown120000
NridgHt320000

传统的 One-Hot 会生成三列 0/1 矩阵,而目标编码更聪明:

用该类别的目标平均值代替它。

得到新特征:

NeighborhoodSalePriceNeighborhood_te
CollgCr200000210000
CollgCr220000210000
OldTown120000120000
NridgHt320000320000

这就让模型直接“知道”:某个社区的平均房价水平。
对于高基数特征(比如上百个类别),比 One-Hot 更高效、解释性更强。


🧩 二、问题:这样会“偷看答案”

如果我们直接用全量 y 算均值(比如上面 210000),
那模型在训练时已经看到了目标 SalePrice ——
这就是数据泄漏(data leakage)
会让交叉验证看起来分数高,但在真实预测中掉分。


🚧 三、解决方案:Out-Of-Fold(OOF)编码

这个函数做的就是 OOF Target Encoding
原理是:

1️⃣ 把训练集分成 n_splits(默认 5 折)。
2️⃣ 每次只用“训练折”的数据去计算类别均值。
3️⃣ 再把均值应用到“验证折”。

这样每一行的编码都来自模型未见过的折,就不会泄漏目标信息。


🔢 四、代码逻辑逐行解释

y_log = np.log1p(y)
global_mean = y_log.mean()

👉 对房价取对数(Kaggle 房价比赛的标准做法),
在 log 空间计算类别平均价格,稳定性更高。
global_mean 是全局平均房价,用作平滑与缺失的兜底值。


kf = KFold(n_splits=n_splits, shuffle=True, random_state=42)
te = pd.Series(index=X.index, dtype=float)

👉 初始化 5 折交叉验证 + 存放结果的空列。


for tr_idx, va_idx in kf.split(X):tr, va = X.iloc[tr_idx], X.iloc[va_idx]y_tr = y_log.iloc[tr_idx]

👉 进入每一折:

  • tr 是“训练折”;
  • va 是“验证折”;
  • 只在训练折上计算编码,避免泄漏验证折的 y

means = tr.groupby(col).apply(lambda d: y_tr[d.index].mean())
counts = tr[col].value_counts()

👉 在训练折中:

  • means 是每个类别的平均 log(房价);
  • counts 是每个类别出现次数(用于平滑)。

enc = (means * counts + global_mean * smooth) / (counts + smooth)

👉 平滑公式
当类别样本数小(如只出现一次),直接取均值会不稳定;
通过加上全局均值 global_mean 按比例混合,稳定效果。
smooth 越大,越偏向全局均值。


te.iloc[va_idx] = X.iloc[va_idx][col].map(enc).fillna(global_mean)

👉 把这一折的验证数据用训练折的编码映射;
未见过的类别用全局均值代替。

这样得到的 te 是一个与原训练集行数相同的新特征,
但它的每一行值都来自“别的折”的均值 → 完全避免泄漏。


🔮 五、测试集的处理

means_full = X.groupby(col).apply(lambda d: y_log[d.index].mean())
counts_full = X[col].value_counts()
enc_full = (means_full*counts_full + global_mean*smooth) / (counts_full + smooth)
te_test = X_test[col].map(enc_full).fillna(global_mean)

👉 对测试集可以安全地用全量训练数据来算编码,因为测试集没有目标泄漏风险。


🧩 六、最后一步:加新列

X[f"{col}_te"] = te.values
X_test[f"{col}_te"] = te_test.values
return X, X_test

这一步生成一个新的特征列,比如 Neighborhood_te
表示该样本所在社区的“平均 log 房价水平”。


✅ 七、效果总结

特征转换前转换后
NeighborhoodCollgCr / OldTown / …数值(代表类别平均房价)
技术点作用
log1p(y)稳定波动,贴合 RMSE 评测
KFold OOF避免目标泄漏
平滑防止稀有类别导致过拟合
训练/测试分别编码保证一致性与鲁棒性

💡 举个直观例子

假设:

NeighborhoodSalePrice
A100000
A120000
B250000
C500000

全局均值(log1p 后)大约等于 log(242500)。
折分后:

  • 第1折训练 A、B → 验证 C → C_te = log(平均B/A价);
  • 第2折训练 A、C → 验证 B → B_te = log(平均A/C价)。

训练集每一行都没看自己的真实价格。
最终模型能利用这些 *_te 特征捕捉“地区价格等级”,提升预测力。


🏁 八、总结一句话

oof_target_encode() 的作用是:

✅ 将类别特征数值化为“类别对应的平均目标值”;

✅ 使用 K 折 OOF 机制防止信息泄漏;

✅ 用平滑控制稀有类别稳定性;

✅ 最终输出训练/测试都包含的安全编码特征。


其实看到这里,什么是“目标编码”就很好理解了,但是我第一次看这个解释时,并没有明白何为“分层”,即K-Fold,那我们继续请教爱老师。


KFold(K 折交叉验证)其实一点都不复杂
我用生活比喻 + 图解的方式,帮你彻底搞懂它👇

🌰 一、直白解释:

KFold 就是“把训练集切成几块,轮流用一块来测试,其他几块来训练”的办法。

举个生活例子 🍰

你有一个蛋糕(数据集),要知道它的味道(模型好不好)。
如果你只尝一口,可能不准;
所以你把蛋糕切成 K 份(比如 5 份):

折数用来训练的部分用来验证的部分
第1折第2~5份第1份
第2折第1,3,4,5份第2份
第3折第1,2,4,5份第3份
第4折第1,2,3,5份第4份
第5折第1~4份第5份

然后你做 5 次实验,每次:

  • 在“训练部分”训练模型;
  • 用“验证部分”测试模型的表现。

最后,把这 5 次的表现(比如 RMSE)取平均值
就得到了一个更稳定的结果。


📊 二、图解理解(假设 K=5)

数据集索引: [1 2 3 4 5 6 7 8 9 10]第1折:  训练=[3,4,5,6,7,8,9,10], 验证=[1,2]
第2折:  训练=[1,2,5,6,7,8,9,10], 验证=[3,4]
第3折:  训练=[1,2,3,4,7,8,9,10], 验证=[5,6]
第4折:  训练=[1,2,3,4,5,6,9,10], 验证=[7,8]
第5折:  训练=[1,2,3,4,5,6,7,8],   验证=[9,10]

你看,每一折都会轮流当一次“验证集”,
其他数据则都用来训练。
所以每个样本都被模型预测过一次,但不会参与预测自己。
这就能避免模型“作弊”看到答案。


💡 三、为什么要这么麻烦?

如果你只随机分一次训练/验证:

  • 运气好:分得刚好平衡 → 分数看起来很好;
  • 运气差:验证集偏、含噪声多 → 分数很差。

而 KFold 多次轮流验证,就像:

“我不看一次考试成绩,而看五次平均分。”

这样更稳定、更可靠。
它能告诉你模型整体表现,而不是“某一次偶然分割”的结果。


🧮 四、在 oof_target_encode 里的作用

回想我们在做“目标编码”时:

  • 我们要用 y(房价)去算类别均值;
  • 但又不能“偷看自己”。

KFold 就帮我们做到这点👇

用来计算均值的行(训练折)被赋值的行(验证折)
1折2~5 的数据折1 的数据
2折1,3,4,5 的数据折2 的数据

所以对于每个样本,它得到的编码值,
都来自其它样本,而不是自己那一折的目标值。
这就完全避免了“信息泄漏”。

简单说:KFold 让我们“用别人家的答案算平均”,
而不是“用自己的答案作弊”。


🧩 五、为什么叫 “Out-Of-Fold” (OOF)

  • “Fold” = 折。
  • “Out-Of-Fold” = 不在这一折里的数据。

即:

每个样本的预测/编码,来自于它不在的那几折的模型或均值。
所以叫 Out-of-Fold 编码


🚀 六、类比理解

场景类比
你考试 5 次,每次都换不同试卷(验证集)。→ KFold
老师不让你看自己卷子的答案,但可以看同学们的平均分来推测难度。→ Out-of-Fold Target Encoding
最后你拿 5 次考试的平均分作为期末成绩。→ 平均 RMSE 作为模型得分

🧠 七、总结一句话

KFold 就是反复切分数据,让模型在“看不到自己”的情况下多次验证,从而得到稳健、无泄漏的结果。


好了,那到此为止,大家明白什么是分层目标编码了吧?

http://www.dtcms.com/a/581230.html

相关文章:

  • C++20之三路比较运算符
  • 微网站方案用dw做的网站怎么上线
  • 微软解除 Win11 限制,“毛玻璃”效果将无处不在
  • 班级回忆录系统|基于SpringBoot和Vue的班级回忆录系统(源码+数据库+文档)
  • 让 ETL 更懂语义:DataWorks 支持数据集成 AI 辅助处理能力
  • 新能源汽车底盘紧固件的“防腐密码”:从技术革新到体系共创
  • 前端性能优化实战:从理论到实践的深度解析
  • 【C++:红黑树】深入理解红黑树的平衡之道:从原理、变色、旋转到完整实现代码
  • 网站怎么做翻页徐州专业网站seo
  • 《算法通关指南数据结构和算法篇(4)--- 队列和queue》
  • 云计算运维监控实战:生产环境与自建方案对比
  • 深入理解MySQL行锁,间隙锁和临键锁
  • 鸿安建设集团网站wordpress主题2019
  • 申请软著,怎么快速整理软件源代码
  • sam2 点选 分割图片 2025
  • 网站开发源程序重庆建筑人才网官网
  • 如何理解蒙特卡洛方法并用python进行模拟
  • 公司网站代码模板wordpress 虎嗅网
  • 在 Windows 中清理依赖node_modules并重新安装
  • 【数据结构】从零开始认识图论 --- 并查集与最小生成树算法
  • 使用 AWS WAF 防护 Stored XSS 攻击完整指南
  • 当爬虫遇到GraphQL:如何分析与查询这种新型API?
  • 游戏手柄遥控越疆协作机器人[一]
  • MATLAB实现决策树数值预测
  • Maven 多模块项目与 Spring Boot 结合指南
  • 搜索量最高的网站小白学编程应该从哪里开始学
  • 西安大型网站制作wordpress耗时显示
  • Kubernetes(k8s)
  • 如何提高 SaaS 产品的成功率?
  • ​技术融合新纪元:深度学习、大数据与云原生的跨界实践