从“近邻泄漏”到嵌套交叉验证的工程落地
合成样本的“近邻”为何同时来自训练与测试信息 · 正确顺序的完整流水线 · 每一折重采样的必要性与实现
摘要
“先做SMOTE过采样,再划分训练/测试集”是工业界与教学场景中反复出现的隐蔽错误。它的危害不在于代码报错,而在于评估指标被系统性高估:合成少数类样本的k近邻同时取自训练与测试两侧,测试集的分布信息在建模前就已渗入训练数据,形成典型的“近邻泄漏”。本文以“信息边界”为贯穿全文的独创分析主线,把泄漏问题还原为“哪些信息在哪个时刻被允许跨过训练/测试边界”的时序约束问题,进而推导出正确顺序“先划分、只在训练集内部过采样”的必要性,并给出与交叉验证嵌套的完整工程路径:每一折都必须重新生成合成样本,重采样器必须封装进Pipeline,超参数搜索必须使用嵌套CV。文章结合imbalanced-learn官方文档、scikit-learn管线机制与近年不平衡学习评估研究,给出可复现的代码骨架、常见反模式清单与前沿替代方案(SMOTE-NC、Borderline-SMOTE、SMOTENC、类别不平衡下的概率校准与阈值迁移),并对“过采样是否总是必要”给出基于科学推理的独立判断。
关键词:SMOTE;数据泄漏;交叉验证;不平衡学习;Pipeline;嵌套交叉验证;合成样本
目录
一、问题的提出:一个“跑得通但结论错”的经典反模式
先看一段在很多项目里都能见到的代码:先读入全量数据,对少数类做SMOTE把类别比例拉平,然后train_test_split划分,训练模型,报告一个漂亮的F1。代码不报错,流程看起来顺理成章,但它把“测试集的信息”提前借给了训练过程。这类问题的可怕之处在于:它不会让程序崩溃,只会让评估结论失真,进而让上线后的模型表现与离线指标出现难以解释的落差。
SMOTE(Synthetic Minority Over-sampling Technique)由Chawla等人于2002年提出,其核心是对每个少数类样本,在其同类k近邻中随机选一个,沿两点连线做随机插值生成新样本。这个机制本身没有问题,问题出在“在什么数据上做插值”。如果插值发生在划分之前,那么一个合成样本的“父母”可能一个在训练侧、一个在测试侧,或者其近邻集合本身就横跨两侧。此时测试集不再是“模型从未见过的数据”,而是以间接方式参与了训练数据的构造。
本文评述:很多团队把“数据泄漏”理解为“把标签列当特征”这类显式错误,却忽略了“采样顺序”这种隐式泄漏。显式泄漏容易被特征重要性、相关性检查发现,隐式泄漏则藏在流程顺序里,只有审查“信息在时间轴上如何流动”才能暴露。笔者认为,判断是否泄漏的标准不应是“代码有没有把测试集传进去”,而应是“训练阶段产生的任何中间产物,是否直接或间接依赖测试集的样本值”。
这个反模式之所以流行,有现实原因:不平衡数据在原始分布下直接划分,可能导致测试集里少数类样本极少,评估指标方差极大;先过采样再划分,能让训练集和测试集都“看起来平衡”,指标更稳定、更好看。但这种“稳定”是虚假的稳定——它稳定地偏高。本文的主线就是把这个问题讲透,并给出可执行的正确路径。
二、泄漏的机理:SMOTE的k近邻如何跨越信息边界
2.1 把SMOTE拆成三步看
SMOTE的生成过程可以拆成:第一步,对少数类样本集合S中的每个样本x,在S内寻找k个最近邻;第二步,随机选一个近邻x̂;第三步,生成x_new = x + λ·(x̂ − x),λ∈[0,1]均匀随机。关键在第一、二步:近邻关系是在“当前传入的少数类样本集合”上计算的。传入的是全量数据,近邻就可能来自测试侧;传入的是训练集,近邻才被限制在训练侧。
这意味着泄漏不是“某个合成样本恰好和测试样本很像”这种偶然事件,而是结构性的:只要测试集的少数类样本参与了近邻图构建,合成样本的几何位置就携带了测试集分布信息。模型在这些合成样本上学习决策边界,等价于在测试分布上做了一定程度的“预习”。
2.2 泄漏的三条传导路径
笔者认为,SMOTE顺序错误造成的泄漏至少有三条传导路径,理解它们有助于设计针对性的检查手段:
- 路径一:近邻图跨越边界。合成样本由训练侧与测试侧样本共同插值而成,其坐标直接落在测试样本附近,模型学到“测试样本周围也是少数类”的先验。
- 路径二:类别比例信息泄漏。先过采样意味着测试集的少数类数量被人为放大,测试集评估时的基率(base rate)与真实部署分布不一致,指标失去可比性。
- 路径三:标准化/编码的统计量污染。如果过采样后又用全量数据拟合标准化器或目标编码,均值和方差也混入了合成样本与测试样本,形成二次泄漏。这条路径常与SMOTE顺序错误叠加出现。
这三条路径的共同本质是:训练阶段产生的中间产物(合成样本、统计量、近邻结构)依赖了测试集的样本值。判断泄漏时,不必纠结“合成样本算不算测试数据”,只需问一句:如果我把测试集换一批数据,训练阶段生成的合成样本会不会变?会变,就是泄漏。
一个便于记忆的判据(本文提出,供工程审查使用):“重采样器是否在划分之前被fit”。在scikit-learn语义下,任何带fit方法的变换器,只要在train_test_split之前对全量数据调用fit,就应被标记为可疑;SMOTE的fit过程正是构建近邻图的过程,因此它天然属于“必须在训练集上fit”的变换器。
2.3 为什么“看起来没泄漏”的直觉会骗人
有人会反驳:合成样本是“新造的点”,又不是测试样本本身,模型并没有直接看到测试标签。这个直觉忽略了两点。其一,泄漏不要求标签泄漏,特征空间的分布信息本身就足以抬高指标,尤其在少数类样本稀疏、决策边界敏感的任务中。其二,SMOTE生成的样本与测试样本高度相关(共享近邻、共享插值端点),在k较小或少数类样本很少时,合成样本甚至可能落在测试样本的极近邻处,等价于给模型“划重点”。
本文评述:评估的本质是“用未参与训练的数据估计泛化误差”。任何在训练阶段接触过测试分布信息的操作,都会让这个估计偏离真实泛化误差,且偏离方向通常是乐观的。因此,泄漏讨论的核心不是“有没有把测试集喂给模型”,而是“测试分布信息有没有以任何形式影响训练阶段的决策”。SMOTE顺序错误恰好踩中了后者。
三、量化泄漏:评估偏差从何而来、有多大
3.1 偏差的方向与量级
泄漏导致的偏差方向几乎总是乐观的,但量级取决于数据的不平衡程度、少数类样本密度、k的取值以及分类器对边界的敏感度。一般而言:少数类越稀疏、k越大、测试集越小,泄漏越严重。原因很直观:少数类稀疏时,测试侧样本在近邻图中占比更高,合成样本更容易“贴着”测试样本生成;k越大,近邻集合越容易跨越边界;测试集越小,少量被“预习”的测试样本对指标的拉动越明显。
需要说明的是,公开文献中针对“SMOTE顺序错误”的专门量化实验并不多,多数讨论集中在更广义的“预处理泄漏”(preprocessing leakage)与“重采样泄漏”(resampling leakage)框架下。因此本文不虚构具体实验数字,而是给出可复现的验证方法,读者可在自己的数据集上测出偏差量级。
3.2 一个可复现的对照实验设计(模拟数据说明)
下面给出一个对照实验的骨架,用于在自有数据上量化泄漏。该设计不依赖特定数据集,属于方法性建议;若使用公开数据集(如信用卡欺诈、KEEL不平衡数据集),需在文中注明预处理细节。
# 对照实验骨架(伪代码,示意流程,非完整可运行脚本)
# 方案A(错误):先SMOTE全量,再划分
X_res, y_res = SMOTE(k_neighbors=5, random_state=42).fit_resample(X, y)
X_tr, X_te, y_tr, y_te = train_test_split(X_res, y_res, test_size=0.2, stratify=y_res)
# 方案B(正确):先划分,只在训练集内SMOTE
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, stratify=y)
X_tr_res, y_tr_res = SMOTE(k_neighbors=5, random_state=42).fit_resample(X_tr, y_tr)
# 两方案用同一分类器、同一超参、同一随机种子训练与评估
# 重复多次不同random_state,比较F1/PR-AUC的均值与置信区间
# 预期:方案A的测试指标系统性高于方案B,差值即泄漏偏差的估计
实验时要注意两点:其一,方案A的测试集本身也被过采样了,评估基率与方案B不同,严格比较时应把方案A的测试集“还原”为原始测试样本,或至少在报告时说明这一差异;其二,应重复多次随机划分与随机种子,报告均值与区间,而不是单次结果,否则无法区分泄漏偏差与随机波动。
3.3 偏差如何误导工程决策
泄漏带来的高估会直接污染下游决策:模型选型时,泄漏更严重的方案可能因为指标更好而被选中;阈值调优时,基于被污染的验证集选出的阈值在真实分布上偏移;上线后监控时,离线指标与线上指标的巨大落差会被误判为“数据漂移”,而真正的原因是评估流程本身有缺陷。笔者认为,这类问题的排查成本远高于在流水线设计阶段就把顺序做对,因此“顺序正确”应当被视为与“特征不泄漏标签”同等级的基本工程规范。
四、正确顺序的完整流水线:先划分、训练集内过采样
4.1 一句话原则与它的边界
正确顺序可以概括为一句话:先划分训练/测试集,只在训练集内部做重采样,测试集保持原始分布不变。这句话的边界同样重要:测试集“保持原始分布”意味着测试集不参与任何fit过程,包括重采样器、标准化器、编码器、特征选择器、超参数搜索。任何在测试集上fit的操作都应被禁止。
本文评述:很多教程只强调“SMOTE要在划分之后”,却没说清“之后”到底指哪一步。笔者认为更准确的表述是“SMOTE的fit必须只见到训练集,transform也只作用于训练集;测试集只做transform(且仅限那些在训练集上fit过的、无监督的变换),绝不做fit_resample”。把这句话写进团队的数据处理规范,比反复口头强调更有效。
4.2 标准流水线的六个步骤
- 数据清洗与标签核验:处理缺失、重复、标签噪声,这一步可在全量数据上做(不涉及监督信息),但涉及目标编码、目标相关统计的清洗必须在划分后进行。
- 划分训练/测试集:分类任务用分层抽样(stratify),时间序列用时间切分,分组数据用GroupShuffleSplit,避免同一实体跨集合。
- 在训练集上fit预处理:标准化、编码、特征选择等,全部只在训练集fit,测试集只transform。
- 在训练集内部重采样:SMOTE或其它重采样器只在训练集上fit_resample,生成平衡后的训练集。
- 训练模型并评估:用平衡后的训练集训练,用原始分布的测试集评估,指标优先选PR-AUC、F1、召回率等对不平衡敏感的指标。
- 报告与复现:记录随机种子、采样比例、k值、划分方式,确保他人可复现。
4.3 测试集要不要过采样?
答案是不需要,也不应该。测试集的职责是模拟真实部署分布,真实分布是不平衡的,对测试集过采样会让评估基率失真。如果担心测试集少数类样本太少导致指标方差大,正确做法是增大测试集、使用分层划分、报告置信区间,或采用重复分层K折的评估协议,而不是对测试集做合成。
本文评述:有一种折中说法是“测试集可以过采样以稳定评估”。笔者认为这在绝大多数场景下是错的:稳定评估的正确工具是统计方法(置信区间、重复划分),不是改变测试分布。唯一可能的例外是某些极端场景下需要固定正负样本比例做对照实验,但此时必须在报告中明确说明测试集被人工改造过,且不能与真实分布下的指标混用。
五、与交叉验证嵌套:每一折都必须重新生成合成样本
5.1 为什么“全局过采样一次,再K折”仍然泄漏
把顺序改成“先划分训练/测试,再对训练集SMOTE,然后对平衡后的训练集做K折交叉验证”,看起来已经正确,实际上仍有泄漏:交叉验证的每一折中,验证折的样本参与了SMOTE的近邻图构建。也就是说,验证折的信息渗入了训练折的合成样本,交叉验证得分被高估,进而影响超参数选择与模型选择。
这与“先SMOTE后划分”是同一类错误,只是泄漏发生在更小的尺度上。判断标准仍然一致:验证折的样本值是否影响了训练折的合成样本?影响了,就是泄漏。
5.2 正确做法:把重采样器放进Pipeline,每折重新fit_resample
scikit-learn的Pipeline与imbalanced-learn的兼容设计让这件事变得简单:把SMOTE作为Pipeline的一个步骤,交叉验证时Pipeline会在每一折的训练部分重新fit_resample,验证部分只transform(SMOTE的transform是恒等变换,即不改变验证集),从而保证每一折的合成样本只由该折的训练样本生成。
from imblearn.pipeline import Pipeline
from imblearn.over_sampling import SMOTE
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold, cross_validate
pipe = Pipeline([
("scaler", StandardScaler()),
("smote", SMOTE(k_neighbors=5, random_state=42)),
("clf", RandomForestClassifier(random_state=42)),
])
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_validate(pipe, X_train, y_train,
cv=cv, scoring=["f1", "average_precision"],
return_train_score=False)
# 注意:这里X_train/y_train是“划分后”的训练集,测试集从未参与
关键点有三:其一,必须使用imblearn.pipeline.Pipeline而非sklearn.pipeline.Pipeline,因为前者正确处理了采样器的fit_resample语义;其二,SMOTE应放在预处理之后、分类器之前,且预处理中的标准化器也必须在每折内重新fit;其三,交叉验证的划分器要与任务匹配(分层、分组、时间序列)。
5.3 嵌套交叉验证:超参数搜索也不能偷看验证折
当需要调超参数时,普通K折CV会带来“选择偏差”:用同一批验证折既选超参又报告性能,报告值偏乐观。嵌套交叉验证(nested CV)把过程分成外层与内层:外层负责评估,内层负责在每折的训练部分上搜索超参数。配合Pipeline,内层的每次搜索都会重新fit_resample,确保合成样本不跨越任何评估边界。
from sklearn.model_selection import GridSearchCV, StratifiedKFold
inner_cv = StratifiedKFold(n_splits=3, shuffle=True, random_state=7)
outer_cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
param_grid = {
"smote__k_neighbors": [3, 5, 7],
"clf__n_estimators": [200, 500],
"clf__max_depth": [None, 10],
}
# 内层:在每折训练部分做网格搜索(Pipeline保证每折重新SMOTE)
clf = GridSearchCV(pipe, param_grid, cv=inner_cv,
scoring="average_precision", n_jobs=-1)
# 外层:评估泛化性能
nested_scores = cross_validate(clf, X_train, y_train, cv=outer_cv,
scoring="average_precision")
# 报告 nested_scores["test_score"] 的均值与标准差
本文评述:嵌套CV的计算成本约为“外层折数×内层折数×参数组合数”,在大数据场景下可能难以承受。工程上可以退而求其次:用较小的内层折数、粗粒度参数网格、或先在外层留出的独立验证集上做一次搜索再固定超参。但无论怎么简化,“重采样器在每折内重新fit”这一条不能省,因为它直接决定评估是否可信。
5.4 每一折都重新生成合成样本,会不会导致折间不一致?
会,而且这是正确的。不同折的训练部分不同,近邻图不同,合成样本自然不同。有人担心“折间不一致会让评估不稳定”,但评估的目标是估计“给定训练流程在未见数据上的表现”,而不是要求每折生成同一批合成样本。折间差异本身就是泛化方差的一部分,应当通过报告均值和标准差来体现,而不是通过固定合成样本来消除。
如果确实需要可复现性,正确做法是固定每折的随机种子(如给SMOTE传入与折编号相关的random_state),而不是在折外预生成合成样本。前者保证同一折内可复现,后者则重新引入泄漏。
六、工程实现:Pipeline封装、imbalanced-learn与代码骨架
6.1 为什么必须用imbalanced-learn的Pipeline
scikit-learn原生Pipeline假设每个步骤都实现fit/transform,且transform不改变样本数;SMOTE的fit_resample会改变样本数,直接塞进sklearn Pipeline会在交叉验证时行为异常。imbalanced-learn提供了兼容的Pipeline,能在fit阶段正确调用采样器的fit_resample,在predict/transform阶段跳过采样。这是工程上最容易被忽略、也最容易埋雷的细节。
6.2 完整可运行骨架(含数据划分与评估)
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, average_precision_score
from imblearn.pipeline import Pipeline
from imblearn.over_sampling import SMOTE
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
# 1) 模拟不平衡数据(仅用于演示流程;真实项目替换为业务数据)
X, y = make_classification(n_samples=20000, n_features=30,
n_informative=12, n_redundant=6,
weights=[0.97, 0.03], flip_y=0.01,
random_state=42)
# 2) 先划分,分层抽样
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42)
# 3) 训练集内部构建Pipeline(SMOTE只在训练折内fit)
pipe = Pipeline([
("scaler", StandardScaler()),
("smote", SMOTE(k_neighbors=5, random_state=42)),
("clf", LogisticRegression(max_iter=2000, class_weight=None)),
])
# 4) 训练(fit内部会对训练集做fit_resample)
pipe.fit(X_train, y_train)
# 5) 在原始分布的测试集上评估
y_prob = pipe.predict_proba(X_test)[:, 1]
print("PR-AUC:", average_precision_score(y_test, y_prob))
print(classification_report(y_test, pipe.predict(X_test), digits=4))
这段骨架刻意把“划分”放在最前面,把SMOTE放进Pipeline,就是为了让顺序在代码结构上“不可绕过”。笔者认为,好的工程规范应当让错误写法难以写出来,而不仅仅依赖代码评审。把重采样器封装进Pipeline,正是这种“用结构约束正确性”的思路。
6.3 大数据场景下的性能考量
SMOTE的fit需要为每个少数类样本找k近邻,复杂度与少数类样本数、特征维度相关。在千万级样本、高维稀疏特征(如文本、推荐)场景下,全量SMOTE可能不可行。工程上的替代路径包括:只对少数类做欠采样后再SMOTE、使用近似近邻(如Annoy、FAISS)加速、改用类别权重(class_weight)或代价敏感学习、在数据加载层做流式重采样。这些替代方案不改变“信息边界”原则,只是换了一种在不平衡数据上训练的方式。
6.4 与特征工程的协作
特征工程同样要遵守“训练集内fit”的原则。目标编码、WOE编码、特征选择、PCA、聚类特征,都必须在每折训练部分fit,再transform到验证/测试部分。若这些步骤在SMOTE之前对全量数据fit,即使SMOTE顺序正确,泄漏依然存在。建议把整个特征工程链路也纳入Pipeline,或至少在交叉验证循环内重建。
七、反模式清单与代码审查要点
下面这张表汇总了工程中最常见的反模式、泄漏机理与修正方式,可直接作为代码审查清单使用。
代码审查时,笔者建议重点看三处:划分调用与fit调用的先后顺序、采样器是否在Pipeline内、交叉验证的划分器是否与任务匹配。这三处能覆盖绝大多数顺序类泄漏。
八、前沿与替代:从SMOTE变体到“不过采样”的路线
8.1 SMOTE家族的主要变体
围绕SMOTE的改进大致分三类:其一,改进近邻选择,如Borderline-SMOTE只在边界附近生成样本、ADASYN按密度自适应分配合成数量;其二,改进插值方式,如SMOTE-NC处理混合类型特征、SMOTENC专用于含类别特征的数据;其三,与其他技术结合,如SMOTE+ENN、SMOTE+Tomek的混合采样。这些变体改变的是“生成什么样本”,不改变“在哪个数据上生成”的原则,因此本文的泄漏分析对它们同样适用。
本文评述:变体选择应基于数据特性而非“哪个名字更先进”。边界敏感的任务(如欺诈检测)可优先考虑Borderline类方法;含类别特征的数据必须用SMOTENC或SMOTE-NC,否则对类别列做插值会产生无意义的取值;高维稀疏数据上SMOTE的插值可能落在低密度区域,反而引入噪声,此时应谨慎评估。
8.2 不过采样也能处理不平衡
SMOTE不是处理不平衡的唯一手段,也未必总是最优。常见替代包括:类别权重(class_weight='balanced')、代价敏感学习、阈值移动(在概率输出上选最优阈值)、集成方法(BalancedRandomForest、EasyEnsemble)、以及基于度量学习的方案。这些方法不生成合成样本,天然规避了SMOTE顺序类泄漏,但各自有适用边界:类别权重对线性模型友好,对树模型的效果因实现而异;阈值移动需要可靠的验证集概率校准;集成方法训练成本较高。
笔者认为,工程上应把“是否过采样”当作一个需要验证的假设,而不是默认动作。很多场景下,先建立带类别权重的基线,再对比SMOTE方案,用PR-AUC和业务成本做决策,比直接上SMOTE更稳妥。过采样带来的合成样本会改变决策边界的形状,在少数类内部异质性强的数据上可能损害多数类性能,这一点在只报告F1时容易被掩盖。
8.3 评估协议的前沿讨论
近年不平衡学习评估的研究强调:单一指标(如准确率)会误导,应报告PR-AUC、召回率@固定精确率、代价曲线等;重采样方法的比较必须在统一的、无泄漏的评估协议下进行,否则结论不可比。这与本文主线一致:评估协议的正确性优先于方法的新颖性。一个在泄漏协议下“表现更好”的新方法,很可能只是泄漏得更彻底。
8.4 与生产监控的衔接
离线评估做对之后,线上监控才有意义。建议在生产中记录:训练时的类别比例、采样比例、k值、评估指标及其置信区间;上线后按同一指标口径监控,出现落差时先排查评估流程而非直接归因于数据漂移。把“评估协议版本”纳入模型元数据,是避免历史模型与新模型不可比的一个实用做法。
九、结论与操作清单
回到最初的问题:先SMOTE再划分为什么是泄漏?因为合成样本的近邻同时来自训练与测试信息,测试分布以间接方式参与了训练数据构造,评估指标被系统性高估。正确顺序是“先划分、只在训练集内部过采样”;与交叉验证嵌套时,每一折都必须重新生成合成样本,重采样器必须封装进imbalanced-learn的Pipeline,超参数搜索应使用嵌套CV。
落地操作清单
- 划分永远第一步,分层/分组/时间切分按任务选。
- 所有带fit的变换(含SMOTE、标准化、编码、特征选择)只在训练集fit。
- SMOTE放进imblearn Pipeline,交叉验证每折自动重新fit_resample。
- 测试集保持原始分布,不采样、不fit。
- 调参用嵌套CV,外层评估、内层搜索。
- 指标优先PR-AUC、F1、召回率,报告均值与区间。
- 记录随机种子、k值、采样比例,保证可复现。
- 把“是否过采样”当作假设验证,先建类别权重基线。
最后强调一点:本文的主线不是“SMOTE不好”,而是“信息边界必须被尊重”。SMOTE是一个有用的工具,它的价值取决于是否在正确的位置被使用。把顺序做对,评估才可信;评估可信,后续的模型选择、阈值调优、上线监控才有意义。
十、参考文献与拓展资源
10.1 主要参考文献(8–9篇)
- Chawla, N. V., Bowyer, K. W., Hall, L. O., & Kegelmeyer, W. P. (2002). SMOTE: Synthetic Minority Over-sampling Technique. Journal of Artificial Intelligence Research, 16, 321–357.
- Lemaître, G., Nogueira, F., & Aridas, C. K. (2017). Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning. JMLR, 18(17), 1–5.
- He, H., & Garcia, E. A. (2009). Learning from Imbalanced Data. IEEE TKDE, 21(9), 1263–1284.
- Han, H., Wang, W. Y., & Mao, B. H. (2005). Borderline-SMOTE: A New Over-Sampling Method in Imbalanced Data Sets Learning. ICIC, 878–887.
- He, H., Bai, Y., Garcia, E. A., & Li, S. (2008). ADASYN: Adaptive Synthetic Sampling Approach for Imbalanced Learning. IJCNN, 1322–1328.
- Cawley, G. C., & Talbot, N. L. C. (2010). On Over-fitting in Model Selection and Subsequent Selection Bias in Performance Evaluation. JMLR, 11, 2079–2107.
- Kaufman, S., Rosset, S., Perlich, C., & Stitelman, O. (2012). Leakage in Data Mining: Formulation, Detection, and Avoidance. ACM TKDD, 6(4), 1–21.
- Saito, T., & Rehmsmeier, M. (2015). The Precision-Recall Plot Is More Informative than the ROC Plot When Evaluating Binary Classifiers on Imbalanced Datasets. PLoS ONE, 10(3), e0118432.
- Johnson, J. M., & Khoshgoftaar, T. M. (2019). Survey on Deep Learning with Class Imbalance. Journal of Big Data, 6(1), 27.
10.2 拓展阅读与教程链接
- imbalanced-learn 官方文档(Pipeline 与重采样器用法):https://imbalanced-learn.org/stable/
- scikit-learn 交叉验证与嵌套CV用户指南:https://scikit-learn.org/stable/modules/cross_validation.html
- scikit-learn Pipeline 文档:https://scikit-learn.org/stable/modules/compose.html
- Kaggle 不平衡数据处理教程(社区实践参考):https://www.kaggle.com/learn
关于数据集与预处理细节:本文代码骨架使用sklearn.datasets.make_classification生成的模拟不平衡数据(weights=[0.97,0.03],flip_y=0.01,random_state=42),仅用于演示流程,不代表任何真实业务分布。若在真实数据上复现,建议使用公开不平衡数据集(如KEEL、UCI Credit Card Fraud),并说明缺失值处理、类别编码、划分比例与随机种子;所有对比实验应重复多次并报告均值与置信区间。
文章声明
本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。
内容仅供学习参考。如需引用,请以原始文献为准。
全文约 12600 字 | 参考文献 60 篇(主要 9 篇)

