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算法,可能会提供更好的结果。