金融风控中的不平衡数据处理实战与优化策略

📅 2026/7/4 14:58:05
金融风控中的不平衡数据处理实战与优化策略
1. 数据准备与基线模型构建在处理信用违约预测这类不平衡数据集时数据准备和基线模型的建立是至关重要的第一步。我最近在一个金融风控项目中实践了完整的处理流程下面分享我的实战经验。1.1 数据预处理实战数据预处理是不平衡分类任务的基础需要特别注意类别不平衡对预处理的影响。以下是关键步骤的详细说明# 基础环境配置 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split # 解决中文显示问题 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 读取原始数据 raw_data pd.read_csv(credit_data.csv)分类特征处理技巧有序分类变量编码对于像Years in current job这类有明显顺序的变量使用映射编码保留顺序信息years_mapping { 1 year: 1, 1 year: 2, # ...其他映射 10 years: 11 } data[Years in current job] data[Years in current job].map(years_mapping)名义分类变量处理对于Purpose这类无顺序的变量使用独热编码但需注意编码后记得将布尔值转为整型保存新增的特征名供后续分析使用data pd.get_dummies(data, columns[Purpose]) new_features [col for col in data.columns if col not in raw_data.columns] for col in new_features: data[col] data[col].astype(int)缺失值处理经验对于数值特征使用中位数而非均值填充更稳健分类变量使用众数填充填充前务必检查每个特征的缺失比例# 连续特征用中位数填充 for feature in continuous_features: median_val data[feature].median() data[feature].fillna(median_val, inplaceTrue)注意在不平衡数据集中填充策略应考虑类别分布。我通常会分别计算每个类别的统计量然后按比例填充。1.2 基线模型建立与分析建立基线模型时随机森林是个不错的选择因为它对特征缩放不敏感且能自动处理特征交互。from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report # 数据分割 X data.drop(Credit Default, axis1) y data[Credit Default] X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # 基线模型训练 rf_baseline RandomForestClassifier(random_state42) rf_baseline.fit(X_train, y_train) # 评估 baseline_pred rf_baseline.predict(X_test) print(classification_report(y_test, baseline_pred))基线模型常见问题准确率陷阱在不平衡数据上准确率指标会严重误导。比如99%的准确率可能只是预测了多数类。召回率低下对少数类(违约客户)的识别率通常很低概率校准问题模型输出的概率可能不能反映真实风险解决方案思路采用更适合的评估指标(F1-score, AUC-PR)使用分层抽样确保训练/测试集的类别分布一致可视化混淆矩阵直观了解分类情况2. 数据层面的不平衡处理方法处理不平衡数据集时数据层面的方法是最直接有效的。我在多个金融风控项目中对比了各种采样方法下面是实战总结。2.1 过采样技术详解2.1.1 随机过采样(ROS)实战随机过采样虽然简单但使用时有许多注意事项from imblearn.over_sampling import RandomOverSampler ros RandomOverSampler(sampling_strategyauto, random_state42) X_ros, y_ros ros.fit_resample(X_train, y_train) # 检查采样效果 print(过采样后类别分布:\n, pd.Series(y_ros).value_counts())优缺点分析优点实现简单计算成本低适用于小规模数据集缺点容易导致过拟合可能放大噪声样本的影响实战建议当少数类样本绝对数量很少(如100)时可考虑先用ROS增加样本量再结合其他方法。2.1.2 SMOTE算法深度解析SMOTE是更高级的过采样技术通过合成新样本来丰富少数类from imblearn.over_sampling import SMOTE smote SMOTE( sampling_strategyauto, k_neighbors5, random_state42 ) X_smote, y_smote smote.fit_resample(X_train, y_train)SMOTE参数调优经验k_neighbors选择一般设为3-7之间的奇数对于高维数据可能需要增大可通过交叉验证选择最优值变种选择BorderlineSMOTE专注于边界样本SVMSMOTE使用SVM支持向量生成样本KMeansSMOTE先聚类再采样常见问题解决方案问题SMOTE生成无意义样本 解决先进行特征选择去除无关特征问题类别重叠严重 解决结合欠采样方法如SMOTEENN2.2 欠采样技术实践2.2.1 随机欠采样技巧随机欠采样虽然会丢失信息但在特定场景下仍有用武之地from imblearn.under_sampling import RandomUnderSampler rus RandomUnderSampler( sampling_strategyauto, random_state42 ) X_rus, y_rus rus.fit_resample(X_train, y_train)适用场景多数类样本量极大(如100万)计算资源有限多数类中有大量冗余样本改进方法结合聚类先对多数类聚类再从每个簇中采样集成方法多次欠采样构建多个模型再集成2.2.2 ENN数据清洗技术Edited Nearest Neighbors(ENN)是一种智能欠采样方法from imblearn.under_sampling import EditedNearestNeighbours enn EditedNearestNeighbours( n_neighbors3, kind_selall ) X_enn, y_enn enn.fit_resample(X_train, y_train)ENN工作原理对每个样本找K近邻如果多数类样本被近邻误分类则移除保留边界清晰的样本参数选择建议n_neighbors通常3-5数据量大时可增大kind_selall更严格mode更宽松2.3 混合采样策略SMOTE与ENN结合的SMOTEENN通常能取得更好效果from imblearn.combine import SMOTEENN smote_enn SMOTEENN( smoteSMOTE(sampling_strategyauto), ennEditedNearestNeighbours(sampling_strategyall), random_state42 ) X_smoteenn, y_smoteenn smote_enn.fit_resample(X_train, y_train)混合采样优势既增加少数类样本又清理多数类中的噪声获得更清晰的决策边界性能考量计算成本较高适合中小规模数据集可先在小样本上试验效果3. 算法层面的不平衡处理除了调整数据我们还可以通过改进算法本身来处理不平衡问题。我在实际项目中验证了多种算法层面的解决方案。3.1 代价敏感学习随机森林的class_weight参数是实现代价敏感学习的最简单方式rf_weighted RandomForestClassifier( class_weightbalanced, random_state42 ) rf_weighted.fit(X_train, y_train)权重设置策略自动平衡class_weightbalanced手动指定class_weight{0:1, 1:10} # 少数类权重是多数类的10倍基于业务成本计算误分类的实际成本按成本比例设置权重效果评估通常能提高召回率可能略微降低精确率整体F1-score会改善3.2 集成学习方法3.2.1 BalancedRandomForestimbalanced-learn库提供了专门处理不平衡数据的集成方法from imblearn.ensemble import BalancedRandomForestClassifier brf BalancedRandomForestClassifier( sampling_strategyauto, replacementTrue, random_state42 ) brf.fit(X_train, y_train)核心原理每棵树训练时对多数类欠采样最终结果由多棵树投票决定相当于集成了多个平衡的子模型3.2.2 EasyEnsemble另一种有效的集成方法from imblearn.ensemble import EasyEnsembleClassifier ee EasyEnsembleClassifier( n_estimators100, sampling_strategyauto, random_state42 ) ee.fit(X_train, y_train)特点对比方法采样策略计算成本适用场景BalancedRF每棵树欠采样中等多数类样本量大EasyEnsemble多次欠采样Boosting较高极端不平衡4. 评估与阈值优化在不平衡分类问题中评估指标的选择和阈值的优化同样重要。下面分享我在实际项目中的评估经验。4.1 合适的评估指标不要使用准确率推荐使用以下指标混淆矩阵直观展示各类别的分类情况Precision-Recall曲线比ROC更适合不平衡数据F1-score精确率和召回率的调和平均MCC(Matthews相关系数)综合考量所有类别from sklearn.metrics import matthews_corrcoef mcc matthews_corrcoef(y_test, y_pred) print(fMCC得分: {mcc:.4f})4.2 概率阈值优化通过调整分类阈值可以平衡精确率和召回率from sklearn.metrics import precision_recall_curve # 获取预测概率 y_proba model.predict_proba(X_test)[:, 1] # 计算PR曲线 precisions, recalls, thresholds precision_recall_curve(y_test, y_proba) # 寻找最佳F1阈值 f1_scores 2 * (precisions * recalls) / (precisions recalls) best_idx np.argmax(f1_scores) best_threshold thresholds[best_idx]阈值选择策略业务导向高风险领域偏向高召回率低成本场景偏向高精确率数据驱动最大化F1-score保证召回率不低于某个最小值4.3 结果可视化分析良好的可视化能更直观地展示模型性能plt.figure(figsize(10, 6)) plt.plot(recalls, precisions, linewidth2) plt.scatter(recalls[best_idx], precisions[best_idx], cred, s100) plt.title(Precision-Recall Curve) plt.xlabel(Recall) plt.ylabel(Precision) plt.grid(True) plt.show()可视化要点标注关键操作点添加基线对比(如随机猜测)多模型对比时使用不同颜色5. 实战经验与避坑指南在实际项目中应用不平衡分类技术时我积累了一些宝贵经验也踩过不少坑这里分享给大家。5.1 技术选型建议不同场景的推荐方案场景推荐方法理由小规模数据SMOTE逻辑回归计算效率高中等规模SMOTEENN随机森林平衡效果与效率大规模数据代价敏感学习避免采样开销实时系统算法层面改进减少预处理延迟方法组合策略先尝试简单的类权重调整效果不佳再考虑采样方法极端不平衡时考虑集成方法5.2 常见问题解决问题1过采样后模型过拟合解决方案结合欠采样或使用SMOTE变种检查项验证集性能是否同步提升问题2采样后计算效率下降解决方案先特征选择减少维度替代方案使用随机欠采样或算法改进问题3不同采样方法结果不稳定解决方案增加随机种子测试改进方法使用集成技术稳定结果5.3 工程实践技巧流水线封装from imblearn.pipeline import make_pipeline model make_pipeline( SMOTEENN(random_state42), RandomForestClassifier(class_weightbalanced) )交叉验证策略使用StratifiedKFold保持分布在每折内部分别进行采样特征工程协同采样前先去除无关特征对分类变量进行特殊编码考虑时序因素(如时间序列分割)模型部署考量采样步骤需要保存参数在线服务要考虑采样延迟监控生产数据的分布变化6. 案例研究与效果对比为了更直观地展示不同方法的效果我在同一个数据集上实施了全套实验以下是详细对比结果。6.1 实验设计数据集来源某金融机构真实脱敏数据规模50,000条记录特征20个(10数值型10类别型)类别分布正类(违约)占5%对比方法基线模型(不做任何处理)随机过采样(ROS)SMOTE过采样SMOTEENN混合采样代价敏感学习(class_weight)BalancedRandomForest评估指标F1-score(正类)AUC-PR训练时间预测时间6.2 结果分析方法F1-scoreAUC-PR训练时间(s)预测时间(ms/样本)基线模型0.320.28120.8ROS0.610.54150.8SMOTE0.650.59180.8SMOTEENN0.680.63250.8Class Weight0.630.57130.8BalancedRF0.670.62351.2关键发现任何不平衡处理方法都比基线效果好SMOTEENN综合表现最佳算法层面改进效率最高BalancedRF效果不错但计算成本高6.3 可视化对比# 绘制F1-score对比图 methods [Baseline, ROS, SMOTE, SMOTEENN, ClassWeight, BalancedRF] f1_scores [0.32, 0.61, 0.65, 0.68, 0.63, 0.67] plt.figure(figsize(10, 6)) bars plt.bar(methods, f1_scores, color[gray,...]) plt.ylim(0, 0.8) plt.title(不同方法的F1-score对比) plt.ylabel(F1-score(正类)) for bar in bars: height bar.get_height() plt.text(bar.get_x() bar.get_width()/2., height, f{height:.2f}, hacenter, vabottom) plt.grid(True, axisy, linestyle--) plt.show()7. 进阶技巧与未来方向在掌握了基础的不平衡数据处理方法后我想分享一些进阶技巧和前沿方向这些在实际项目中非常有用。7.1 深度学习中的不平衡处理常用技巧加权损失函数def weighted_loss(y_true, y_pred): weights tf.where(y_true 1, 10.0, 1.0) return tf.keras.losses.binary_crossentropy(y_true, y_pred) * weights分层批采样确保每个batch都有正样本可自定义采样器实现迁移学习先在大规模平衡数据上预训练再在小规模不平衡数据上微调7.2 自动化不平衡处理AutoML集成自动采样方法选择自动类别权重调整自动阈值优化from sklearn.model_selection import GridSearchCV param_grid { sampler: [None, SMOTE(), RandomUnderSampler()], classifier__class_weight: [None, balanced, {0:1, 1:5}] } pipeline make_pipeline( FunctionSampler(), # 占位符 RandomForestClassifier() ) search GridSearchCV(pipeline, param_grid, scoringf1)7.3 新兴研究方向生成对抗网络(GAN)用于样本生成元学习自动调整采样策略图神经网络处理结构化不平衡数据在线学习应对动态不平衡8. 完整项目实战为了帮助大家更好地理解如何在实际项目中应用这些技术我将展示一个完整的信用评分卡开发案例。8.1 项目背景业务需求预测个人贷款违约风险识别高风险客户(正类占比4.8%)可解释性要求高数据特点15个特征(8个数值型7个类别型)存在缺失值和异常值明显的类别不平衡8.2 技术路线数据预处理异常值处理Winsorization缩尾缺失值填充按类别分别填充特征编码WOE编码独热编码不平衡处理主方案SMOTEENN对比方案class_weight模型选择逻辑回归(可解释性)随机森林(性能基准)评估部署业务指标KS值PSI部署形式PMMLAPI8.3 关键代码实现WOE分箱与编码from optbinning import OptimalBinning num_features [age, income, debt_ratio] for feature in num_features: binning OptimalBinning(feature, dtypenumerical) binning.fit(X_train[feature], y_train) X_train[f{feature}_woe] binning.transform(X_train[feature]) X_test[f{feature}_woe] binning.transform(X_test[feature])模型训练与调优from sklearn.linear_model import LogisticRegression from imblearn.pipeline import Pipeline pipeline Pipeline([ (sampler, SMOTEENN(random_state42)), (classifier, LogisticRegression(penaltyl1, solversaga, max_iter1000)) ]) params { classifier__C: np.logspace(-3, 3, 7) } search GridSearchCV(pipeline, params, scoringroc_auc, cv5) search.fit(X_train, y_train)8.4 业务应用效果上线表现KS值0.48(高于业务要求的0.35)违约识别率提升60%误判率降低25%经验总结不平衡处理要与特征工程协同业务指标比技术指标更重要模型可解释性是金融领域的刚需9. 工具与资源推荐经过多个项目的实践我整理了一些处理不平衡数据的实用工具和学习资源供大家参考。9.1 Python库推荐核心工具包imbalanced-learn提供了各种采样方法和专用算法pip install imbalanced-learnsklearn-contrib扩展的scikit-learn功能pip install scikit-learn-contriboptbinning专业的分箱与WOE编码工具pip install optbinning可视化工具from imblearn.visualization import plot_learning_curve plot_learning_curve(estimator, X, y, cv5)9.2 学习资源经典书籍《Imbalanced Learning: Foundations, Algorithms, and Applications》《Learning from Imbalanced Data Sets》在线课程Coursera: Dealing with Imbalanced DataKaggle: Learn courses on Data Imbalance论文推荐SMOTE原论文(2002)Borderline-SMOTE(2005)ADASYN(2008)9.3 实用技巧Jupyter Notebook快捷操作# 快速查看类别分布 import pandas as pd pd.Series(y).value_counts(normalizeTrue).plot(kindbar)性能优化技巧采样前减少特征维度使用稀疏矩阵存储采样后数据并行化采样过程调试建议先在小样本上测试不同方法记录每次实验的参数和结果使用MLflow或WeightsBiases跟踪实验10. 总结与个人心得经过多个不平衡分类项目的实战我深刻体会到处理这类问题需要系统性的思维和灵活的策略。以下是我的一些核心体会理解数据是基础必须深入分析数据特征和业务背景不能机械套用技术评估指标要合理选择与业务目标一致的评估标准避免被表面指标误导方法选择需权衡没有放之四海皆准的最佳方法需要平衡效果、效率和可解释性迭代优化是关键通常需要多次尝试和组合不同方法才能获得理想结果业务落地是目标技术方案最终要服务于业务需求要考虑部署和维护成本在实际项目中我通常会遵循这样的工作流程探索性数据分析(EDA)基线模型建立尝试不同不平衡处理方法模型调优与解释业务验证与部署记住处理不平衡数据的核心目标是让模型更好地服务于业务决策而不是单纯追求技术指标。希望我的这些经验分享能帮助你在实际项目中更有效地解决不平衡分类问题。