
Exercise 27
Marketing bankowy – działalność podmiotów gospodarczych mającą na celu poznanie i dostosowanie się do potrzeb rynku oraz oddziaływanie na popyt i podaż, uwzględniając wymagania i preferencje finalnych nabywców.
Zatem koncepcja marketingu oznacza, że punktem wyjścia działalności podmiotów gospodarczych, są potrzeby i wymagania ostatecznych odbiorców, jak również dostosowanie się do zmiennych warunków rynkowych i wywieraniu wpływu na rynek dla osiągnięcia swoich celów.
Marketing bankowy to system zintegrowanych działań banku dostępnymi instrumentami w celu dostosowania się do potrzeb rynku, zaspokojenia tych potrzeb swoimi produktami, kreowania popytu na te produkty, a także poszukiwania nowych rynków lub nisz rynkowych oraz kształtowania i utrwalania pozytywnego wizerunku banku w społeczeństwie.
źródło: https://pl.wikipedia.org/wiki/Marketing_bankowy
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
%matplotlib inline
plt.style.use('ggplot')
df = pd.read_csv('c:/1/bank.csv')
df.head()
Jak w praktyce zastosować model Linear Regression 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)
Poprzednią analize Marketingu Bankowego, można znaleźć pod adresem:
http://sigmaquality.pl/machine-learning/artificial-intelligence-w-marketingu-bankowym
Kierownik Marketingu Bankowego dowiedział się z niej, jakie grupy klientów są najbardziej przewidywalne oraz które zmienne wpływają na decyzję klientów. Dowiedział się również, jakie znaczenie mają określone techniki operacyjne takie jak średni czas rozmowy i liczba kontaktów z klientem. Jak ważny jest czas między kolejnymi kontaktami, czego unikać a o czym rozmawiać z klientami. Te informacje pozwolą kierownikowi podnieść efektywność sprzedaży w kolejnych kampaniach promocyjnych.
Przyjmijmy, że dane zamieszczone pod powyższym adresem (https://archive.ics.uci.edu/ml/machine-learning-databases/00222/) są danymi historycznymi banku z poprzednich akcji promocyjnych. Teraz Kierownik Marketingu Bankowego ma listą 150 nowych klientów banku. Kierownik chce wiedzieć, którzy klienci, na podstawie historii poprzednich akcji promocyjnych, najprawdopodobniej wezmą kredyt.
Kierownik dysponując określonymi zasobami ludzkimi i czasem, chce więc skoncentrować swoje wysiłki na określonych, wskazanych przez algorytm artificial intelligence klientach. Dzięki temu ma nadzieję na poprawę efektywności sprzedaży banku.
Ponieważ nie posiadamy listy 150 nowych klientów, wydzielimy 150 przypadkowych rekordów z bazy UC Irvine Machine Learning Repository (https://archive.ics.uci.edu/ml/machine-learning-databases/00222/)
Wydzielam listę 150 nowych klientów banku.
df = pd.read_csv('c:/1/bank.csv')
df3 = df.sample(150)
df3.shape
Niestety nie można wykorzystać modeli z poprzedniej analizy ponieważ zawiera on zmienne, których nie potrafimy przewidzieć w przyszłości.
Nie wiemy jaki będzie czas kontaktu. Nie wiemy ile będzie rozmów konsultant banku z klientem ponieważ to zwykle klient decyduje jak długo i ile razy chce rozmawiać.
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.
df.head()
Musimy z pierwotnej bazy wykasować kilka kolumn:
Usuwam kolumny: ‘day_of_week’,’month’,’previous’,’campaign’,’duration’, ‘contact’, ‘y’
df.columns
df2 = df[['age', 'job', 'marital', 'education','default', 'housing', 'loan', 'poutcome', 'emp_var_rate','cons_price_idx', 'cons_conf_idx', 'euribor3m', 'nr_employed','y']]
Podobny zabieg trzeba wykonać dla zbioru ‘kierownika marketingu’, listy nowych 150 klientów oznaczonej jako df3, wycinamy te same, nieznane w przyszłości zmienne egzogeniczne. Tym razem jednak musimy też wyciąć zmienną wynikową y ponieważ nie wiemy, czy kredyt zostanie sprzedany.
df3 = df3[['age', 'job', 'marital', 'education','default', 'housing', 'loan', 'poutcome', 'emp_var_rate','cons_price_idx', 'cons_conf_idx', 'euribor3m', 'nr_employed']]
df2.head(5)
Tworzenie Dummy Variables
Wybieram kolumny tekstowe, dyskretne, do głębszej analizy.
Wyświetlamy kolumny zmiennnych dyskretnych
df2.describe(include=["object"]).columns
list = ['job', 'marital', 'education', 'default', 'housing', 'loan','poutcome']
Transforumjemy na dane dummy variables
df2[list] = df2[list].apply(LabelEncoder().fit_transform)
df2[list].head()
Dzielimy nowy zbiór df2 na zmienne opisujące i zmienną wynikową.
y = df2['y']
X = df2.drop('y', axis=1)
Dzielimy zbiór df2 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 nowego zbioru df2 bo zmienna wynikowa nie jest zbilansowana. Oversampling robimy na zmiennych treningowych.
df2.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 df2 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 df2 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)
Logistic Regression na zbiorze df2
import numpy as np
from sklearn import model_selection
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
Parameteres = {'C': np.power(10.0, np.arange(-3, 3))}
LR = LogisticRegression(warm_start = True)
LR_Grid = GridSearchCV(LR, param_grid = Parameteres, scoring = 'roc_auc', n_jobs = 5, cv=2)
LR_Grid.fit(Xtrain_OVS, ytrain_OVS)
Podstawienie do wzoru
ypred_OVS = LR_Grid.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, LR_Grid.predict(Xtrain_OVS)), decimals=4))
print("Precision Training data: ", np.round(precision_score(ytrain_OVS, LR_Grid.predict(Xtrain_OVS)), decimals=4))
print("----------------------------------------------------------------------")
print("Recall Test data: ", np.round(recall_score(ytest, LR_Grid.predict(Xtest)), decimals=4))
print("Precision Test data: ", np.round(precision_score(ytest, LR_Grid.predict(Xtest)), decimals=4))
print("----------------------------------------------------------------------")
print("Confusion Matrix Test data")
print(confusion_matrix(ytest, LR_Grid.predict(Xtest)))
print("----------------------------------------------------------------------")
print(classification_report(ytest, LR_Grid.predict(Xtest)))
y_pred_proba = LR_Grid.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 = %0.2f)' % 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()
Model wyszedł raczej słaby – teraz nie będziemy polepszać modelu, lecz skoncentrujemy się na tym jak zastosować go w praktyce. Mamy zbiór 150 nowych klientów w zbiorze df3. Kierownik departamentu Marketingu Bankowego, powinien wiedzieć, na których klientach powinien skoncentrować swoje wysiłki. Którzy klienci mogą wziąć kredyty a którzy raczej go nie wezmą. Zlikwidowaliśmy zmienne, które można otrzymać po przeprowadzonej akcji takie jak czas trwania rozmów z klientem oraz ilość kontaktów. Stworzyliśmy więc nowy model nie zawierający nieznanych w przyszłości parametrów. Model jest słabszy od modelu z pełnymi danymi lecz wciąż jest on względnie dobry.
Podstawiamy dane do modelu
df3.head()
df3.shape
Zróbmy kopie df3 aby zrobić na niej Dummy Variables
df3dummy = df3.copy()
df3dummy.head()
Transforumjemy dane tekstowe na dane dummy variables
Dummy Variables
Mamy zwykły zbiór danych kierownika marketingu, musimy go przerobić na Dummy Variables aby logistic Regression mógł dokonać predykcji.
Wyświetlamy kolumny zmiennnych dyskretnych
df3dummy.describe(include=["object"]).columns
list = ['job', 'marital', 'education', 'default', 'housing', 'loan', 'poutcome']
df3dummy[list] = df3dummy[list].apply(LabelEncoder().fit_transform)
df3dummy[list].head()
df3dummy.head(4)
Podstawienie do wzoru
ypred_OVS3 = LR_Grid.predict(df3dummy)
ypred_OVS3.shape
df3['Wynik'] = ypred_OVS3
Tworzenie listy dla kierownika marketingu
print('Lista kierownika marketingu bankowego')
df3[df3['Wynik']==1]
Statystyka
df3['Wynik'].value_counts(normalize=True)
df3.pivot_table(index = 'job', columns='Wynik', values='age', aggfunc='count', margins=True, margins_name='RAZEM')
df3.pivot_table(index = ['marital'], columns='Wynik', values='age', aggfunc='count', margins=True, margins_name='RAZEM')
df3.head(6)
Artificial Intelligence w Marketingu Bankowym – Logistic regression model part 1