You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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两类)

说明

  1. 参考O'Reilly《Practical Statistics for Data Scientists》(电子版第218/247页)中描述的「KNN as a Feature Engine」方法,尝试在train、test和cl参数中使用原始数据集
  2. 已选择与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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:07:22