Exercise 29
Naive Bayes Classifier
Naiwny Bayes to prosta technika konstruowania klasyfikatorów: modele, które przypisują etykiety klas do wystąpień problemowych, reprezentowane jako wektory wartości cech , w których etykiety klas są rysowane z pewnego zbioru skończonego. Nie istnieje jeden algorytm do szkolenia takich klasyfikatorów, ale rodzina algorytmów oparta na wspólnej zasadzie: wszystkie naiwne klasyfikatory Bayesa zakładają, że wartość określonej cechy jest niezależna od wartości innej cechy, biorąc pod uwagę zmienną klasy. Na przykład owoc można uznać za jabłko, jeśli jest czerwone, okrągłe i ma około 10 cm średnicy. Naiwny klasyfikator Bayesa uważa, że każda z tych cech przyczynia się niezależnie do prawdopodobieństwa, że ten owoc jest jabłkiem, niezależnie od wszelkich możliwych korelacje między kolorem, okrągłością i średnicą.
W przypadku niektórych rodzajów modeli prawdopodobieństwa naiwnych klasyfikatorów Bayesa można bardzo skutecznie trenować w nadzorowanym środowisku uczenia się . W wielu praktycznych zastosowaniach estymacja parametrów dla naiwnych modeli Bayesa wykorzystuje metodę maksymalnego prawdopodobieństwa ; innymi słowy, można pracować z naiwnym modelem Bayesa bez akceptacji prawdopodobieństwa bayesowskiego lub przy użyciu jakichkolwiek metod bayesowskich.
Pomimo naiwnego projektu i pozornie uproszczonych założeń, naiwne klasyfikatory Bayesa działały całkiem dobrze w wielu złożonych rzeczywistych sytuacjach. W 2004 r. Analiza problemu klasyfikacji bayesowskiej wykazała, że istnieją uzasadnione teoretyczne powody pozornie nieprawdopodobnej skuteczności naiwnych klasyfikatorów Bayesa. [6] Jednak kompleksowe porównanie z innymi algorytmami klasyfikacji w 2006 r. Wykazało, że klasyfikacja Bayesa jest lepsza niż inne podejścia, takie jak wzmocnione drzewa lub losowe lasy . [7]
Zaletą naiwnych Bayesa jest to, że wymaga jedynie niewielkiej liczby danych treningowych do oszacowania parametrów niezbędnych do klasyfikacji.
źródło: https://en.wikipedia.org/wiki/Naive_Bayes_classifier
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.preprocessing import LabelEncoder
import matplotlib.pylab as plt
from pylab import plot, show, subplot, specgram, imshow, savefig
from sklearn import preprocessing
from sklearn.preprocessing import Normalizer
from sklearn.preprocessing import Imputer
import matplotlib.pyplot as plote
plt.style.use('ggplot')
df = pd.read_csv('c:/1/bank.csv')
df.head()
Jak w praktyce zastosować Naive Bayes Classifier w marketingu bankowym?
Departament marketingu bankowego niedawno przeprowadził akcję promocyjną. Klienci byli zachęcani do skorzystania z oferty banku – zaciągania kredytów w rachunku bieżącym. Cała operacja została skrupulatnie odnotowana w formie tabeli danych. Tabelę danych można znaleźć pod adresem: https://archive.ics.uci.edu/ml/machine-learning-databases/00222/
Dane klienta banku
age: (numerycznie)
job: rodzaj pracy (kategorycznie: „admin.”, „Pracownik fizyczny”, „przedsiębiorca”, „pokojówka”, „zarządzanie”, „emerytowany”, „samozatrudniony”, „ usługi ”,„ student ”,„ technik ”,„ bezrobotny ”,„ nieznany ”)
marital: stan cywilny (kategorycznie:„ rozwiedziony ”,„ żonaty ”,„ samotny ”,„ nieznany ”; uwaga:„ rozwiedziony ”oznacza rozwiedziony lub owdowiały)
education: (kategoryczne: „podstawowy. 4 lata”, „podstawowy. 6 lat”, „podstawowy. 9 lat”, „szkoła średnia”, „analfabeta”, „kurs zawodowy”, „uniwersytet. stopień”, „nieznane”)
default: czy kredyt jest niespłacony? (kategorycznie: „nie”, „tak”, „nieznany”)
housing: ma kredyt mieszkaniowy? (kategorycznie: „nie”, „tak”, „nieznany”)
loan: czy pożyczka osobista? (kategorycznie: „nie”, „tak”, „nieznany”)
Powiązane z ostatnim kontaktem bieżącej kampanii
contact: typ komunikacji kontaktowej (kategorycznie: „komórkowy”, „telefon”)
month:ostatni miesiąc kontaktowy w roku (kategorycznie: „jan”, „lut”, „mar”, …, „lis”, „dec”)
day_of_week: ostatni dzień tygodnia w tygodniu (kategorycznie: „pon”, „wt”, „środ”, „czw”, „pt”)
duration: czas trwania ostatniego kontaktu, w sekundach (numerycznie) . Ważna uwaga: ten atrybut ma duży wpływ na docelowy wynik (np. Jeśli czas trwania = 0, to y = „nie”). Jednak czas trwania nie jest znany przed wykonaniem połączenia. Ponadto po zakończeniu połączenia y jest oczywiście znane. W związku z tym dane te należy uwzględnić wyłącznie do celów porównawczych i należy je odrzucić, jeżeli intencją jest stworzenie realistycznego modelu predykcyjnego.
Inne atrybuty
campaign: liczba kontaktów wykonanych podczas tej kampanii i dla tego klienta (numerycznie, obejmuje ostatni kontakt)
pdays: liczba dni, które upłynęły od ostatniego kontaktu klienta z poprzedniej kampanii (numerycznie; 999 oznacza, że klient nie był wcześniej skontaktowano się)
previous: liczba kontaktów wykonanych przed tą kampanią i dla tego klienta (numerycznie)
poutcome:wynik poprzedniej kampanii marketingowej (kategorycznie: „porażka”, „nieistniejąca”, „sukces”)
Atrybuty kontekstu społecznego i gospodarczego
emp.var.rate: wskaźnik zmienności zatrudnienia – wskaźnik kwartalny (liczbowy)
Cons.price.idx: wskaźnik cen konsumpcyjnych – wskaźnik miesięczny (liczbowy)
cons.conf.idx: wskaźnik zaufania konsumentów – wskaźnik miesięczny (liczbowy )
euribor3 mln: stawka 3-miesięczna euribor – wskaźnik dzienny (liczbowy)
nr_employed: liczba zatrudnionych: liczba pracowników – wskaźnik kwartalny (liczbowy)
df = pd.read_csv('c:/1/bank.csv')
df.shape
Sprawdzamy czy baza zawiera komórki puste, Naive Bayes Classifier nie działa gdy baza zawiera komórki puste.
df.isnull().sum()
Brak komórek pustych w rejestrze bankowym.
df.head()
Kasujemy z rejestru następujące klumny:
Usuwam kolumny: 'day_of_week’,’month’,’previous’,’campaign’,’duration’, 'contact’, 'y’
df.columns
df = df[['age', 'job', 'marital', 'education','default', 'housing', 'loan', 'poutcome', 'emp_var_rate','cons_price_idx', 'cons_conf_idx', 'euribor3m', 'nr_employed','y']]
df.head(5)
Tworzenie Dummy Variables
Naive Bayes Classifier działa na zmiennych numerycznych. Trzeba więc zamienić zmienne tekstowe na format numeryczny.
Wyświetlamy kolumny zmiennnych dyskretnych
df.describe(include=["object"]).columns
list = ['job', 'marital', 'education', 'default', 'housing', 'loan','poutcome']
Transforumjemy na dane dummy variables
df[list] = df[list].apply(LabelEncoder().fit_transform)
df[list].head()
Dzielimy nowy zbiór df na zmienne opisujące i zmienną wynikową.
y = df['y']
X = df.drop('y', axis=1)
Dzielimy zbiór df na zbiór testowy i zbiór treningowy.
from sklearn.model_selection import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(X,y, test_size=0.33, stratify = y, random_state = 148)
OVERSAMPLING
Dla zbioru df bo zmienna wynikowa nie jest zbilansowana. Oversampling robimy na zmiennych treningowych.
df.y.value_counts(dropna = False, normalize=True)
Proporcja = sum(ytrain == 0) / sum(ytrain == 1)
Proporcja = np.round(Proporcja, decimals=0)
Proporcja = Proporcja.astype(int)
print('Ile na jedną sybskrypcje przypada nieprzedłużonych subskrypcji:',Proporcja)
Replikacja zmiennych wynikowych w zbiorze treningowym
ytrain_pos_OVS = pd.concat([ytrain[ytrain==1]] * Proporcja, axis = 0)
print('Ilość zmiennych wynikowych y w zbiorze treningowym df po replikacji:' ,ytrain_pos_OVS.count())
Replikacja zmiennych niezależnych w zbiorze treningowym
Xtrain_pos_OVS = pd.concat([Xtrain.loc[ytrain==1, :]] * Proporcja, axis = 0)
ytrain_pos_OVS = pd.concat([ytrain[ytrain==1]] * Proporcja, axis = 0)
print('Ilość zmiennych niezależnychX z zbiorze treningowym df po replikacji:')
Xtrain_pos_OVS.count()
Wprowadzenie nowych, zreplikowanych zmiennych do zbioru treningowego
ytrain_OVS = pd.concat([ytrain, ytrain_pos_OVS], axis = 0).reset_index(drop = True)
Xtrain_OVS = pd.concat([Xtrain, Xtrain_pos_OVS], axis = 0).reset_index(drop = True)
Sprawdzenie ilość wierszy w zbiorach przed i po oversampling
print ('Zbiór X treningowy: ',Xtrain.shape)
print ('Zbiór X testowy: ', Xtest.shape)
print ('Zbiór y treningowy: ', ytrain.shape)
print ('Zbiór y testowy: ', ytest.shape)
Xtrain_OVS.head(3)
Naive Bayes Classifier na zbiorze df
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
gnb.fit(Xtrain, ytrain)
Podstawienie do wzoru
y_pred = gnb.predict(Xtest)
Blok diagnostyczny
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
print("Recall Training data: ", np.round(recall_score(ytrain_OVS, gnb.predict(Xtrain_OVS)), decimals=4))
print("Precision Training data: ", np.round(precision_score(ytrain_OVS, gnb.predict(Xtrain_OVS)), decimals=4))
print("----------------------------------------------------------------------")
print("Recall Test data: ", np.round(recall_score(ytest, gnb.predict(Xtest)), decimals=4))
print("Precision Test data: ", np.round(precision_score(ytest, gnb.predict(Xtest)), decimals=4))
print("----------------------------------------------------------------------")
print("Confusion Matrix Test data")
print(confusion_matrix(ytest, gnb.predict(Xtest)))
print("----------------------------------------------------------------------")
print(classification_report(ytest, gnb.predict(Xtest)))
y_pred_proba = gnb.predict_proba(Xtest)[::,1]
fpr, tpr, _ = metrics.roc_curve(ytest, y_pred_proba)
auc = metrics.roc_auc_score(ytest, y_pred_proba)
plt.plot(fpr, tpr, label='Logistic Regression (auc =
plt.xlabel('False Positive Rate',color='grey', fontsize = 13)
plt.ylabel('True Positive Rate',color='grey', fontsize = 13)
plt.title('Receiver operating characteristic')
plt.legend(loc="lower right")
plt.legend(loc=4)
plt.plot([0, 1], [0, 1],'r--')
plt.show()
Tworzenie listy dla kierownika marketingu
print('Lista dla kierownika marketingu bankowego')
df3[df3['Wynik']==1].head(4)
Statystyka
Threshold ROC curve
Klasyfikacja dla progów od 0.2 do 0.9 Threshold ROC curve
gnb_ytest = gnb.predict_proba(X)[:, 1]
X.shape
Klasyfikacja dla progów threshold = od 0.2 do 0.9
y_predT09 = (gnb_ytest >= 0.9).astype(int)
df['ResultTH09'] = y_predT09
y_predT08 = (gnb_ytest >= 0.8).astype(int)
df['ResultTH08'] = y_predT08
y_predT07 = (gnb_ytest >= 0.7).astype(int)
df['ResultTH07'] = y_predT07
y_predT06 = (gnb_ytest >= 0.6).astype(int)
df['ResultTH06'] = y_predT06
y_predT05 = (gnb_ytest >= 0.5).astype(int)
df['ResultTH05'] = y_predT05
y_predT04 = (gnb_ytest >= 0.4).astype(int)
df['ResultTH04'] = y_predT04
y_predT03 = (gnb_ytest >= 0.3).astype(int)
df['ResultTH03'] = y_predT03
y_predT02 = (gnb_ytest >= 0.2).astype(int)
df['ResultTH02'] = y_predT02
df.head(3)
Punktacja dla każdego klienta
df['Customer_classification']= df['ResultTH02']+df['ResultTH03']+df['ResultTH04']+df['ResultTH05']+df['ResultTH06']+df['ResultTH07']+df['ResultTH08']+df['ResultTH09']
df.sort_values('Customer_classification').head(4)
df.pivot_table(index =['Customer_classification'],values='marital', aggfunc='count').plot(kind='bar', legend=False)
df['ResultTH05'].value_counts(normalize=True)
Podsumowanie
Porównaine Logistic Regression Classifier z Naive Bayes Classifier.
Logistic Regression na zbiorze df
precision recall f1-score support
0 0.95 0.76 0.85 12062
1 0.27 0.68 0.38 1531
accuracy 0.75 13593
macro avg 0.61 0.72 0.61 13593
weighted avg 0.87 0.75 0.79 13593
Naive Bayes Classifier na zbiorze df¶
precision recall f1-score support
0 0.95 0.78 0.86 12062
1 0.28 0.66 0.39 1531
accuracy 0.77 13593
macro avg 0.61 0.72 0.62 13593
weighted avg 0.87 0.77 0.80 13593
