python - 使用留一交叉验证进行过采样

标签 python machine-learning roc precision-recall oversampling

我的研究项目正在使用一个极其不平衡的数据集,共有 44 个样本。这是一个二元分类问题,其中有少数类的 3/44 个样本,对此我使用留一交叉验证。如果我在 LOOCV 循环之前对整个数据集执行 SMOTE 过采样,则 ROC 曲线的预测精度和 AUC 分别接近 90% 和 0.9。然而,如果我仅对 LOOCV 循环内的训练集进行过采样(这恰好是一种更合乎逻辑的方法),ROC 曲线的 AUC 会降至 0.3

我还尝试了精确记忆曲线和分层 k 倍交叉验证,但在循环外部和内部过采样的结果中面临着类似的区别。 请建议我什么是过采样的正确位置,并在可能的情况下解释其区别。

循环内过采样:-

i=0
acc_dec = 0
y_test_dec=[] #Store y_test for every split
y_pred_dec=[] #Store probablity for positive label for every split

for train, test in loo.split(X):    #Leave One Out Cross Validation
    #Create training and test sets for split indices
    X_train = X.loc[train]  
    y_train = Y.loc[train]
    X_test = X.loc[test]
    y_test = Y.loc[test]

    #oversampling minority class using SMOTE technique
    sm = SMOTE(sampling_strategy='minority',k_neighbors=1)
    X_res, y_res = sm.fit_resample(X_train, y_train)

    #KNN
    clf = KNeighborsClassifier(n_neighbors=5) 
    clf = clf.fit(X_res,y_res)
    y_pred = clf.predict(X_test)
    acc_dec = acc_dec +  metrics.accuracy_score(y_test, y_pred)
    y_test_dec.append(y_test.to_numpy()[0])
    y_pred_dec.append(clf.predict_proba(X_test)[:,1][0])
    i+=1

# Compute ROC curve and ROC area for each class
fpr,tpr,threshold=metrics.roc_curve(y_test_dec,y_pred_dec,pos_label=1)
roc_auc = metrics.auc(fpr, tpr)
print(str(acc_dec/i*100)+"%")

AUC:0.25

准确率:68.1%

循环外过采样:

acc_dec=0 #accuracy for decision tree classifier
y_test_dec=[] #Store y_test for every split
y_pred_dec=[] #Store probablity for positive label for every split
i=0
#Oversampling before the loop
sm = SMOTE(k_neighbors=1)
X, Y = sm.fit_resample(X, Y)   
X=pd.DataFrame(X)
Y=pd.DataFrame(Y)
for train, test in loo.split(X):    #Leave One Out Cross Validation

    #Create training and test sets for split indices
    X_train = X.loc[train]  
    y_train = Y.loc[train]
    X_test = X.loc[test]
    y_test = Y.loc[test]

    #KNN
    clf = KNeighborsClassifier(n_neighbors=5) 
    clf = clf.fit(X_res,y_res)
    y_pred = clf.predict(X_test)
    acc_dec = acc_dec +  metrics.accuracy_score(y_test, y_pred)
    y_test_dec.append(y_test.to_numpy()[0])
    y_pred_dec.append(clf.predict_proba(X_test)[:,1][0])
    i+=1

# Compute ROC curve and ROC area for each class
fpr,tpr,threshold=metrics.roc_curve(y_test_dec,y_pred_dec,pos_label=1)
roc_auc = metrics.auc(fpr, tpr)
print(str(acc_dec/i*100)+"%")

曲线下面积:0.99

准确率:90.24%

这两种方法为何会导致如此不同的结果?我应该遵循什么?

最佳答案

在分割数据之前进行上采样(如 SMOTE)意味着测试集中存在有关训练集的信息。这有时称为“泄漏”。不幸的是,您的第一个设置是正确的。

Here's a post解决这个问题。

关于python - 使用留一交叉验证进行过采样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56577593/

相关文章:

python - 如何通过数组交集对 pandas 数据框进行分组

python - Keras LSTM 模型无法学习

python - 在 sklearn 中尝试交叉验证时出现类型错误

python - 使用交叉验证 (CV) 计算 scikit-learn 多类 ROC 曲线

python - 如何获得神经网络的ROC曲线?

python - scikit learn auc 函数的一些错误?

python - 使用 Conda Build 的 Cython Python 程序

python - 无法在 python selenium 中正确获取所有图像 url

python - Django Rest Framework 嵌套序列化程序不显示相关数据

machine-learning - 逻辑回归数据集标签的含义是什么?