SMOTE处理后KNN特征工程模型无法适配原始数据集的问题
SMOTE训练的KNN模型无法在原始不平衡数据集上有效分类
背景
- 处理稀有类别/不平衡数据集
- 使用SMOTE(Synthetic Minority Over-sampling Technique)平衡数据集并做归一化缩放,在SMOTE数据集上训练的KNN模型表现达标
- 核心代码逻辑如下:
knn ( train = scale(sample(smote(dataset)))), test = scale(1-sample(smote(dataset)))), cl = 1-sample(smote(dataset))), ... )
- 希望将模型输出概率用于集成学习
问题
在SMOTE数据集上表现优异的KNN模型,应用到原始数据集时无法完成有效分类(所有结果均为0,而非0和1两类)
说明
- 参考O'Reilly《Practical Statistics for Data Scientists》(电子版第218/247页)中描述的「KNN as a Feature Engine」方法,尝试在train、test和cl参数中使用原始数据集
- 已选择与SMOTE数据集匹配的范围,避免了「train」和「Class」错误,且分布与正常情况一致
- 尝试过格式化列、缩放/反缩放、调整SMOTE数据集行数等多种方法,仍无法让SMOTE训练的模型适配原始数据集,需解决该问题
可复现问题的R代码
可正常运行的标准/SMOTE版KNN代码
## DataPrep set.seed(0) df <- data.frame(y=rep(as.factor(c('Yes', 'No')), times=c(90, 10)),x1=rnorm(100),x2=rnorm(100)) df_knn <- smote(y~x1+x2,data=df,perc.over = 4, perc.under = 1.25 ) ##Smote - 50/50 split # df ##Standard ## Split data & Scale sample_size = floor(0.8*nrow(df_knn)) split = sample(seq_len(nrow(df_knn)),size = sample_size) train_cl = df_knn[split,] test_cl = df_knn[-split,] ## Scale data train_scale <- scale( select ( train_cl, x1, x2) ) test_scale <- scale( select ( test_cl, x1, x2) ) ## KNN - Best K Inserted from below classifier_knn <- knn( train = train_scale, test = test_scale, cl = train_cl[,"y"] , prob = TRUE, k = 15) ## Confusion Matrix & Metrics cm <- table(test_cl$y, classifier_knn) cm print(paste('Accuracy =', round( (cm[1,1]+cm[2,2]) / sum(cm[]), digits = 4) * 100 )) print(paste('Precision =',round( cm[2,2] / sum(cm[,2]), digits = 4)* 100 )) print(paste('Specificity =', round( cm[1,1] / sum(cm[1,]), digits = 4)* 100 )) print(paste('Recall =', round( cm[2,2] / sum(cm[2,]), digits = 4)* 100 ))
无法在原始数据集上运行的KNN代码
## DataPrep set.seed(0) df <- data.frame(y=rep(as.factor(c('Yes', 'No')), times=c(90, 10)),x1=rnorm(100),x2=rnorm(100)) df_knn <- smote(y~x1+x2,data=df,perc.over = 4, perc.under = 1.25 ) ##Smote - 50/50 split ## Split data & Scale sample_size = floor(0.8*nrow(df_knn)) split = sample(seq_len(nrow(df_knn)),size = sample_size) train_cl = df_knn[split,] test_cl = df_knn[-split,] ## Scale data train_scale <- scale( select ( train_cl, x1, x2) ) test_scale <- scale( select ( test_cl, x1, x2) ) ## KNN - Best K Inserted from below classifier_knn <- knn( train_scale, test = train_scale, cl = df[split,'y'] , prob = TRUE, k = 15) ## Original Dataset & Distribution table( df[split,'y'] ) ## Train Dataset & Distribution table( train_cl$y) ## KNN Output table ( classifier_knn )
内容的提问来源于stack exchange,提问作者William Rodriguez
相关产品推荐
相关产品推荐

