如何正确结合CalibratedClassifierCV与RandomOverSampler处理不平衡分类任务?
解决不平衡分类中CalibratedClassifierCV与上采样Pipeline结合的报错问题
问题根源
你的报错核心原因是训练集少数类样本总数(4个)小于交叉验证折数(5),导致StratifiedKFold(CalibratedClassifierCV默认的分类任务交叉验证策略)无法生成有效的分层折——分层交叉验证要求每个类在每个折中至少有1个样本,4个少数类样本无法分配到5个折里。拆分操作发生在上采样之前,因此即使使用了上采样Pipeline,依然会触发报错。
解决方案
针对该场景,推荐以下两种可靠调整方向:
方案1:降低交叉验证折数并显式指定分层策略
将cv折数调整为不超过少数类样本数(比如4折),同时显式使用StratifiedKFold并开启shuffle,确保拆分的随机性和分层合理性。这样既能满足分层拆分的要求,又能保证上采样仅在每折的训练阶段执行,不影响校准用的验证数据。
修改后的完整代码:
from sklearn.calibration import CalibratedClassifierCV from sklearn.naive_bayes import GaussianNB from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split, StratifiedKFold from imblearn.over_sampling import RandomOverSampler from imblearn.pipeline import Pipeline X, y = make_classification( n_samples=100, n_features=10, n_classes=2, weights=(0.95,), # 5%正样本 random_state=10, shuffle=True ) X_train, X_val, y_train, y_val = train_test_split( X, y, test_size=0.2, random_state=10, shuffle=True, stratify=y ) # 定义上采样+模型的Pipeline pipeline = Pipeline([ ("resampling", RandomOverSampler( sampling_strategy=0.2, random_state=10 )), ("model", GaussianNB()) ]) # 定义分层交叉验证策略,折数匹配少数类样本数 cv_strategy = StratifiedKFold(n_splits=4, shuffle=True, random_state=10) # 初始化校准分类器,样本量小时优先用sigmoid方法 m = CalibratedClassifierCV( base_estimator=pipeline, method="sigmoid", cv=cv_strategy, n_jobs=-1 ) m.fit(X_train, y_train) # 验证校准后的概率输出 print(m.predict_proba(X_val)[:5])
方案2:使用RepeatedStratifiedKFold(备选)
如果不想降低折数,可以使用RepeatedStratifiedKFold,通过重复分层拆分缓解样本不足的问题。比如设置n_splits=5, n_repeats=2,每次拆分时重新打乱数据,尽可能保证每个折都能分到少数类样本。但这种方法计算量会翻倍,样本极小时仍可能出现个别折无少数类的情况,需谨慎使用。
关键注意事项
- 上采样仅作用于训练阶段:imblearn的
Pipeline会自动区分fit和predict阶段,上采样只会在交叉验证的每折训练数据上执行,校准用的验证数据保持原始分布,保证了概率校准的有效性。 - 校准方法选择:样本量较小时优先使用
method="sigmoid"(Platt缩放),它是参数化方法,对样本量要求更低;isotonic是非参数方法,需要足够多的样本才能生成可靠的校准曲线。
内容的提问来源于stack exchange,提问作者Requin
相关产品推荐
相关产品推荐

