不平衡数据集交叉验证洗牌后F1反而更高,原因何在?
不平衡数据集交叉验证:洗牌与不洗牌的F1得分差异问题
我正在处理一个不平衡数据集,奇怪地发现交叉验证时若对数据洗牌,得到的F1 score较高;若不洗牌,F1 score则较低。以下是我使用的交叉验证函数:
def train_cross_v(md,df_train,n_folds=5,shuffl=False): X,y=df_train.drop([variable],axis=1),df_train[variable] cv =StratifiedKFold(n_splits=n_folds,shuffle=shuffl) scores = cross_val_score(md,X,y, scoring='f1', cv=cv, n_jobs=-1) y_pred=cross_val_predict(md,X,y, cv=cv, n_jobs=-1) print(' f1: ',scores,np.mean(scores)) print(confusion_matrix(y_pred,y)) return np.mean(scores)
洗牌时,F1约为0.82:
nfolds=5 train_cross_v(XGBClassifier(),df_train,n_folds=nfolds,shuffl=True) f1: [0.81469793 0.82076749 0.82726257 0.82379249 0.82484862] 0.8222738195197493 [[23677 2452] [ 1520 9126]] 0.8222738195197493
不洗牌时的结果:
nfolds=5 train_cross_v(XGBClassifier(),df_train,n_folds=nfolds,shuffl=False) f1: [0.67447073 0.55084022 0.4166443 0.52759421 0.64819164] 0.5635482198057791 [[21621 5624] [ 3576 5954]] 0.5635482198057791
我原本认为洗牌能消除数据顺序相关依赖,更能评估模型真实性能,且通常洗牌后性能指标会更低,但我的情况恰好相反:洗牌后F1更高,且测试集预测值无变化。这可能是什么问题?
问题分析
原始数据的类别特征分布失衡:虽然用了
StratifiedKFold保证每折的类别比例与整体一致,但如果原始数据是按类别或相关特征排序的(比如多数类集中在前半段,少数类集中在后半段),不洗牌时,部分折的训练集里少数类样本的特征分布会过于集中,模型无法充分学习到少数类的判别模式。洗牌后,每折训练集的少数类样本特征分布更均匀,模型能更好捕捉少数类特征,从混淆矩阵能明显看出:不洗牌时少数类召回率仅约51%,洗牌后提升至约78%,直接拉高了对少数类敏感的F1得分。数据顺序引入伪相关性:如果数据是按采集批次、时间等非分类维度排序的,同一折内的数据可能带有相同的噪声或偏置(比如某批次特征普遍偏高),模型训练时会学到这种批次特征而非真实分类特征,跨折验证时就会失效。洗牌打破了这种顺序依赖,让模型学习到通用的分类特征,性能自然提升。
对“洗牌后性能更低”的认知误区:这种预期只适用于数据本身存在有意义顺序结构的场景(比如时间序列,洗牌会破坏时序依赖)。你的数据显然没有这种有效顺序,反而顺序带来了数据分布偏差,洗牌纠正了偏差,因此性能反而更高。
内容的提问来源于stack exchange,提问作者Sunny
相关产品推荐
相关产品推荐

