一、知识点数据层面通过调整训练集的类别分布来缓解数据不平衡问题不对测试集操作1.1过采样随机采样/smote1. 随机采样ROS从少数类中随机选择样本将其复制后添加到训练集步骤1.确定少数类2.从少数类中随机选择样本复制3.将复制样本添加到训练集优点避免数据不平衡提高模型泛化能力缺点增加训练集的大小增加训练时间增加噪声增加模型的偏差from imblrarn.over_sampling import RandomOverSampler#随机过采样器 import time #实例化随机过采样器 #sampling_strategyminority 表示只对少数类过采样 rosRandomOverSampler(sampling_strategyminority,random_state42) #对训练集随机过采样 x_resampled_ros,y_resampled_rosros.fit_resample(x_train,y_train) #过采样后的类别分布 print(pd.Series(y_resampled_ros).value_counts()) #使用过采样后的数据训练随机森林 rf_model_rosRandomForestClassifier(random_state42) rf_model_ros.fit(x_resample_ros,y_resample_ros) rf_pred_rosrf_model_ros.predict(x_test)2. smote过采样核心思想对少数类的样本的特征空间进行插值步骤1.对每个样本求K近邻 2.从k近邻中随机选择一个样本 3.计算选中样本和原始样本之间的插值 4.将差值乘以随机数随机数在0-1之间再加到原始样本上得到合成样本 5.重复合成样本直到数据平衡from imblearn.over_sampling import SMOTE #实例化SMOTE过采样器 smoteSMOTE(random_state42) #对训练集SMOTE过采样 x_resample_smote,y_resample_smotesmote.fit_resample(x_train,y_train) print(pd.Series(y_resampled_smote).value_counts()) #用过采样后的训练集训练随机森林 rf_model_smoteRandomForestClassifier(random_state42) rf_model_smote.fit(x_resample_somte,y_resmaple_smote) rf_pred_smoterf_model_smote.predict(x_test)1.2欠采样随机欠采样随机删除多数类样本可能会丢失重要信息from imblearn.under_sampling import RandomUnderSampler #实例化随机欠采样器 #sampling_strategymajority 表示只对多数类欠采样 rusRandomUnderSampler(sample_strategymajority,random_state42) #对训练集欠采样 x_resample_rus,y_resample_rusrus.fit_resample(x_train,y_train) #使用随机欠采样后的数据集训练随机森林 rf_model_rusRandomForestClassifier(random_staet42) rf_model_rus.fit(x_resample_rus,y_resample_rus) rf_model_predictrf_model_rus.predict(x_test)ENNENN是基于K近邻的欠采样方法核心思想不是为了平衡数据集而是通过清洗训练集中的噪声和边界模糊的多数类样本。从而减少模型对模糊区域的学习专注于更明确的特征类别步骤1. 识别坏样本遍历数据集中的每一个多数类样本 2. 对于某个多数类x,它的邻居中属于多数类的小于K/2那么x被认为是噪声或边界模糊样本会被移除from imblearn.under_sampling import EditedNearestNeibours #实例化ENN #sampling_strategyall 表示对所有类应用规则但实际上主要移除多数类 #kind_selall只要任意 1 个邻居类别和当前样本不一样该样本就判定为边界噪声、直接删除 ennEditedNearestNeibours(sampling_strategyall,n_neighbours3,kind_selall) #对训练集欠采样ENN x_resampled_enn,y_resample_ennenn.fit_resample(x_train,y_train) print(pd.Series(y_resample_enn).value_count()) #训练随机森林 rf_model_ennRandomForestClassifier(random_sate42) rf_model_enn.fit(x_resample_enn,y_resample_enn) rf_model_predrf_model_enn.predict(x_test)1.3混合采样结合过采样和欠采样从而通过合成样本增加少数样本还清理多数类的噪声和冗余样本先smote后enn,enn清理的包括袁术多数样本和smote生成的样本采样后的结果并没有得到改善1. 没有调整超参数 2. 删除过多有效样本 3.该方法不适合该数据from imblearn.combine import SMOTEENN #实例化 smote_ennSMOTEENN(random_state42) #对训练集混合采样 x_resample_somteenn,y_resample_smoteennsmote_enn.fit_resample(x_train,y_train) print(pd.Series(y_resample_smoteenn).value_counts()) rf_model_smoteennRandomForestClassifier(random_state42) rf_model_smoteenn.fit(x_resample_smoteenn,y_resample_smoteenn) rf_model_predrf_model_smoteenn.predict(x_test)1.4 算法层面-使用class_weight参数调整模型训练过程RandomForestClassifier中有class_weight参数推荐结合交叉验证Stratified K-Fold使用class_weightNone所有类别赋相同权重在不平衡数据集上,模型会偏向多数类class_weightbalanced权重与类别频率成反比少数类权重更高多数类权重较低class_weight{dict}手动设置权重class_weight{0:1,1:10}类别为1的权重是10print(y_train.value_count()) #实例化随机森林 rf_model_weightedRandomForestClassifier(random_state42,class_weightbalanced) #训练并预测 rf_model_weighted.fit(x_train,y_train) rf_model_predrf_model_weighted.predict(x_test)1.5 评估指标-修改分类阈值修改分类阈值在模型训练完成之后介入调整最终的分类规则阈值来平衡不同类型的错误目的在不改变已训练好的模型前提下根据需要调整精确率和召回率。精确率上升会导致召回率下降调整阈值不改变模型学到的参数和决策边界本身只改变如何解释模型的输出缺点该方法治标不治本一味降低阈值会导致低精确率from sklearn.metrics import precision_recall_curve,f1_score,confusion_matrix import numpy as np #输出预测概率是一个矩阵在行代表样本列代表类别 y_probarf_model.predict_proba(x_test)[:,1] #输出类别为1的预测概率 # thresholds 阈值 precisions,recalls,thresholdsprecision_recall_curve(y_test,y_proba) #计算所有阈值对应的F1-scores fscores(2*precisions*recall)/(precisionsrecall) #fscores比thresholds多一个值因为当precision1,recall0,阈值是无穷大不保存 用[:-1]来匹配因为左闭右开 ixnp.aegmax(fscores[:-1]) #返回最大值的索引 best_thresholdthreshold[ix] best_fscore fscores[ix] y_pred_best_threshold (y_proba best_threshold).astype(int)f1_score曲线的最高点就是选择的最佳阈值因为平衡了精确率和召回率实际阈值选择根据业务需求需要高准确就选稍大一点的阈值需要低漏报就选小阈值浙大疏锦行