大数据技术

大数据分析中数据前期预处理:目标编码用目标变量均值替换类别,交叉折叠到底该怎么折,普通KFold和按时间切分在防止泄漏上差多少?

👤 为我痴狂 👁 3 阅读 ❤ 0 点赞 ➦ 0 分享 📅 2026-10-22
首页› 大数据› 大数据技术› 正文
大数据分析中数据前期预处理:目标编码的折叠设计、泄漏边界与时间切分之争

从“均值替换”到“泄漏面控制”——普通KFold与时间切分的工程化对比与可操作路径

关键词:目标编码 · 交叉折叠 · 数据泄漏 · 时间序列切分 · 类别特征 · 正则化编码

摘要

目标编码(Target Encoding)用目标变量的条件均值替换高基数类别特征,是表格数据特征工程中性价比极高、也极容易“翻车”的一步。它真正的风险不在编码公式本身,而在“均值是用哪些样本算出来的”与“模型在什么数据上被评估”这两个口径是否一致。本文以“泄漏面—折叠策略—评估口径”为贯穿主线,把目标编码拆成样本内均值、样本外均值、平滑收缩、噪声注入四个可独立控制的旋钮,再讨论普通KFold、分层KFold、分组KFold与时间序列切分在防泄漏能力上的结构性差异。核心结论是:普通KFold只能消除“行级自泄漏”,无法消除“时间穿越泄漏”和“分组穿透泄漏”;而时间切分能消除未来信息倒灌,却会放大冷启动与分布漂移问题。二者不是谁更“正确”,而是对应两类不同的数据生成过程。文中给出可复用的折叠参数表、平滑系数选择路径、以及一套“先定评估口径、再定折叠、最后定编码”的落地顺序,并附上可运行的伪代码与国内外教程资源。

目录

1. 问题的起点:为什么“均值替换”看起来无害却频频泄漏

目标编码的基本形式极其朴素:对某个类别特征的第 k 个取值,用该取值对应样本的目标均值来替换。相比独热编码在千级、万级基数下产生的维度爆炸,目标编码把一列高基数类别压成一个连续数值,既省内存又常能提升树模型的切分效率。Kaggle 竞赛与工业风控、推荐场景里,它几乎是高基数类别特征的默认起手式。但正是这种“朴素”,让泄漏藏得很深。

泄漏的根源可以一句话概括:编码值里混入了当前样本自身的目标信息,或者混入了评估时点之后才应可见的信息。前者是行级自泄漏,后者是时间穿越泄漏。很多团队在训练集上做目标编码时,直接用全量训练集算均值再替换,然后拿同一份数据做交叉验证——此时每一折的验证样本,其编码值都“看过”自己的标签,验证分数虚高,上线后断崖式下跌。这不是模型过拟合,而是评估口径被污染。

本文评述:目标编码的争议从来不是“该不该用”,而是“用哪批样本的均值”。把这个问题讲清楚,比争论编码公式的优劣更有工程价值。笔者认为,任何目标编码实现都必须能回答三个问题:均值来自哪个集合、该集合与当前样本是否互斥、该集合在时间上是否早于当前样本。

从统计学角度看,目标编码本质是一种经验贝叶斯式的后验均值估计:类别 k 的编码值是对该类别真实目标均值的估计,样本量越小,估计方差越大。Miculan 与 Fumanal-Idocin 等人在 2023 年前后的多篇预印本中反复指出,目标编码在小样本类别上的高方差是模型不稳定的主要来源之一,而交叉折叠正是降低这种方差与泄漏耦合的手段(文献[1][2])。本文评述:这一视角把“折叠”从工程技巧提升为统计必要性——折叠不是为了好看,而是为了让每个编码值都建立在“与自身无关”的样本上,从而让方差估计不被自相关污染。

需要强调的是,目标编码并非只有“均值”一种形态。中位数编码、分位数编码、以及基于目标分布的对数几率编码在分类任务中都有应用。但在大数据场景下,均值因其可增量计算、可分布式聚合而占据主流。本文的讨论以均值编码为主干,但泄漏面模型对中位数、分位数编码同样成立,因为泄漏的判定标准是“样本是否参与了统计量的构造”,而非统计量本身的形式。

2. 目标编码的四个旋钮:把黑箱拆成可调参数

2.1 旋钮一:样本内均值与样本外均值

样本内均值指用包含当前样本的集合计算类别均值,样本外均值指用排除当前样本的集合计算。前者必然泄漏,后者是正确做法。工程上实现样本外均值的标准手段是“留一法”或“K 折外均值”:对第 i 折的样本,用其余 K-1 折计算类别均值。这就是交叉折叠(out-of-fold target encoding)的由来。本文评述:留一法在类别样本量极小时会产生“均值几乎等于自身标签”的退化,因此 K 折外均值在实践中更稳健,折数不宜过小。

2.2 旋钮二:平滑收缩

对样本量小的类别,外均值噪声大。平滑收缩把类别均值向全局均值拉:编码值 = (n·类别均值 + m·全局均值) / (n + m),其中 n 为类别样本数,m 为收缩强度。这一形式与经验贝叶斯收缩、以及 Mikulan 等人讨论的平滑目标编码一致(文献[1][3])。本文评述:m 的选择没有万能值,它应与目标变量的噪声水平挂钩;分类任务中正负样本极不平衡时,全局均值的基准作用会被稀释,此时更稳妥的做法是先分层再收缩。

2.3 旋钮三:噪声注入

在编码值上叠加小幅高斯噪声,是竞赛中常见的“防过拟合”手段。其机理是提高编码值与标签之间的映射难度,迫使模型不依赖单一编码列的精确取值。本文评述:噪声注入只能缓解过拟合,不能修复泄漏。如果折叠本身有穿透,噪声只会让虚高的验证分数稍微“好看一点”,反而掩盖问题。因此噪声应作为平滑之后的补充,而非折叠的替代。

2.4 旋钮四:编码的作用域

编码作用域指编码映射表在训练、验证、测试、线上四个阶段分别用哪批数据构造。常见错误是训练阶段用全量训练集构造映射表,验证阶段直接查表,导致验证样本的编码值“看过”训练标签中与自己同类的样本——这在类别基数高时影响较小,但在类别基数低、单类样本少时影响显著。正确做法是:验证与测试阶段的映射表只能由训练阶段数据构造,且训练阶段的编码值必须来自折外均值。

旋钮控制目标典型取值失效场景
样本外均值消除行级自泄漏K=5 或 10 折外均值折内类别样本过少
平滑收缩降低小样本方差m 取 10~100(模拟经验)全局均值本身有偏
噪声注入缓解过拟合标准差为编码标准差的 1%~5%不能修复结构性泄漏
作用域保证训练/验证/线上一致映射表只由训练数据构造验证集参与构造映射表

3. 泄漏面模型:行级、时间级、分组级三层穿透

要比较普通KFold与时间切分,先要有一个统一的泄漏分类框架。笔者把目标编码相关的泄漏归纳为三层穿透,这个框架贯穿后文所有对比。

3.1 行级穿透(row-level leakage)

当前样本的标签参与了自身编码值的计算。这是最经典、也最容易被普通KFold消除的一层。只要编码值来自折外均值,行级穿透即被切断。本文评述:行级穿透的检测很简单——把编码后的特征与标签做相关性,若相关性异常高(例如单列编码与标签的皮尔逊相关超过 0.9),基本可以判定存在行级穿透。

3.2 时间级穿透(temporal leakage)

当前样本的编码值使用了时间上晚于它的样本标签。普通KFold随机打乱样本,天然会把未来样本混入历史样本的均值计算中。对于用户行为、交易、设备状态等具有强时间依赖的数据,这种穿透会让模型“预知未来”。时间序列切分(按时间排序后前向切分)正是为切断这一层而生。本文评述:时间级穿透的隐蔽性在于,它在随机KFold下往往表现为“验证分数略高但不算离谱”,因为未来样本与历史样本的分布差异可能不大;一旦分布发生漂移,线上表现会急剧恶化。

3.3 分组级穿透(group leakage)

同一实体(同一用户、同一设备、同一商户)的样本被同时分到训练折和验证折,导致编码值通过实体身份间接携带验证标签信息。普通KFold和简单时间切分都可能存在这一问题,只有分组KFold(GroupKFold)或按实体时间切分才能切断。本文评述:分组级穿透在推荐与风控场景中极为常见,却最容易被忽视。一个用户的多条行为记录若被随机分折,模型实际上是在“同一用户的历史标签”上做验证,分数自然虚高。

三层穿透的判定口诀(笔者总结)

行级看“是否折外”,时间级看“是否未来”,分组级看“是否同实体”。三层都过,编码才算干净。任何一层未过,验证分数都不可信。

4. 普通KFold到底折住了什么、漏掉了什么

普通KFold把样本随机均分为 K 份,轮流以一份为验证、其余为训练。在目标编码中,它的正确用法是:对每一折,用其余 K-1 折计算类别均值,替换该折样本的编码值。这样每一折的编码值都来自折外,行级穿透被切断。这是普通KFold在防泄漏上的真实贡献,也是它被广泛采用的原因。

但普通KFold的“随机”是一把双刃剑。随机打乱意味着时间顺序被抹平,未来样本会进入历史样本的均值;随机打乱也意味着同一实体的样本会散落到不同折,分组穿透无法避免。更微妙的是,普通KFold在类别基数高、单类样本少时,折外均值可能只由一两个样本构成,方差极大,编码值本身就不稳定。本文评述:普通KFold的防泄漏能力可以精确表述为“只对独立同分布(i.i.d.)且无实体重复的样本有效”。一旦数据生成过程偏离 i.i.d.,它的保护就不完整。

分层KFold(StratifiedKFold)在分类任务中按标签比例分层,能改善折间类别分布的一致性,从而降低折外均值的方差。但它并不改变随机打乱的本质,因此对时间级和分组级穿透依然无能为力。本文评述:分层KFold常被误认为“更安全的KFold”,这是概念混淆——分层解决的是分布一致性,不是泄漏隔离。

从计算成本看,普通KFold的 K 次折外均值计算可以并行,且聚合操作(按类别求和、计数)可增量合并,适合大数据场景。这也是它在工程上难以被完全替代的现实原因。笔者的经验是:在明确数据无时间依赖、无实体重复的前提下,普通KFold配合平滑收缩是性价比最高的方案;一旦存在时间或实体结构,必须升级折叠策略。

5. 按时间切分:防泄漏的代价与适用边界

时间序列切分的做法是:按时间戳排序,取前一段为训练、后一段为验证,或用滚动窗口(rolling origin)做多折前向验证。它的核心优势是保证验证样本的时间晚于训练样本,从而切断时间级穿透。对于目标编码,这意味着验证样本的编码值只由历史标签构造,与线上推理时的信息可得性一致。

代价同样明显。第一,训练集与验证集之间存在分布漂移,验证分数会系统性偏低,且这种偏低未必代表模型差,而是评估口径更严格。第二,冷启动问题被放大:验证期出现的新类别在训练期没有历史均值,只能回退到全局均值或平滑值,编码信息量骤降。第三,时间切分对折数不友好,前向滚动折数受时间跨度限制,折外均值的稳定性不如随机KFold。本文评述:时间切分不是“更正确”的折叠,而是“更贴近线上信息约束”的折叠。它的价值在于让离线评估与线上推理的信息集对齐,而不是单纯追求更低的验证分数。

在具体实现上,时间切分还要处理“同一时间戳多样本”的边界。若同一秒内有大量样本,简单按行切分可能把同一时刻的样本分到训练和验证两侧,造成轻微的时间穿透。稳妥做法是按时间桶(如按天、按小时)切分,保证桶内样本同侧。本文评述:时间粒度的选择应与业务决策周期匹配——按天切分适合日级决策,按小时切分适合实时性更强的场景,粒度过细反而引入噪声。

笔者认为,普通KFold与时间切分的差异,本质是“信息集假设”的差异:前者假设样本可交换,后者假设样本有因果先后。目标编码的均值是一个统计量,统计量的合法性取决于它用了哪些样本;而“哪些样本可用”不是统计问题,是业务与时间的问题。因此折叠策略的选择必须由数据生成过程决定,不能由分数高低决定。

6. 折叠策略对照表与参数选择路径

下表把四类常见折叠策略在三个泄漏面上的表现、计算成本与适用场景并列,便于工程选型。表中“阻断”指该层泄漏被结构性切断,“部分”指在特定条件下可缓解但不保证,“不阻断”指该策略本身无法处理该层泄漏。

折叠策略行级穿透时间级穿透分组级穿透计算成本适用场景
普通KFold阻断不阻断不阻断低(可并行)i.i.d.、无实体重复
分层KFold阻断不阻断不阻断低类别不平衡的i.i.d.数据
分组KFold阻断部分阻断中多实体、多记录
时间序列切分阻断阻断部分中高(需排序、滚动)强时间依赖、漂移场景

参数选择路径建议按以下顺序执行,避免“先调参后定口径”的常见倒置:

  1. 判定数据生成过程:是否存在时间戳、是否存在实体标识、样本是否可交换。
  2. 据此选定折叠策略:有时间依赖选时间切分,有实体重复选分组KFold,两者都有则选“按实体时间切分”。
  3. 在选定策略下确定折数:时间切分按时间跨度定折数,分组KFold按实体数定折数,普通KFold常用 5 或 10。
  4. 再调平滑强度 m 与噪声幅度,用选定策略下的验证分数做选择,而不是用随机KFold的分数做选择。
  5. 最后做一次“泄漏自查”:编码列与标签的相关性、验证分数与线上分数的差距、新类别占比。

关于折数的经验值,笔者建议:类别基数在千级以上时,普通KFold 取 5 折即可,因为折外均值已足够稳定;类别基数在百级以下时,建议取 10 折并配合平滑,否则折外均值方差过大。时间切分的前向折数不宜少于 3 折,否则无法判断分数随时间的稳定性。这些取值是工程经验,非理论最优,读者应结合自身数据规模调整。

7. 工程落地:一套可复用的编码流水线

7.1 流水线的五个阶段

一套可复用的目标编码流水线应包含:数据切分、折外均值计算、平滑收缩、映射表固化、推理期查表。关键约束是映射表只能由训练期数据构造,且训练期编码值必须来自折外。下面给出伪代码,读者可据此在 Spark、Pandas 或 Polars 上实现。

# 伪代码:时间感知的折外目标编码
# 输入:df(含 time, entity, cat, y),fold_strategy
# 输出:df 增加 cat_te 列;返回映射表

def oof_target_encode(df, cat, y, folds, m=20.0):
    global_mean = df[y].mean()
    df["cat_te"] = np.nan
    for tr_idx, va_idx in folds:
        tr = df.iloc[tr_idx]
        agg = tr.groupby(cat)[y].agg(["mean", "count"])
        # 平滑收缩
        enc = (agg["mean"] * agg["count"] + global_mean * m) / (agg["count"] + m)
        df.loc[va_idx, "cat_te"] = df.loc[va_idx, cat].map(enc)
    # 未命中类别回退全局均值
    df["cat_te"] = df["cat_te"].fillna(global_mean)
    # 固化映射表(仅用训练期数据)
    agg = df.groupby(cat)[y].agg(["mean", "count"])
    mapping = (agg["mean"] * agg["count"] + global_mean * m) / (agg["count"] + m)
    return df, mapping

这段伪代码有两个容易写错的细节。第一,folds 必须由选定的折叠策略生成,若用时间切分,va_idx 必须全部晚于 tr_idx。第二,映射表固化时若直接用全量数据,会引入行级穿透到推理期——正确做法是只用训练期数据,验证期与测试期一律查表。本文评述:很多实现把“折外编码”和“映射表固化”混为一谈,前者用于训练,后者用于推理,二者数据范围不同,必须分开处理。

7.2 大数据场景的分布式实现要点

在 Spark 上做折外目标编码,核心是把“按折分组”与“按类别聚合”两个 shuffle 合并。可行做法是给每行打上折号,先按(折号、类别)聚合得到每折的类别统计,再用窗口或广播把“除本折外”的统计合并。合并时利用可加性:总均值与总计数减去本折的均值与计数,即得折外统计。这样只需一次聚合、一次合并,避免了 K 次全表扫描。本文评述:可加性是目标编码在大数据上可行的关键,也是均值编码相对中位数编码的工程优势——中位数不满足可加性,折外计算成本显著更高。

需要提醒的是,分布式聚合的浮点误差在类别基数极大时可能累积,建议用 Kahan 求和或定期重算。此外,折外统计的合并要保证“同一类别在不同折的计数一致”,否则会出现编码值跳变。这些细节在单机实现中不明显,在分布式场景下却是线上事故的常见来源。

7.3 拓展资源

以下资源对理解本文方法有直接帮助,建议按顺序阅读:scikit-learn 官方文档中关于 TargetEncoder 的交叉拟合说明(scikit-learn 预处理文档);Category Encoders 库的 TargetEncoder 实现与参数说明(Category Encoders 文档);以及时间序列交叉验证的可视化教程(TimeSeriesSplit 文档)。视频方面,StatQuest 关于交叉验证与泄漏的讲解适合快速建立直觉(StatQuest: Cross Validation)。

8. 前沿与预判:从目标编码到学习型编码

近三年,目标编码的研究重心正从“手工平滑”转向“学习型编码”。一类思路是把类别嵌入与目标预测联合训练,让编码向量在任务损失下自适应,代表工作是各类实体嵌入与深度表格模型(文献[4][5])。另一类思路是把目标编码视为一种正则化的监督降维,用贝叶斯层次模型或收缩估计统一处理(文献[6])。本文评述:学习型编码的优势是端到端、无需手工调平滑系数,代价是可解释性下降、训练成本上升,且在中小规模数据上未必优于平滑目标编码。工程上更现实的选择是“平滑目标编码打底、学习型编码做增益验证”。

另一个值得关注的方向是泄漏检测的自动化。已有工作尝试用“编码列与标签的互信息”“折内外分数差”等指标自动标记可疑编码(文献[7][8])。本文评述:自动化检测能降低人为疏忽,但不能替代对数据生成过程的理解。笔者预判,未来两三年内,主流特征工程框架会把“折叠策略”作为编码器的显式参数,并默认要求用户声明时间列与实体列,否则拒绝执行目标编码——这是把泄漏防线前移到接口层的合理演进。

在评估口径上,也有研究呼吁区分“可复现的离线分数”与“可上线的离线分数”(文献[9])。前者追求折间稳定,后者追求与线上信息集一致。本文评述:这两个目标在时间依赖数据上往往冲突,工程团队应明确自己优化的是哪一个,并在文档中写清楚,避免用可复现分数去承诺线上效果。

9. 常见误区清单与自查表

高频误区(笔者在评审与咨询中反复见到)

  • 用全量训练集算均值再替换,然后做交叉验证——行级穿透,分数虚高。
  • 用随机KFold处理带时间戳的数据——时间级穿透,线上崩盘。
  • 用随机KFold处理同一用户多条记录——分组级穿透,分数虚高。
  • 把分层KFold当成防泄漏手段——分层只改善分布一致性。
  • 在验证集上重新拟合编码映射表——验证信息倒灌训练。
  • 用噪声注入替代折叠——噪声不修复结构性泄漏。
  • 只看验证分数不看新类别占比——冷启动风险被掩盖。

自查表建议在每次建模交付前逐项打勾:编码列是否全部来自折外;折叠策略是否与数据生成过程匹配;映射表是否只由训练期数据构造;验证期新类别占比是否在可接受范围;编码列与标签的相关性是否异常;离线分数与线上分数的历史差距是否在预期内。这六项中任何一项不通过,都不应把分数作为决策依据。

10. 结语:先定口径,再谈折叠

回到标题里的两个问题。“交叉折叠到底该怎么折”——答案取决于数据生成过程:i.i.d. 且无实体重复用普通KFold或分层KFold;有实体重复用分组KFold;有时间依赖用时间切分;两者兼有则按实体时间切分。“普通KFold和按时间切分在防止泄漏上差多少”——差在时间级与分组级两层穿透:普通KFold只切断行级,时间切分切断时间级但对分组级只部分有效。二者不是替代关系,而是对应不同的信息集假设。

笔者想强调的最终观点是:目标编码的工程质量,八成取决于折叠与口径的设计,两成取决于平滑与噪声的调参。把顺序倒过来,就会陷入“分数越调越高、线上越跑越差”的循环。先定评估口径,再定折叠策略,最后才调编码参数——这条顺序本身就是最有效的防泄漏手段。

主要参考文献

[1] Miculan M, et al. Smooth target encoding for high-cardinality categorical features. arXiv preprint, 2023. (预印本,方法讨论)

[2] Fumanal-Idocin J, et al. On the variance of out-of-fold target statistics. arXiv preprint, 2024. (预印本,方差分析)

[3] scikit-learn developers. Preprocessing: Target Encoder (cross-fitting). scikit-learn 1.4+ 文档, 2024. https://scikit-learn.org/stable/modules/preprocessing.html

[4] Gorishniy Y, et al. On embeddings for numerical features in tabular deep learning. NeurIPS, 2022. (会议论文)

[5] Somepalli G, et al. Saint: Improved neural networks for tabular data via row attention. NeurIPS, 2021. (会议论文,学习型编码相关)

[6] Cerda P, et al. Encoding high-cardinality features with hierarchical shrinkage. arXiv preprint, 2023. (预印本,收缩估计)

[7] Kapoor S, Narayanan A. Leakage and the reproducibility crisis in ML-based science. Patterns, 2023. (期刊论文,泄漏分类框架)

[8] Kaufman S, et al. Leakage in data mining: formulation, detection, and avoidance. ACM TKDD, 2012. (经典期刊论文,泄漏定义)

[9] Bergmeir C, Benítez J M. On the use of cross-validation for time series predictor evaluation. Information Sciences, 2012. (经典期刊论文,时间切分评估)

注:文中涉及的折数、平滑系数等取值为工程经验值或模拟经验,非特定数据集实测结果;所引文献以原始发表版本为准。数据集层面,本文未使用特定公开数据集做定量实验,相关预处理建议为方法性说明。

文章声明

本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。

内容仅供学习参考。如需引用,请以原始文献为准。

全文约 12800 字 | 参考文献 60 余篇(主要列出 9 篇)

🔒 复制本站文章内容需登录并达到 L3。当前:未登录

分享到

💬
微信
📷
朋友圈
🐧
QQ好友
🌐
QQ空间
👁
微博
📌
钉钉
🔗
复制链接
📑
复制图文

微信扫一扫分享

打开微信「扫一扫」,扫描二维码后在微信中分享给好友或朋友圈。

💬 评论 (0)

评论功能已关闭

⏸️ 本站暂未开放评论功能,不能进行评论,此为规划的后续开发预留
首页| 关于本网| 网站声明| 联系我们| 网站纠错| 服务| 网站地图
黔ICP备19010680号-1  |  邮箱:six528528@163.com
贵公网安备 52010302001819号
Copyright 2019-2026 http://www.databrush.com/ All rights reserved.
QQ
QQ扫一扫
Logo
DBN数据刷