Machine learning 即使在过采样数据集之后,性能也非常低

Machine learning 即使在过采样数据集之后,性能也非常低,machine-learning,scikit-learn,classification,imblearn,mlp,Machine Learning,Scikit Learn,Classification,Imblearn,Mlp,我正在使用mlpclassizer对心脏病进行分类。我使用imblearn.SMOTE来平衡每个类的对象。我得到了非常好的结果(85%的平衡acc),但有人建议我不会对测试数据使用SMOTE,只对列车数据使用。在我做了这些更改之后,我的分类器的性能下降了太多(~35%的平衡精度),我不知道会出什么问题 以下是一个简单的基准,训练数据平衡,但测试数据不平衡: 这是代码: def改造样本SMOTE(X,y): 从IMBRearn.over_采样导入SMOTE sm=SMOTE(采样策略='all'

我正在使用
mlpclassizer
对心脏病进行分类。我使用
imblearn.SMOTE
来平衡每个类的对象。我得到了非常好的结果(85%的平衡acc),但有人建议我不会对测试数据使用
SMOTE
,只对列车数据使用。在我做了这些更改之后,我的分类器的性能下降了太多(~35%的平衡精度),我不知道会出什么问题

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

这是代码:

def改造样本SMOTE(X,y):
从IMBRearn.over_采样导入SMOTE
sm=SMOTE(采样策略='all')
十、 y=标准拟合样本(X,y)
返回X,y
X_序列,X_测试,y_序列,y_测试=序列测试分割(X,y,测试大小=0.2,随机状态=20)
##规范化数据
从sklearn.preprocessing导入StandardScaler
sc_X=StandardScaler()
X_序列=sc_X.拟合变换(X_序列)
X_测试=sc_X.拟合变换(X_测试)
##仅对训练数据进行SMOTE
X_-train,y_-train=改造样本SMOTE(X_-train,y_-train)
clf=MLP分类器(隐藏层大小=(20),详细值=10,
学习率初始值=0.5,最大值=2000,
激活class='logistic',解算器class='sgd',洗牌=True,随机状态=30)
clf.fit(X_系列、y_系列)
y_pred=clf.预测(X_检验)

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

代码中的第一个错误是将数据转换为标准格式时。您只需要安装一次
StandardScaler
,这是在
X\U列车上安装的。您不应该在
X\u测试中重新安装它。因此,正确的代码是:

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模型。

希望您已经为您的模型获得了更好的结果。我尝试更改了一些参数,我得到了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
混淆矩阵:

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)

应该有一个权重参数,你可以设置,这样当你在SMOTE之后训练50%的积极等级时,你不会预测没有SMOTE的50%积极等级。没有这样的事情,不幸的是,你能考虑SMOTE应用程序更新你的代码吗?我看不出它去了哪里。另一件事:您的代码实际上是在测试数据上应用scaler,但在您的回答中,您说不要使用它。我很困惑,我正在转换测试数据,但我没有在该数据上拟合
sc_X
。我按照您所说的进行了更改,但没有更好的结果。关于分类器,没有什么错,因为MLP对于此类问题非常适合。仅对
序列
进行过采样,而不是对整个数据集进行过采样后,就出现了这种较低的结果。不,MLP在不平衡数据集上的表现不是最好的。这种预测损失的一个原因是,该模型只是过度拟合训练数据,而训练数据是较小数据的过采样版本。检查训练的准确性。同时检查每类的准确性。尝试交叉验证和NN算法,可能会提供更好的结果。