1

我正在使用MLPClassifier心脏病分类。我曾经imblearn.SMOTE平衡每个班级的对象。我得到了非常好的结果(85% 的平衡acc。),但我被告知我不会用于SMOTE测试数据,只用于训练数据。在我做出这些改变之后,我的分类器的性能下降太多(大约 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)

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

4

2 回答 2

2

代码中的第一个错误是在将数据转换为标准格式时。你只需要适合StandardScaler一次,那就是 on 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 模型。

于 2019-07-26T15:48:27.283 回答
0

希望您已经为您的模型获得了更好的结果。我尝试通过更改一些参数来获得 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-score 支持

       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

混淆矩阵:

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)
于 2019-08-02T00:40:21.717 回答