即使在对数据集进行过采样之后性能也非常低

Very low performance even after oversampling dataset

我正在使用 MLPClassifier 来 class 诊断心脏病。我用imblearn.SMOTE来平衡每个class的对象。我得到了很好的结果(85% 的平衡 acc.),但我被告知我不会在测试数据上使用 SMOTE,只对训练数据使用。进行此更改后,我的 classifier 的性能下降太多(~35% 的平衡精度),我不知道哪里出了问题。

这是一个训练数据平衡但测试数据不平衡的简单基准:

这是代码:

    def makeOverSamplesSMOTE(X,y):
         from imblearn.over_sampling import SMOTE
         sm = SMOTE(sampling_strategy='all')
         X, y = sm.fit_sample(X, y)
         return X,y
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=20)

    ## Normalize data
    from sklearn.preprocessing import StandardScaler
    sc_X = StandardScaler()
    X_train = sc_X.fit_transform(X_train)
    X_test = sc_X.fit_transform(X_test)

    ## SMOTE only on training data
    X_train, y_train = makeOverSamplesSMOTE(X_train, y_train)

    clf = MLPClassifier(hidden_layer_sizes=(20),verbose=10,
                        learning_rate_init=0.5, max_iter=2000, 
                        activation='logistic', solver='sgd', shuffle=True, random_state=30)

    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)

我想知道我做错了什么,因为这似乎是准备数据的正确方法。

代码中的第一个错误是在将数据转换为标准格式时。您只需要适合 StandardScaler 一次,那就是 X_train。您不应该在 X_test 上改装它。所以正确的代码是:

def makeOverSamplesSMOTE(X,y):
     from imblearn.over_sampling import SMOTE
     sm = SMOTE(sampling_strategy='all')
     X, y = sm.fit_sample(X, y)
     return X,y
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=20)

## Normalize data
from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)

## SMOTE only on training data
X_train, y_train = makeOverSamplesSMOTE(X_train, y_train)

clf = MLPClassifier(hidden_layer_sizes=(20),verbose=10,
                    learning_rate_init=0.5, max_iter=2000, 
                    activation='logistic', solver='sgd', shuffle=True, random_state=30)

clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

对于机器学习模型,尝试降低学习率。它太高了。 sklearn 中的默认学习率为 0.001。尝试改变激活函数和层数。此外,并非每个 ML 模型都适用于每个数据集,因此您可能需要查看数据并相应地选择 ML 模型。

希望你的 model.I 已经通过改变几个参数得到了更好的结果,我得到了 65% 的准确率,当我将它更改为 90:10 样本时,我得到了 70 的准确率%。 但是准确性可能会产生误导,所以我计算了 F1 分数,它可以为您提供更好的预测画面。

from sklearn.neural_network import MLPClassifier
clf = MLPClassifier(hidden_layer_sizes=(1,),verbose=False,
                    learning_rate_init=0.001, 
                    max_iter=2000, 
                    activation='logistic', solver='sgd', shuffle=True, random_state=50)

clf.fit(X_train_res, y_train_res)
y_pred = clf.predict(X_test)

from sklearn.metrics import accuracy_score, confusion_matrix ,classification_report
score=accuracy_score(y_test, y_pred, )
print(score)
cr=classification_report(y_test, clf.predict(X_test))
print(cr)

准确度 = 0.65

分类报告: 精确召回 f1 分数支持

       0       0.82      0.97      0.89        33
       1       0.67      0.31      0.42        13
       2       0.00      0.00      0.00         6
       3       0.00      0.00      0.00         4
       4       0.29      0.80      0.42         5

   micro avg       0.66      0.66      0.66        61
   macro avg       0.35      0.42      0.35        61
weighted avg       0.61      0.66      0.61        61

confusion_matrix:

array([[32,  0,  0,  0,  1],
       [ 4,  4,  2,  0,  3],
       [ 1,  1,  0,  0,  4],
       [ 1,  1,  0,  0,  2],
       [ 1,  0,  0,  0,  4]], dtype=int64)