即使在对数据集进行过采样之后性能也非常低
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)
我正在使用 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)