290520200955
Trident project part: conglomerate of the models
When we have a very unbalanced set, each classification model is good – that is, it has excellent parameters. Unfortunately, it depends on whether it classifies a collector’s collection or not. Today we will check whether the application of oversampling is an effective method. Starting this experiment today I had mixed experiences. I do not know what will come out we start the experiment.
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
from sklearn.ensemble import BaggingClassifier
from simple_colors import *
from prettytable import PrettyTable
warnings.filterwarnings("ignore")
%matplotlib inline
df= pd.read_csv('/home/wojciech/Pulpit/1/Stroke_Prediction.csv')
print(df.shape)
print()
print(df.columns)
df.head(3)
Zmniejszacz próbki
df = df.sample(frac = 1.0, random_state=10)
df.shape
Tool for automatic coding of discrete variables¶
a,b = df.shape #<- ile mamy kolumn
b
print('DISCRETE FUNCTIONS CODED')
print('------------------------')
for i in range(1,b):
i = df.columns[i]
f = df[i].dtypes
if f == np.object:
print(i,"---",f)
if f == np.object:
df[i] = pd.Categorical(df[i]).codes
continue
df.fillna(7777, inplace=True)
X = df.drop('Stroke', axis=1)
y = df['Stroke']
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=123,stratify=y)
X_test = X_test.values
y_test = y_test.values
X_train = X_train.values
y_train = y_train.values
Oversampling 
def oversampling(ytrain, Xtrain):
import matplotlib.pyplot as plt
global Xtrain_OV
global ytrain_OV
calss1 = np.round((sum(ytrain == 1)/(sum(ytrain == 0)+sum(ytrain == 1))),decimals=2)*100
calss0 = np.round((sum(ytrain == 0)/(sum(ytrain == 0)+sum(ytrain == 1))),decimals=2)*100
print("y = 0: ", sum(ytrain == 0),'-------',calss0,'%')
print("y = 1: ", sum(ytrain == 1),'-------',calss1,'%')
print('--------------------------------------------------------')
ytrain.value_counts(dropna = False, normalize=True).plot(kind='pie',title='Before oversampling')
plt.show
print()
Proporcja = sum(ytrain == 0) / sum(ytrain == 1)
Proporcja = np.round(Proporcja, decimals=0)
Proporcja = Proporcja.astype(int)
ytrain_OV = pd.concat([ytrain[ytrain==1]] * Proporcja, axis = 0)
Xtrain_OV = pd.concat([Xtrain.loc[ytrain==1, :]] * Proporcja, axis = 0)
ytrain_OV = pd.concat([ytrain, ytrain_OV], axis = 0).reset_index(drop = True)
Xtrain_OV = pd.concat([Xtrain, Xtrain_OV], axis = 0).reset_index(drop = True)
Xtrain_OV = pd.DataFrame(Xtrain_OV)
ytrain_OV = pd.DataFrame(ytrain_OV)
print("Before oversampling Xtrain: ", Xtrain.shape)
print("Before oversampling ytrain: ", ytrain.shape)
print('--------------------------------------------------------')
print("After oversampling Xtrain_OV: ", Xtrain_OV.shape)
print("After oversampling ytrain_OV: ", ytrain_OV.shape)
print('--------------------------------------------------------')
ax = plt.subplot(1, 2, 1)
ytrain.value_counts(dropna = False, normalize=True).plot(kind='pie',title='Before oversampling')
plt.show
kot = pd.concat([ytrain[ytrain==1]] * Proporcja, axis = 0)
kot = pd.concat([ytrain, kot], axis = 0).reset_index(drop = True)
ax = plt.subplot(1, 2, 2)
kot.value_counts(dropna = False, normalize=True).plot(kind='pie',title='After oversampling')
plt.show
oversampling(y_train, X_train)
I used three models of GaussianNB, LogisticRegression, CatBoostClassifier in their basic version without oversamplin and with oversampling. We will see what differences in the minority set classification the oversampling method gives.
I get rid of one dimension from the ytrain_OV set so that the set is similar to y_test.
print(Xtrain_OV.shape)
print(ytrain_OV.shape)
ytrain_OV = ytrain_OV['Stroke']
print(ytrain_OV.shape)
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
from lightgbm import LGBMClassifier
from sklearn.ensemble import RandomForestClassifier
from catboost import CatBoostClassifier
from sklearn.svm import SVC
from sklearn.linear_model import LassoCV
NBC = GaussianNB()
LRE = LogisticRegression(solver='lbfgs')
GBC = GradientBoostingClassifier()
RFC = RandomForestClassifier()
LGBM = LGBMClassifier()
CBC = CatBoostClassifier(verbose=0, n_estimators=100)
classifiers_A = [NBC,LRE,GBC,RFC,LGBM,CBC]
name = ['NBC','LRE','GBC','RFC','LGBM','CBC']
#for cls in classifiers_A:
# cls.fit(X_train, y_train)
classifiers_OV = [NBC,LRE,GBC,RFC,LGBM,CBC]
name2 = ['NBC_OV','LRE_OV','GBC_OV','RFC_OV','LGBM_OV','CBC_OV']
#for t in classifiers_OV:
# t.fit(Xtrain_OV, ytrain_OV)
def Recall_Precision(six_classifiers,name, X_train, y_train,X_test,y_test):
import numpy as np
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.metrics import confusion_matrix, log_loss, auc, roc_curve, roc_auc_score, recall_score, precision_recall_curve
from sklearn.metrics import make_scorer, precision_score, fbeta_score, f1_score, classification_report
from sklearn.metrics import accuracy_score
from mlxtend.plotting import plot_learning_curves
from prettytable import PrettyTable
#from simple_colors import *
for cls in six_classifiers:
cls.fit(X_train, y_train)
Recall_Training = ['Recall Training: ']
Precision_Training = ['Precision Training: ']
Recall_Test= ['Recall Test: ']
Precision_Test = ['Precision Test: ']
def compute_metric2(model):
Recall_Training = np.round(recall_score(y_train, model.predict(X_train)), decimals=3)
Precision_Training = np.round(precision_score(y_train, model.predict(X_train)), decimals=3)
Recall_Test = np.round(recall_score(y_test, model.predict(X_test)), decimals=3)
Precision_Test = np.round(precision_score(y_test, model.predict(X_test)), decimals=3)
return Recall_Training, Precision_Training, Recall_Test, Precision_Test
for cls in six_classifiers:
results = compute_metric2(cls)
Recall_Training.append(results[0])
Precision_Training.append(results[1])
Recall_Test.append(blue(results[2],'bold'))
Precision_Test.append((blue(results[3],'bold')))
t = PrettyTable(['Name', name[0],name[1],name[2],name[3],name[4],name[5]])
t.add_row(Recall_Training)
t.add_row(Precision_Training)
t.add_row(Recall_Test)
t.add_row(Precision_Test)
print(t)
print(green('RECALL - procentowy udział chorych dobrze zdiagnozowanych w populacji ludzi chorych ogółem','italic'))
print(green('PRECISION - procentowy udział chorych dobrze zdiagnozowanych w populacji ludzi zdiagnozowanyc fałszywie lub prawdziwie jako chorych','italic'))
In confusuin_matrix we have 4 states to consider. These values are presented in the form of a matrix in which the Y axis shows the real classes, while the X axis shows the predicted classes. Because we are considering a medical case, let’s imagine that we are analyzing if someone has COVID-19.
True Positive – patients who were not COVIT-19 sufferers were diagnosed with COVID-19. For the GaussianNB model it was 8246 patients.
True Negative – patients who have bulls with COVIT-19, and the model has detected that they are sick. There were 34 such people for the GaussianNB model.
False Positive (Test false) – The test showed that patients did not have COVIT-19 and they were sick. This is the first type of error. For GaussainNB there were 277 people.
False Negative – This is the number of people who are healthy (marked as 0), however the model indicates that they are people with COVIT-19. This is a second type of error. For Gaussian there were 123 people.
In confusuin_matrix we have 4 states to consider. These values are presented in the form of a matrix in which the Y axis shows the real classes, while the X axis shows the predicted classes. Because we are considering a medical case, let’s imagine that we are analyzing if someone has COVID-19.
True Positive – patients who were not COVIT-19 have been diagnosed with COVID-19.
For the GaussianNB model it was 8246 patients.
True Negative – patients who have bulls with COVIT-19, and the model has detected that they are sick.
There were 34 such people for the GaussianNB model.
False Positive – Test showed that patients did not have COVIT-19 and they were sick. This is the first type of error. For GaussainNB there were 277 people.
False Negative – This is the number of people who are healthy (marked as 0) but the model has shown that they are people with COVIT-19. This is a second type of error. For Gaussian there were 123 people.
It is easy to see that when the model without oversampling is used, the number of detected COVIT-19 patients is catastrophically low. Confusion_matrix operates only on test sets. In our case, 157 patients with COVIT-19 have 8523 healthy people.
As medical personnel, we are interested in the detection of patients. Without oversampling, Gaussian NB was detected by 34 patients out of 157 COVID-19 patients, the remaining models were correctly detected by one or two patients. That is, in the case of LogisticRegression among 157 COVIT-19 patients, one was detected as a patient (True-Negative) while 156 really COVID-19 patients were considered healthy (type II error). Furthermore, 3 healthy people were considered to be COVID-19 patients. Similarly tragic quality occurred in subsequent classification models.
After balancing the classes by applying oversampling, the COVID-19 detection level has improved significantly.
For the aforementioned LogisticRegression model, the model detected 121 patients out of 157 possible (True-Negative). However, he scared 3701 people saying that they have COVID even though they were healthy, i.e. this model caught the patients (True-Negative) while it indicated 3701 as sick although they were healthy, there were 8523 healthy (type I error). Normally, the model would fly far out the window. The discussed LogisticRegression model also found 36 patients healthy (type II error) after oversampling, i.e. it caused further infections, because these people went to work normally. the other models did better, but the results after oversampling are still not satisfactory.
W confusuin_matrix mamy 4 stany do rozważenia. Wartości te są przedstawione w postaci macierzy, w której oś Y pokazuje prawdziwe klasy, podczas gdy oś X pokazuje przewidywane klasy. Ponieważ rozpatrujemy przypadek medyczny wyobraźmy sobie, że analizujemy czy ktoś jest chory na COVID-19.
True Positive – pacjęci, którzy nie byli chorzy na COVIT-19, zostali zdiagnozowani że nie są chodzy na COVID-19.
Dla modelu GaussianNB było to 8246 pacjętów.
True Negative – pacjęci, którzy byki chorzy na COVIT-19, i model wykrył, że są chorzy.
Dla modelu GaussianNB było takich osób 34.
False Positive (czyli fałszywie zdrowy) – Test wykazał, że pacjęci nie mmieli COVIT-19 a oni byli chorzy. Jest to błąd pierwszego typu. Dla GaussainNB było to 277 osób.
False Negative (czyli fałszywie chory)- To liczba osób które są zdrowe (oznaczone jako 0) jednak model wskazał że są to osoby chore na COVIT-19. Jest to błąd drugiego rodzaju. Dla Gaussian były to 123 osoby.
Latwo zauważyć, że w przypadku użycia modelu bez oversampling ilość wykrytych chorych na COVIT-19 jest katastrofalnie niska. Confusion_matrix operuje wyłacznie na zbiorach testowych. W naszym przypadku chorych na COVIT-19 jest w 157 zaś zdrowych jest 8523 osoby.
Nas jako personel medyczny interesuje wykrywalność chorych. Bez oversampling Gaussian NB wykryło 34 chorych na 157 chorych na COVID-19, pozostałe modele wykryły prawidłowo po jednym lub dwóch pacjętów. Czyli w przypadku na przykład LogisticRegression z pośród 157 chorych na COVIT-19 jeden został wykryty jako chory (True-Negative) natomiast 156 naprawde chorych na COVID-19 zostało uznanych za zdrowych (błąd II rodzaju). Co więcej, 3 osoby zdrowe uznane zostały za chorych na COVID-19. Podobnie tragiczna jakość wystąpiła w kolejnych modelach klasyfikacji.
Po zbilansowaniu klas przez zastosowanie oversampling poziom wykrywalności COVID-19 znacznie się poprawił.
Dla wspomnianego modelu LogisticRegression model wykrył 121 chorych na 157 możliwych (True-Negative). Natomiast wystraszył 3701 osób mówiąc że mają COVID mimo, że byli zdrowi, czyli ten model wyłapał chorych (True-Negative) natomiast wskazał, 3701 jako chorych mimo, że byli zdrowi, zdrowych łącznie było 8523 (bład I typu). W normalnej sytuacji model wyleciałby daleko za okno. Omawiany model LogisticRegression po oversampling uznał też 36 chorych za zdrowych (błąd II typu) czyli przysporzył kolejnych zarażeń, bo ludzie ci poszli normalnie do pracy. pozostałe modele lepiej poroadziły sobie lecz wyniki po oversampling wciąż nie należą do zadowalających.
y_test.value_counts()
def confusion_matrix(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn.metrics import plot_confusion_matrix
for cls in six_classifiers:
cls.fit(X_train, y_train)
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(14,7))
target_names = ['0','1']
for cls, ax in zip(six_classifiers, axes.flatten()):
plot_confusion_matrix(cls,
X_test,
y_test,
ax=ax,
cmap='Blues',
display_labels=target_names,values_format='')
ax.title.set_text(type(cls).__name__)
ax.title.set_color('blue')
plt.tight_layout()
plt.show()
confusion_matrix(classifiers_A,name, X_train, y_train,X_test,y_test)
After oversampling¶
confusion_matrix(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
Recall przed oversampling¶
W naszym przykładzie Recall oznacza odsetek chorych, u których rozpoznano chorobę (true-positive) z pośród wszytkich chorych.
$ Recall = displaystylefrac{tp}{tp+fn} $
Bez oversampling mamy bardzo niezbilansowane klasy, w naszym przypadku zdrowi oznaczeni jako 0 stanowią 98% populacji zaś chorzy oznaczeni jako 1 stanowi zaledwie 2% populacji. Poziom Ricall dla modelu GaussianNB oblicza się ze wzoru:
$ Recall = displaystylefrac{34}{34+123}=0.217 $
Dla modelu LogisticRegression:
$ Recall = displaystylefrac{1}{1+154}=0.0064 $
Jak widać Recall pokazuje jaki procent chorych wskazał model jako chorych z pośród wszystkich chorych. Bez oversampling, przy mocno niezbilansowanym zbiorze wynik jest bardzo zły.
Recall po oversampling¶
Po zbilansowaniu próby przez oversampling otrzymaliśmy znacznie lepsze wyniki recall. Dla modelu GaussianNB wynik ten wyniósł:
$ Recall = displaystylefrac{120}{120+37}=0.764 $
Dla LogisticRegression:
$ Recall = displaystylefrac{121}{121+31}=0.771 $
Precission przed oversampling¶
Pokazuje ile było wykrytych chorych (true-positive) w stosunku do wszystkich wskazanych przez model chorych, czyli w stosunku do sumy naprawde chorych wskazanych przez model (True-Positive) oraz zdrowych wskazanych przez model jako chorych (false-negative)
$ Precision = displaystylefrac{tp}{tp+fp} $
Przed oversampling winik precision dla modelu GaussianNB bedzie wynosił:
$ Precision = displaystylefrac{34}{34+277} = 0.109$
Dla modelu LogisticRegression:
$ Precision = displaystylefrac{1}{1+3} = 0.25$
Precission po oversampling¶
Dla modelu GaussianNB:
$ Precision = displaystylefrac{120}{120+1739} = 0.064$
Dla modelu LogisticRegression:
$ Precision = displaystylefrac{121}{121+3701} = 0.032$
Czyli modele są dalej beznadziejne. Wyobraźmy sobie przychodnie zdrowia, w której testy wskazały chorych na COVID-19. Jednak potam okazało sie, że na stu pacjętów jedynie 6% pacjętów było naprawde zarażonych wirusem.
Oversampling nie pomógł we wskaźniku precision. Oversampling spowodował znaczny wzrost czułości modeli.
I jeszcze jedno:
Zwiększenie recall powoduje zmniejszenie precission co zobaczymy na wykresach w dalszej części opracowania.
Recall_Precision(classifiers_A,name,X_train, y_train,X_test,y_test)
Recall_Precision(classifiers_OV,name2,Xtrain_OV, ytrain_OV,X_test,y_test)
def classification_score(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn.metrics import precision_recall_fscore_support as score
Precision_0 = ['Precision_0: ']
Precision_1 = ['Precision_1: ']
Recall_0 = ['Recall_0: ']
Recall_1 = ['Recall_1: ']
f1_score_0 = ['f1-score_0: ']
f1_score_1 = ['f1-score_1: ']
Support_0 = ['Support_0: ']
Support_1 = ['Support_1: ']
for cls in six_classifiers:
cls.fit(X_train, y_train)
def compute_metric4(model):
precision, recall, fscore, support = score(y_test, model.predict(X_test))
Precision_0 = np.round(precision[:1],decimals=3).item()
Precision_1 = np.round(precision[1:],decimals=3).item()
Recall_0 = np.round(recall[:1],decimals=3).item()
Recall_1 = np.round(recall[1:],decimals=3).item()
f1_score_0 = np.round(fscore[:1],decimals=3).item()
f1_score_1 = np.round(fscore[1:],decimals=3).item()
Support_0 = np.round(support[:1],decimals=3).item()
Support_1 = np.round(support[1:],decimals=3).item()
return Precision_0, Precision_1, Recall_0, Recall_1, f1_score_0, f1_score_1, Support_0, Support_1
for cls in six_classifiers:
results = compute_metric4(cls)
Precision_0.append(results[0])
Precision_1.append(blue(results[1],'bold'))
Recall_0.append(results[2])
Recall_1.append(blue(results[3],'bold'))
f1_score_0.append(results[4])
f1_score_1.append(blue(results[5],'bold'))
Support_0.append(results[6])
Support_1.append(blue(results[7],'bold'))
t = PrettyTable(['Name', name[0],name[1],name[2],name[3],name[4],name[5]])
t.add_row(Precision_0)
t.add_row(Precision_1)
t.add_row(Recall_0)
t.add_row(Recall_1)
t.add_row(f1_score_0)
t.add_row(f1_score_1)
t.add_row(Support_0)
t.add_row(Support_1)
print(t)
print(green('RECALL - procentowy udział chorych dobrze zdiagnozowanych w populacji ludzi chorych ogółem','italic'))
print(green('PRECISION - procentowy udział chorych dobrze zdiagnozowanych w populacji ludzi zdiagnozowanyc fałszywie lub prawdziwie jako chorych','italic'))
Analiza recall – precision dla osób zdrowych¶
In our example, we examine the quality of the classification for the detection of COVID_19 patients. It is less important to say that healthy people are really healthy. Due to the fact that only 2% of patients are sick, even if they consider everyone (even the sick) to be healthy, they will have a high recall and a very high precision ratio.
Such information does not lead to anything, below are the calculations for healthy for the GaussianNB model.
W naszym przykładzie badamy jakość kalsyfikacji dla wykrywania chorych na COVID_19. Mniejsze znaczenie ma stwierdzdenie, że zdrowi są naprawde zdrowi. Przez to, że chorych jest zaledwie 2%, modele nawet jak uznają wszystkich (nawet chorych) za zdrowych będą miały wysoki recall i bardzo wysoki wskaźnik precision.
Taka informacja do niczego nie prowadzi, poniżej znajdują się kalkulacje dla zdrowych dla modelu GaussianNB.
Przed oversampling dla modelu GaussianNB:¶
$ Precision = displaystylefrac{8246}{8246+123} = 0.985$
from sklearn.metrics import confusion_matrix
NBC = NBC.fit(X_train,y_train)
confusion_matrix(y_test, NBC.predict(X_test))
Po oversampling dla modelu GaussianNB:¶
$ Precision = displaystylefrac{6784}{6784+37} = 0.995$
from sklearn.metrics import confusion_matrix
NBC_OV = NBC.fit(Xtrain_OV, ytrain_OV)
confusion_matrix(y_test, NBC_OV.predict(X_test))
classification_score(classifiers_A,name, X_train, y_train,X_test,y_test)
classification_score(classifiers_OV,name2,Xtrain_OV, ytrain_OV,X_test,y_test)
Miara f1 jest miarą łaczącą precision i recall. Jet to w przybliżeniu średni z tych dwóch wskaźników.
$ F1 = 2timesdisplaystylefrac{precisiontimes{recall}}{precision+{recall}} $
Przed oversampling dla modelu GaussianNB dla klasy 1:
$ F1 = 2timesdisplaystylefrac{0.109times{0.217}}{0.109+{0.217}}= 0.1451$
Po oversampling dla modelu GaussianNB dla klasy 1:
$ F1 = 2timesdisplaystylefrac{0.065times{0.764}}{0.065+{0.764}}= 0.1198$
Jak widać dla modelu GaussianNB zastosowanie oversampling pogorszył wynik wskaźnika F1.
def AUC_score(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn import metrics
for cls in six_classifiers:
cls.fit(X_train, y_train)
AUC_train = ['AUC_train: ']
AUC_test = ['AUC_test: ']
def compute_metric(model):
auc_train = np.round(metrics.roc_auc_score(y_train,model.predict_proba(X_train)[:,1]),decimals=3)
auc_test = np.round(metrics.roc_auc_score(y_test,model.predict_proba(X_test)[:,1]),decimals=3)
return auc_train, auc_test
for cls in six_classifiers:
results = compute_metric(cls)
AUC_train.append(results[0])
AUC_test.append(results[1])
t = PrettyTable(['Name', name[0],name[1],name[2],name[3],name[4],name[5]])
t.add_row(AUC_train)
t.add_row(AUC_test)
print(t)
Wielkość pola pod krzywą AUC jest wysoki zarówno przed jak i po oversampling. Oversampling nieznacznie wpłynął na poprawę jakości klasyfikacji modeli.
AUC_score(classifiers_A,name, X_train, y_train,X_test,y_test)
AUC_score(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
def Accuracy_score(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn.metrics import accuracy_score
for cls in six_classifiers:
cls.fit(X_train, y_train)
Accuracy_Training = ['Accuracy_Training: ']
Accuracy_Test = ['Accuracy_Test: ']
def compute_metric5(model):
Accuracy_Training = np.round(accuracy_score(y_train, model.predict(X_train)), decimals=3)
Accuracy_Test = np.round(accuracy_score(y_test, model.predict(X_test)), decimals=3)
return Accuracy_Training, Accuracy_Test
for cls in six_classifiers:
results = compute_metric5(cls)
Accuracy_Training.append(results[0])
Accuracy_Test.append(results[1])
t = PrettyTable(['Name', 'GN','LogReg','GradBoos','RandFor','LGBM','CatBoost'])
t.add_row(Accuracy_Training)
t.add_row(Accuracy_Test)
print(t)
Accuracy_score(classifiers_A,name, X_train, y_train,X_test,y_test)
Accuracy_score(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
def f1_score(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn import metrics
from sklearn.metrics import make_scorer, precision_score, fbeta_score, f1_score, classification_report
for cls in six_classifiers:
cls.fit(X_train, y_train)
classifiers = [NBC,LRE,GBC,RFC,LGBM,CBC]
f1_score_macro = ['f1_score_macro: ']
f1_score_micro = ['f1_score_micro: ']
def compute_metric6(model):
f1_score_macro = np.round(metrics.f1_score(y_test, model.predict(X_test), average='macro'), decimals=3)
f1_score_micro = np.round(metrics.f1_score(y_test, model.predict(X_test), average='micro'), decimals=3)
return f1_score_macro, f1_score_micro
for cls in six_classifiers:
results = compute_metric6(cls)
f1_score_macro.append(results[0])
f1_score_micro.append(results[1])
t = PrettyTable(['Name', 'GN','LogReg','GradBoos','RandFor','LGBM','CatBoost'])
t.add_row(f1_score_macro)
t.add_row(f1_score_micro)
print(t)
f1_score(classifiers_A,name, X_train, y_train,X_test,y_test)
f1_score(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
False Positive Rate ( type I error)¶
Błąd powstaje kiedy przewidujemy coś, gdy tego nie ma. W naszym przykładzie będzie to ilość ludzi zdrowych uznanych przez model za chorych w stosunku do wszystkich zdrowych w populacji. Czyli procentowy udział ludzi zdrowych źle zdiagnozowanych w zbiorowisku ludzi zdrowych.
Czym mniejszy jest ten udział tym lepiej!
False Positive Rate można wyliczyć ze wzoru:
$ False Positive Rate = displaystylefrac{fp}{fp+tn}$
Przed oversampling dla modelu GaussianNB dla klasy 1:
$ False Positive Rate = displaystylefrac{277}{277+8246}=0.0325$
Po oversampling dla modelu GaussianNB dla klasy 1:
$ False Positive Rate = displaystylefrac{1739}{1739+6784}=0.2040$
$begin{matrix} tn & fp \ fn & tp
end{matrix}$
To samo można obliczyć za pomocą funkcji:
from sklearn.metrics import confusion_matrix
NBC = NBC.fit(X_train,y_train)
cm = confusion_matrix(y_test, NBC.predict(X_test))
tn, fp, fn, tp = cm.ravel()
print('tn: ',tn)
print('fp: ',fp)
print('fn: ',fn)
print('tp: ',tp)
print('------------------')
print(cm)
false_positive_rate = fp / (fp + tn)
false_positive_rate
NBC_OV = NBC.fit(Xtrain_OV,ytrain_OV)
cm_ov = confusion_matrix(y_test, NBC_OV.predict(X_test))
tn, fp, fn, tp = cm_ov.ravel()
print('tn: ',tn)
print('fp: ',fp)
print('fn: ',fn)
print('tp: ',tp)
print('------------------')
print(cm_ov)
false_positive_rate = fp / (fp + tn)
false_positive_rate
True Positive Rate (type II error) RECALL¶
W liczniku jest ilość chorych uznanych przez model za chorych. Wskaźnik mówi jaki jest procentowy udział chorych dobrze zdiagnozowanych w populacji ludzi chorych ogółem.
$ True Positive Rate = displaystylefrac{tp}{tp+fn}$
Przed oversampling dla modelu GaussianNB dla klasy 1:
$ True Positive Rate = displaystylefrac{34}{34+123} = 0.2165 $
Po oversampling dla modelu GaussianNB dla klasy 1:
$ True Positive Rate = displaystylefrac{120}{120+37} = 0.7643 $
Generalnie zbilansowanie populacji przez oversampling znacznie poprawiło zdolności klasyfikacyjne modeli co widać na przykładzie czerwonego punktu który wyemigrował w okolicę połowy krzywej ROC.
Podobnie poprawił sie nieznacznie rozmiar pola AUC.
????_????????_???? = tp / (tp + fn)
????_????????_????
False Negative Rate (type II error)¶
Wskaźnik ten można zdefiniować jako procentowy udział niewykrytych chorych (fn) w badanej populacji.
Czyli ilość niewykrytych chorych jest dzielona przez sume wszystkich faktycznie chorych. To coś w rodzaju recall lecz tu w liczbniku zamiast chorych wykrytych jest liczba chorych niewykrytych.
$ False Negative Rate = displaystylefrac{fn}{tp+fn}$
from sklearn.metrics import confusion_matrix
NBC = NBC.fit(X_train,y_train)
cm = confusion_matrix(y_test, NBC.predict(X_test))
tn, fp, fn, tp = cm.ravel()
print('tn: ',tn)
print('fp: ',fp)
print('fn: ',fn)
print('tp: ',tp)
print('------------------')
print(cm)
False_Negative_Rate = fn/(tp+fn)
False_Negative_Rate
True Negative Rate (Specificity)¶
W naszym przykładzie wykrywania chorych COVID-19 pokazuje nam, ilu ludzi zdrowych procentowo spośród wszystkich zdrowych sklasyfikowano jako zdrowych. Jak wypada 80% to znaczy że 20% ludzi zdrowych zostało niepotrzebnie wystraszonych, że są chorzy.
$ Specificity = displaystylefrac{tn}{tn+fp}$
def Type_error(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn import metrics
import simple_colors
for cls in six_classifiers:
cls.fit(X_train, y_train)
FPR = ['False_Positive_Rate:']
TPR = ['True_Positive_Rate: ']
FNR = ['False_Negative_Rate: ']
SPEC = ['Specifity']
def compute_metric(model):
FPR = np.round(fp/(fp + tn),decimals=3)
TPR = np.round(tp/(tp + fn),decimals=3)
FNR = np.round(fn/(tp + fn),decimals=3)
SPEC = np.round(tn/(tn + fp),decimals=3)
return FPR,TPR,FNR,SPEC
for cls in six_classifiers:
cls.fit(X_train,y_train)
cm = confusion_matrix(y_test, cls.predict(X_test))
tn, fp, fn, tp = cm.ravel()
kom =['1','2','3','4']
results = compute_metric(cls)
FPR.append(results[0])
TPR.append(red(results[1],'bold'))
FNR.append(results[2])
SPEC.append(results[3])
t = PrettyTable(['Name', name[0],name[1],name[2],name[3],name[4],name[5]])
t.add_row(FPR)
t.add_row(TPR)
t.add_row(FNR)
t.add_row(SPEC)
print(t)
print(black('False_Positive_Rate - procentowy udział ludzi zdrowych uznanych przez model za chorych w populacji ludzi zdrowych','italic'))
print(red('True_Positive_Rate RECALL - procentowy udział chorych dobrze zdiagnozowanych w populacji ludzi chorych ogółem','italic'))
print(black('False_Negative_Rate - procentowy udział niewykrytych chorych w populacji ludzi chorych ogółem','italic'))
print(black('Specifity - procentowy udział ludzi zdrowych uznanych za zdrowych w populacji ludzi zdrowych','italic'))
Type_error(classifiers_A,name, X_train, y_train,X_test,y_test)
Jak widać w zbiorze wysoko niezbilansowanym modele uznawały prawie wszystkich za zdrowych. Ogolnie efektywność modeli w wykrywaniu ludzi chorych była bardzo słaba (True_Positive_Rate). W najlepszym modelu NBC wykrywalność ludzi chorych wynosiła około 20%, w pozostałych modelach wykrywalność była bliska zeru. Przy bardzo niezbilansowanych zbiorach, mimo że model nie wykrył żadnego chorego, zachował bardzo wysoki wskażnik accuracy.
Type_error(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
Po zbilansowaniu zbiorów za pomocą oversampling okazało modele zaczęły znacznie lepiej wykrywać ludzi chorych w populacji ludzi chorych (True_Positive_Rate). Model NBC posiada teraz wykrywalność rzędu 76%, przy okazji około 20% ludzi zdrowych model ten uznaje za chorych (False_Positive_Rate). Model LogisticRegresion ma podobną wykrywalność ludzi chorych co NBC na poziomie 77% niestety ma znacznie wyższy 43 procentowy udział określania ludzi zdrowych jako chorych (False_Positive_Rate).
Binary Class Plot¶
def BinaryClassPlot(six_classifiers,name, X_train, y_train,X_test,y_test):
from plot_metric.functions import BinaryClassification
for cls in six_classifiers:
cls.fit(X_train, y_train)
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_color('blue')
model = six_classifiers[i]
bc = BinaryClassification(y_test, model.predict_proba(X_test)[:,1], labels=["Class 1", "Class 2"])
bc.plot_roc_curve(title=type(six_classifiers[i]).__name__)
Najbardziej na wykresie ROC AUC przyciąga uwagę czerwony punkt. Współczędne czerwonego punktu znajdują się na osi X i y. wspołczędne osi X to False Positive Rate.
Punkt ten ma wsplrzędne dla X:False_Positive_Rate, y:True_Positive_Rate.
BinaryClassPlot(classifiers_A,name, X_train, y_train,X_test,y_test)
BinaryClassPlot(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
def Precision_Recall_plot(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn.metrics import confusion_matrix, log_loss, auc, roc_curve, roc_auc_score, recall_score, precision_recall_curve
for cls in six_classifiers:
cls.fit(X_train, y_train)
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(16,7))
for cls, ax in zip(six_classifiers, axes.flatten()):
precision, recall, thresholds = precision_recall_curve(y_test, cls.predict_proba(X_test)[:,1])
ax.plot(recall, precision, marker='.', label='model')
ax.title.set_text(type(cls).__name__)
ax.title.set_color('blue')
ax.set_xlabel('Recall', color='grey', alpha=0.8)
ax.set_ylabel('Precision', color='grey', alpha=0.8)
plt.tight_layout()
plt.show()
Precision_Recall_plot(classifiers_A,name, X_train, y_train,X_test,y_test)
Precision_Recall_plot(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
Cohen Kappa Metric¶
$ bbox[20px,border:1px solid red]
{
κ = displaystylefrac{(p_o – p_e)}{(1 – p_e)}=1-frac{1 – p_e}{1 – p_e}
qquad
} $
where:
$ p_0 = displaystylefrac{(tn+??)}{(tn+fp+fn+??)}$
$ p_{empire} = displaystylefrac{(tn+fp)}{(tn+fp+fn+??)}timesfrac{(tn+fn)}{(tn+fp+fn+??)}$
$ p_{theory} = displaystylefrac{(fn+??)}{(tn+fp+fn+??)}timesfrac{(fp+??)}{(tn+fp+fn+??)}$
$ p_e = p_{empire}+p_{theory}$
Zaleca się korzystać z kappa Cohena obliczając go osobno dla każdej etykiety. W przeciwnym razie najlepszym rozwiązaniem byłoby użycie Alfa Krippendorffa do określania niezawodności między oceniającymi
$begin{matrix} tn & fp \ fn & tp
end{matrix}$
tn = 45
fp = 15
fn = 25
tp = 15
p_0 = (tn+??)/(tn+fp+fn+??)
print(‘p_0:’,p_0)
P_yes = ((tn+fp)/(tn+fp+fn+??))*((tn+fn)/(tn+fp+fn+??))
print(‘P_yes: ‘,P_yes)
P_no = ((fn+??)/(tn+fp+fn+??))*((fp+??)/(tn+fp+fn+??))
print(‘P_no: ‘,P_no)
pe = P_yes + P_no
print(‘pe: ‘,pe)
κ = (p_0-pe)/(1-pe)
print(‘κ: ‘,κ)
def Cohen_Kappa(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn import metrics
import simple_colors
for cls in six_classifiers:
cls.fit(X_train, y_train)
κ = ['κ:']
p0 = ['p0:']
pe = ['pe:']
def compute_metric(model):
from sklearn.metrics import confusion_matrix
model.fit(X_train,y_train)
cm = confusion_matrix(y_test, model.predict(X_test))
tn, fp, fn, tp = cm.ravel()
p0 = (tn+??)/(tn+fp+fn+??)
P_empire = ((tn+fp)/(tn+fp+fn+??))*((tn+fn)/(tn+fp+fn+??))
P_theory = ((fn+??)/(tn+fp+fn+??))*((fp+??)/(tn+fp+fn+??))
pe = P_empire + P_theory
κ = (p0-pe)/(1-pe)
κ = np.round(κ,decimals=3)
p0 = np.round(p0,decimals=3)
pe = np.round(pe,decimals=3)
return κ,p0, pe
for cls in six_classifiers:
results = compute_metric(cls)
κ.append(blue(results[0],'bold'))
p0.append(results[1])
pe.append(results[2])
t = PrettyTable(['Name', name[0],name[1],name[2],name[3],name[4],name[5]])
t.add_row(p0)
t.add_row(pe)
t.add_row(κ)
print(t)
print(blue('Obserwowana zgodność p0', 'underlined'))
print(black('Jest to prawdopodobieństwo dobrego wyboru, to procent przypadków, które zostały sklasyfikowane prawidłowo w całej matrycy zamieszania, czyli prawdziwi chorzy zostali sklasyfikowani jako chorzy a prawdziwie zdrowi sklasyfikowani jako prawdziwie zdrowi','italic'))
print(blue('Oczekiwana zgodność pe', 'underlined'))
print(black('Jest to prawdopodobieństwo wyboru bezpośrednio związana z liczbą wystąpień każdej klasy. Jeżeli wystąpień klas było po równo (np. 1: 20 wystąpień i 0: 20 wystapień), czyli zbiór był zbilansowany, to prawdopodobieństwo wynosi 50%. ','italic'))
print(blue('Cohen Kappa mówi, o ile lepszy jest model klasyfikacji (p0) od losowego klasyfikatora(pe), który przewiduje na podstawie częstotliwości klas.','italic'))
print(black(''))
print(black('Statystyka może być ujemna, co oznacza, że nie ma skutecznej zgodności między dwoma wskaźnikami lub zgodność jest gorsza niż losowa.'))
Cohen_Kappa(classifiers_A,name, X_train, y_train,X_test,y_test)
Cohen_Kappa(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
Zbilansowanie zbiorów w sposób nieznaczny wpłynęło na to, aby obserwowana zgodność p0 była lepsza od oczekiwanej zgodność pe.
Matthews Correlation Coefficient MCC¶
Współczynnik korelacji Matthewsa (MCC) ma zakres od -1 do 1, gdzie -1 oznacza całkowicie zły klasyfikator binarny, a 1 oznacza całkowicie poprawny klasyfikator binarny.
$ bbox[23px,border:1px solid red]
{
MCC = displaystylefrac{{(tp times tn)}-{(fp times fn)}}{(tp+fp)(tp+fn)(tn+fp)(tn+fn)}
qquad
} $
def MCC(six_classifiers,name, X_train, y_train,X_test,y_test):
from sklearn import metrics
import simple_colors
for cls in six_classifiers:
cls.fit(X_train, y_train)
MCC = ['MCC:']
def compute_metric(model):
from sklearn.metrics import confusion_matrix
model.fit(X_train,y_train)
cm = confusion_matrix(y_test, model.predict(X_test))
tn, fp, fn, tp = cm.ravel()
MCC = ((tp*tn)-(fp*fn))/(((tp+fp)*(tp+fn)*(tn+fp)*(tn+fn))** .5)
MCC = np.round(MCC,decimals=6)
MCC
return MCC
for cls in six_classifiers:
results = compute_metric(cls)
MCC.append(results)
t = PrettyTable(['Name', name[0],name[1],name[2],name[3],name[4],name[5]])
t.add_row(MCC)
print('Matthews Correlation Coefficient MCC')
print(t)
print(black('Współczynnik korelacji Matthewsa (MCC) ma zakres od -1 do 1, gdzie -1 oznacza całkowicie zły klasyfikator binarny, a 1 oznacza całkowicie poprawny klasyfikator binarny','italic'))
MCC(classifiers_A,name, X_train, y_train,X_test,y_test)
MCC(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
Plot_roc¶
def plot_roc(six_classifiers,name, X_train, y_train,X_test,y_test):
import scikitplot as skplt
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for cls in classifiers_A:
cls.fit(X_train, y_train)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_color('blue')
model = classifiers_A[i]
skplt.metrics.plot_roc(y_test, model.predict_proba(X_test), ax=ax, title=type(six_classifiers[i]).__name__)
plt.show()
W tym teście szczególnie waża jest różnica pomiedzy krzywą micro-average ROC pokazaną na różowo oraz krzywą macro-average ROC pokazana na granatowo.
Idealnie gdy obie krzywe się pokrywają. Zbilansowanie klas prze oversampling poprawiło w wielu medelach spójność obu krzywych, w niektórych jednak pozostały duże różnice.
Jeżeli:
macro average ROC > micro average ROC
wtedy mówimy, że: “1 (minority) is better classified than 0 (majority) – macro > micro”
Jeżeli:
macro average ROC micro average ROC
wtedy mówimy, że: ‘0 (majority) is better classified than 1 (minority)- micro < macro’
Idealnie gdy krzywe micro i macro pokrywają się ze sobą. Taka sytuacja ma miejsce po oversampling w GaussianNB oraz GradientBoostingClassifier.
plot_roc(classifiers_A,name, X_train, y_train,X_test,y_test)
plot_roc(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
def Trainsize(six_classifiers,name, X_train, y_train,X_test,y_test):
from mlxtend.plotting import plot_learning_curves
for cls in six_classifiers:
cls.fit(X_train, y_train)
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_text(type(six_classifiers[i]).__name__)
ax.title.set_color('blue')
model = six_classifiers[i]
plot_learning_curves(X_train, y_train,
X_test, y_test,
model, print_model=False, style='ggplot')
Learning_curves¶
Najważniejsza są informacje:
- jeżeli zbiór testowy i treningowy bardzo odstają od siebie oznacza to przeuczenie modelu
- znajduje się miejsce gdzie oba wykresy testowy i treningowy są najbliżej siebie. Dla takiej wielkości próby model działa najlepiej w kontekście przeuczenia
- na wykresie należy brać pod uwagę wielkość błędu klasyfikacji (oś y)
Dobrym wskaźnikiem przeuczenia jest różnica predykcji pomiedzy zbiorem treningowym i zbiorem testowym.
W modelu GaussianNB przed oversampling występuje średni błąd wielkości 0.045. oba zbiory testowy i treningowy są blisko siebie dla każdej wielkości próby. Wpodobnie było w przypadku LogisticRegression, natomiast model GradientBoosting poprawiał swój poziom nauki wraz z wielkością próbki.
Najmniejsza różnica pomiędzy błedami zbioru treningowego i testowego dla modelu LGBMClassifier znajduje sie dla 90% zbioru treningowego.
Trainsize(classifiers_A,name, X_train, y_train,X_test,y_test)
Trainsize(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
y_train.dtypes
def ks_statistic(six_classifiers,name, X_train, y_train,X_test,y_test):
import scikitplot as skplt
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for cls in six_classifiers:
cls.fit(X_train, y_train)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_color('blue')
model = classifiers_A[i]
# skplt.metrics.plot_roc(y_test, model.predict_proba(X_test), ax=ax, title=type(six_classifiers[i]).__name__)
skplt.metrics.plot_ks_statistic(y_test, model.predict_proba(X_test), ax=ax,title=type(six_classifiers[i]).__name__)
plt.show()
ks_statistic(classifiers_A,name, X_train, y_train,X_test,y_test)
ks_statistic(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
def precision_recall2(six_classifiers,name, X_train, y_train,X_test,y_test):
import scikitplot as skplt
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for cls in six_classifiers:
cls.fit(X_train, y_train)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_color('blue')
model = six_classifiers[i]
skplt.metrics.plot_precision_recall(y_test, model.predict_proba(X_test), ax=ax,title=type(six_classifiers[i]).__name__)
plt.show()
print(blue('Jest to krzywa łącząca precyzję (PPV) i Recall (TPR) na jednym wykresie. Im wyższa krzywa na osi y, tym lepsza wydajność modelu. Informuje, przy którym recall, precision zaczyna spadać, może pomóc wybrać próg'))
precision_recall2(classifiers_A,name, X_train, y_train,X_test,y_test)
precision_recall2(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
Jak widac na wykresach problemem jest precyzjia klasy 1. Nie pomogła w tym zbilansowanie zbiorów przez oversampling.
def calibration_curve2(six_classifiers,name, X_train, y_train,X_test,y_test):
import scikitplot as skplt
from sklearn.calibration import CalibratedClassifierCV, calibration_curve
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for cls in six_classifiers:
cls.fit(X_train, y_train)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_color('blue')
model = classifiers_A[i]
A_probas = model.fit(X_train, y_train).predict_proba(X_test)
probas_list = [A_probas]
clf_names = [name[i]]
skplt.metrics.plot_calibration_curve(y_test,probas_list,clf_names,title=type(six_classifiers[i]).__name__,ax=ax)
plt.show()
calibration_curve2(classifiers_A,name, X_train, y_train,X_test,y_test)
calibration_curve2(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
Wyraźnie widać, że modele nie są skalibrowane.
https://machinelearningmastery.com/calibrated-classification-model-in-scikit-learn/
Co by sie stałom gdybyśmy je teraz spróbowali skalibrować?¶
from sklearn.datasets import make_classification
from sklearn.calibration import CalibratedClassifierCV
from sklearn.calibration import calibration_curve
import scikitplot as skplt
from sklearn.calibration import CalibratedClassifierCV, calibration_curve
NBC = GaussianNB()
LRE = LogisticRegression(solver='lbfgs')
GBC = GradientBoostingClassifier()
RFC = RandomForestClassifier()
LGBM = LGBMClassifier()
CBC = CatBoostClassifier(verbose=0, n_estimators=100)
classifiers_A = [NBC,LRE,GBC,RFC,LGBM,CBC]
name = ['NBC','LRE','GBC','RFC','LGBM','CBC']
#for cls in classifiers_A:
# calibrated = CalibratedClassifierCV(cls, method='sigmoid', cv=5)
# calibrated.fit(X_train, y_train)
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_color('blue')
model = classifiers_A[i]
calibrated = CalibratedClassifierCV(model, method='sigmoid', cv=5)
calibrated.fit(X_train, y_train)
A_probas = calibrated.fit(X_train, y_train).predict_proba(X_test)
probas_list = [A_probas]
clf_names = [name[i]]
skplt.metrics.plot_calibration_curve(y_test,probas_list,clf_names,title=type(classifiers_A[i]).__name__,ax=ax)
plt.show()
def cumulative_gain(six_classifiers,name, X_train, y_train,X_test,y_test):
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for cls in six_classifiers:
cls.fit(X_train, y_train)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_color('blue')
model = six_classifiers[i]
skplt.metrics.plot_cumulative_gain(y_test, model.predict_proba(X_test), ax=ax,title=type(six_classifiers[i]).__name__)
plt.show()
cumulative_gain(classifiers_A,name, X_train, y_train,X_test,y_test)
cumulative_gain(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
def lift_curve(six_classifiers,name, X_train, y_train,X_test,y_test):
plt.figure(figsize=(15,7))
grid = plt.GridSpec(2, 3, wspace=0.3, hspace=0.4)
for cls in six_classifiers:
cls.fit(X_train, y_train)
for i in range(6):
col, row = i%3,i//3
ax = plt.subplot(grid[row,col])
ax.title.set_color('blue')
model = six_classifiers[i]
skplt.metrics.plot_lift_curve(y_test, model.predict_proba(X_test), ax=ax,title=type(six_classifiers[i]).__name__)
plt.show()
lift_curve(classifiers_A,name, X_train, y_train,X_test,y_test)
lift_curve(classifiers_OV,name2, Xtrain_OV, ytrain_OV,X_test,y_test)
