Qual è la migliore metrica delle prestazioni utilizzata nel bilanciamento del set di dati utilizzando la tecnica SMOTE


8

Ho usato la tecnica smote per sottocampionare il mio set di dati e ora ho un set di dati bilanciato. Il problema che ho dovuto affrontare è che le metriche delle prestazioni; precisione, richiamo, misura f1, accuratezza nel set di dati sbilanciato vengono eseguite meglio rispetto al set di dati bilanciato.

Quale misura posso usare per mostrare che il set di dati di bilanciamento può migliorare le prestazioni del modello?

NB: roc_auc_score è migliore nel datset bilanciato rispetto a roc_auc_score con un set di dati sbilanciato Può essere considerata una buona misurazione delle prestazioni? dopo la spiegazione ho implementato il codice e ho ottenuto questi risultati

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')))

risultati:

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

Per set di dati bilanciato

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')))

risultati:

(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

Non ho trovato risultati efficienti. Devo implementare il modello usando la validazione incrociata?

Risposte:


8

Prima di tutto, per essere chiari, non dovresti valutare le prestazioni dei tuoi modelli nel set di dati bilanciato. Quello che dovresti fare è dividere il tuo set di dati in un treno e un set di test con idealmente lo stesso grado di squilibrio. La valutazione deve essere eseguita esclusivamente sul set di test, mentre il bilanciamento sul set di allenamento.

Per quanto riguarda la tua domanda, qualsiasi metrica a media macro dovrebbe andare bene per dimostrare che la tua tecnica di bilanciamento è efficace. Per calcolare una tale metrica (diciamo accuratezza per semplicità), devi solo calcolare le precisioni di ogni classe individualmente e quindi fare una media .

Esempio :
abbiamo addestrato due modelli m1e m2, il primo senza bilanciare il set di dati e il secondo dopo aver usato SMOTE per bilanciare il set di dati.

Valori effettivi: 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
Previsto m1: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 <- prevede solo la classe di maggioranza
Previsto m2:1, 0, 0, 1, 0, 1, 0, 0, 1, 1

Come calcoleremmo normalmente l'accuratezza?

acc=correctpredictionstotalpredictions

Come si comportano i nostri due modelli su questa metrica?

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

Secondo questa metrica delle prestazioni, m2è meglio di m1. Tuttavia, questo non è necessariamente il caso in quanto m1prevede solo la classe di maggioranza! Per mostrare come m2sia meglio di m1, abbiamo bisogno di una metrica che tratta i due clasi come uguali.

Proveremo ora a calcolare un'accuratezza mediata a macroistruzione. Come? In primo luogo calcoleremo l'accuratezza per ciascuna classe separatamente, quindi li classificheremo:

  • Per m1: Precisione del <- sulla classe <- Accuratezza sulla classe
    acc10=88=100%m10
    acc11=02=0%m11
    macro_acc1=acc10+acc112=100%+0%2=50%

  • Per m2: <- accuratezza sulla classe <- precisione sulla classe
    acc20=58=62.5%m20
    macro_acc2=acc 0 2 +acc 1 2acc21=22=100%m21
    macro_acc2=acc20+acc212=62.5%+100%2=81.25%

Note :

  • La media delle macro può essere applicata a qualsiasi metrica desiderata, tuttavia è più comune nelle metriche della matrice di confusione (ad esempio precisione, richiamo, f1).

  • Non è necessario implementarlo da soli, molte librerie lo hanno già (ad es. Il parametro f1_score di sklearn ha un parametro chiamato average, che può essere impostato su "macro")


Grazie mille per la tua grande spiegazione è chiaro conciso Potresti proporre alcuni articoli scientifici a reali ??
Rawia Sammout,

4
Alcuni articoli sull'argomento: 1 , 2 , 3 . In sostanza, questi articoli in sintesi sono metodi per combattere lo squilibrio di classe (sovracampionamento / sottocampionamento, pesi di classe, ecc.) E metriche che possono essere utilizzate in queste situazioni (ROC, g-media, quadratica kappa, ecc.)
Djib2011

potresti dare un'occhiata al codice condiviso ho trovato risultati confusi invece di migliorare le prestazioni del modello usando smote ho ottenuto il contrasto
Rawia Sammout

3
Da quello che posso dire a giudicare dalle matrici di confusione, il tuo primo modello (senza bilanciamento) prevede solo la classe di maggioranza, mentre il secondo (con smote) predice l'altra classe. Consiglierei forse di provare un altro classificatore, in quanto gli SVM richiedono una grande quantità di ottimizzazione dei parametri ipertestuali (ovvero eseguire il modello ancora e ancora per capire il miglior C, gamma, tipo di kernel, ecc.).
Djib2011,

grazie per te. penso che cambiare il classificatore sia meglio perché uso il parametro di tuning di gridsearch e ho addestrato entrambi i modelli sui migliori iperparametri trovati dall'algoritmo di gridsearch
Rawia Sammout,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.