skip to content
tlj 的工程笔记
← 项目

一次没进牌区的 Kaggle:CV 陷阱、数据泄漏证伪、打不过的基线

比赛

一个测井地质导向的回归赛,我认真做了十几版,公榜 RMSE 14.759,倒数四分之一,没进牌区。但这次复盘不是关于名次,是三件我把过程讲透了的事:一次教科书级的 CV 口径纠错、一次亲手发现又亲手证伪的数据泄漏、以及一个系统性证明'曲线匹配打不过一条平线'的负面结果。

时间
2026-07
角色
主导需求 / CV 方法论 / 泄漏排查 / 结果判读(代码由 AI 写)
成果
测井 TVT 回归公榜 RMSE 14.759(约倒数 25%,未进牌区);但跑通了 CV 评分口径纠错、亲手发现并证伪一处 train/test 数据泄漏、系统性证伪'geosteering 曲线匹配打不过 flat 外推基线'

这是一个 kernels-only 的 Kaggle 代码赛:预测水平井的 TVT(真垂厚)。我认真做了十几版,最后公榜最优 RMSE 14.759,在约 4628 支队伍里排到三千四百多,倒数四分之一——铜牌线大概是 7.2,我离得很远,没进牌区

所以这篇不是战果展示。把它写出来,是因为一个”我认真做了、诚实承认没夺牌、但把为什么讲透了”的过程,比一个漂亮名次更值得留下。这里有三件事。

一、CV 口径错了,我优化的是幻觉

一开始我的本地交叉验证分数(MSE 一百七八十)和公榜分数(14.759)怎么都对不上,差了一个数量级。查下来是两个口径错误叠在一起:

  1. 公榜只在原本缺失的那些行上评分。 提交样例里 100% 的行都是待预测的空值,而我的 CV 是在全部训练行上算的——里面混了大量”已知答案、残差接近 0”的行,把误差稀释得看不出真实水平。
  2. 榜单显示的”MSE”其实是 RMSE。 我把本地 MSE 开个平方根,sqrt(237) ≈ 15.4,一下就和公榜对上了。

修法是:CV 只在原缺失行上算、按井分组做 leave-one-well-out、并且当 RMSE 算。教训很硬——在校准评估口径之前,你所有的”这版更好”都可能是在对着错误的分布优化。 我前面好几版的进退,有一部分就是白忙。

二、一处数据泄漏,我发现了,又亲手证伪了

排查时发现训练目录里藏着和三口测试井文件名完全相同、坐标差为 0、逐行数值一模一样的完整未打码版本——理论上可以直接查到答案。

但有个矛盾:如果泄漏真能用,应该能刷到接近 0 分,可公榜榜首才 4.859。于是我没有直接用它去刷分,而是构造了一个”泄漏解”提交上去验证:结果提交状态显示完成,但公榜分返回空白。

这就把泄漏证伪了:kernels-only 代码赛评分时是用隐藏的真实测试集重新跑的,我在训练目录里看到的那批”测试井”,根本不是评分用的同一批。这个结论很反直觉,也很重要——你能看到的 test 集不等于评分集,基于它做的一切 CV,都可能在对着错误的分布优化(又一次回到第一件事的教训)。

三、一个负面结果:曲线匹配打不过一条平线

这道题我一开始按”地质导向(geosteering)“去想,以为要做井间的曲线插值匹配。做进去才发现题目结构是另一回事:每口井开头一小段(约 26%)是已知的,之后整段水平段全是空值一直到井尾——这是纯前向外推,不是插值

于是最强的一个基线简单到离谱:保持已知段最后一个 TVT 值一路平推(flat 外推),RMSE 就有 14.7~15.9。 我随后试遍了值匹配、Viterbi、DTW、仿射标定、形状匹配、跨井漂移的 ML 模型五大类方法,没有一个在诚实的 CV 上稳定打过这条平线

物理根因是真实的:井被主动导向、刻意保持 TVT 恒定留在目标层里,剩下的残差主要是导向误差,本身就接近不可预测;而用来定位的伽马曲线,在需要的那个 ±12 的细尺度上,噪声就有十几个单位,分辨率根本不够。

唯一一次在诚实 CV 上小胜 flat,是把几十个”单独都不如 flat”的弱特征全塞进一个 LightGBM+CatBoost 的组合模型,留井 CV 从 15.91 压到 13.62。但要如实标:这只是 CV 数字、没有真实上榜验证,而且离牌区需要的 7~9 仍然差得远。

诚实的边界

一个负面结果、加上把它为什么负讲清楚,有时候比一块奖牌更接近真实的工程——至少它诚实。