使用 SMOTE 技术平衡数据集时使用的最佳性能指标是什么

数据挖掘 Python 阶级失衡 表现 打击
2021-09-24 11:24:21

我使用 smote 技术对我的数据集进行过采样,现在我有了一个平衡的数据集。我面临的问题是性能指标;与平衡数据集相比,不平衡数据集中的精度、召回率、f1 度量、准确率表现更好。

我可以使用哪种测量来表明平衡数据集可以提高模型的性能?

注意:roc_auc_score 在平衡数据集中比在不平衡数据集中更好的 roc_auc_score 可以被认为是一个很好的性能测量吗?在解释之后我实现了代码,我得到了这个结果

import pandas as pd
import numpy as np
from sklearn import preprocessing
import matplotlib.pyplot as plt 
plt.rc("font", size=14)
from sklearn.svm import LinearSVC
from sklearn.svm import SVC
from sklearn.cross_validation import train_test_split,StratifiedShuffleSplit,cross_val_score
import seaborn as sns
from scipy import interp
from time import *
from sklearn import metrics
X=dataCAD.iloc[:,0:71]
y= dataCAD['Cardio1']
# Split the dataset in two equal parts
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=0)
print(y_test.value_counts())
model=SVC(C=0.001, kernel="rbf",gamma=0.01, probability=True)
t0 = time()
clf = model.fit(X_train,y_train)
y_pred = clf.predict(X_test)
t = time() - t0
print("=" * 52)
print("time cost: {}".format(t))
print()
print("confusion matrix\n", metrics.confusion_matrix( y_test, y_pred))
cf=metrics.confusion_matrix(y_test, y_pred)
accuracy=(cf.item((0,0))/50)+(cf.item((1,1))/14)
print("model accuracy \n",accuracy/2)
print()
print("\t\tprecision_score: {}".format(metrics.precision_score( y_test, y_pred, average='macro')))
print()
print("\t\trecall_score: {}".format(metrics.recall_score(y_test, y_pred, average='macro')))
print()
print("\t\tf1_score: {}".format(metrics.f1_score(y_test, y_pred, average='macro')))
print()
print("\t\troc_auc_score: {}".format(metrics.roc_auc_score( y_test, y_pred, average='macro')))

结果:

Name: Cardio1, dtype: int64
====================================================
time cost: 0.012008905410766602

confusion matrix
 [[50  0]
 [14  0]]
model accuracy 
 0.5

        precision_score: 0.390625

        recall_score: 0.5

        f1_score: 0.43859649122807015

        roc_auc_score: 0.5

对于平衡数据集

X_train1,y_train1 = sm.fit_sample(X_train, y_train.ravel())
df= pd.DataFrame({'Cardio1': y_train1})
df.groupby('Cardio1').Cardio1.count().plot.bar(ylim=0)
plt.show()
print(X_train1.shape)
print(y_train1.shape)
#model=SVC(C=0.001, kernel="rbf",gamma=0.01, probability=True)
model=SVC(C=10, kernel="sigmoid",gamma=0.001, probability=True)
t0 = time()
clf = model.fit(X_train1,y_train1)
y_pred = clf.predict(X_test)
t = time() - t0
print("=" * 52)
print("time cost: {}".format(t))
print()
print("confusion matrix\n", metrics.confusion_matrix(y_test, y_pred))
cf=metrics.confusion_matrix(y_test, y_pred)
accuracy=(cf.item((0,0))/50)+(cf.item((1,1))/14)
print("model accuracy \n",accuracy/2)
print()
#print("\t\taccuracy: {}".format(metrics.accuracy_score( y_test, y_pred)))
print()
print("\t\tprecision_score: {}".format(metrics.precision_score( y_test, y_pred, average='macro')))
print()
print("\t\trecall_score: {}".format(metrics.recall_score(y_test, y_pred, average='macro')))
print()
print("\t\tf1_score: {}".format(metrics.f1_score(y_test, y_pred, average='macro')))
print()
print("\t\troc_auc_score: {}".format(metrics.roc_auc_score( y_test, y_pred, average='macro')))

结果:

(246, 71)
(246,)
====================================================
time cost: 0.05353999137878418

confusion matrix
 [[ 0 50]
 [ 0 14]]
model accuracy 
 0.5


        precision_score: 0.109375

        recall_score: 0.5

        f1_score: 0.1794871794871795

        roc_auc_score: 0.5

我没有发现有效的结果。我应该使用交叉验证来实现模型吗?

1个回答

首先,为了清楚起见,您不应该评估模型在平衡数据集上的性能。你应该做的是将你的数据集分成一个训练集和一个测试集,理想情况下具有相同程度的不平衡。评估应在测试集上执行,而在训练集上进行平衡。

至于您的问题,任何宏观平均指标都应该可以很好地证明您的平衡技术是有效的。要计算这样一个指标(为了简单起见,我们说准确度),您只需要单独计算每个类的准确度,然后对它们进行平均

示例
我们训练了两个模型m1m2第一个没有平衡数据集,第二个使用 SMOTE 平衡数据集。

实际值: 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
预测m10, 0, 0, 0, 0, 0, 0, 0, 0, 0 <--仅预测多数类
预测m21, 0, 0, 1, 0, 1, 0, 0, 1, 1

我们通常如何计算准确性?

acc=correctpredictionstotalpredictions

我们的两个模型在这个指标上的表现如何?

acc1=810=80%
acc2=710=70%

根据这个性能指标,m2优于m1. 然而,这并不一定是m1预测多数类的情况!为了显示m2比 更好m1,我们需要一个将这两个类别视为平等的指标。

我们现在将尝试计算宏观平均精度。如何?首先,我们将分别计算每个类的准确率,然后我们将它们平均:

  • 对于m1
    acc10=88=100%<--m1在课堂上的准确性0
    acc11=02=0% <--m1在课堂上的准确性1
    macro_acc1=acc10+acc112=100%+0%2=50%

  • 对于m2
    acc20=58=62.5%<--m2在课堂上的准确性0
    acc21=22=100% <--m2在课堂上的准确性1
    macro_acc2=acc20+acc212=62.5%+100%2=81.25%

备注

  • 宏平均可以应用于您想要的任何度量,但它最常见于混淆矩阵度量(例如精度、召回率、f1)。

  • 这个不用自己实现,很多库已经有了(比如sklearn的f1_score有个参数叫average,可以设置为"macro"