Procedura oversampling dla Logistic Regression
Przy budowie modelów klasyfikacji 0-1 występuje problem niezbilansowanych zbiorów.
In [1]:
import numpy as np
import pandas as pd
#import xgboost as xgb
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 import cross_validation, metrics
from sklearn.preprocessing import Normalizer
#from sklearn.cross_validation import cross_val_score
from sklearn.preprocessing import Imputer
import matplotlib.pyplot as plote
plt.style.use('ggplot')
In [2]:
df = pd.read_csv('c:/1/bank.csv')
df.head()
Out[2]:
MODEL BEZ ZBILANSOWANIA ZBIORÓW
Skalowanie standardowe tylko dla wartości dyskretnychWybieram kolumny tekstowe, dyskretne, do głębszej analizy. Lepsze było to wybieranie dyskretne i ciągłe.
In [3]:
encoding_list = ['job', 'marital', 'education', 'default', 'housing', 'loan',
'contact', 'month', 'day_of_week','poutcome']
In [4]:
df[encoding_list] = df[encoding_list].apply(LabelEncoder().fit_transform)
In [5]:
df[encoding_list].head()
Out[5]:
Tworzymy zestaw treningowy i zestaw testowy, budujemy model
In [6]:
y = df['y']
X = df.drop('y', axis=1)
Złoty podział zioru na testowy i treningowy
In [7]:
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)
Wielkości zbiorów:
In [8]:
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)
Dane dyskretne są zdygitalizowane.
In [9]:
Xtrain.head(4)
Out[9]:
Logistic Regression
In [10]:
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, ytrain)
Out[10]:
Blok oceny jakości modelu Logistic Regression
Podstawienie do wzoru
In [11]:
# Podstawienie do wzoru
ypred = LR_Grid.predict(Xtest)
from sklearn.metrics import classification_report, confusion_matrix
from sklearn import metrics
co_matrix = metrics.confusion_matrix(ytest, ypred)
co_matrix
Out[11]:
In [12]:
print(classification_report(ytest, ypred))
In [13]:
print("Accuracy: ",np.round(metrics.accuracy_score(ytest, ypred), decimals=2))
print("Precision: ",np.round(metrics.precision_score(ytest, ypred), decimals=2))
print("Recall: ",np.round(metrics.recall_score(ytest, ypred), decimals=2))
print("F1 score: ",np.round(metrics.f1_score(ytest, ypred), decimals=2))
Analiza poziomu zbilansowania zmiennej wynikowej
In [14]:
df.y.value_counts(dropna = False, normalize=True)
Out[14]:
In [15]:
print("ytrain = 0: ", sum(ytrain == 0))
print("ytrain = 1: ", sum(ytrain == 1))
In [16]:
Proporcja = sum(ytrain == 0) / sum(ytrain == 1)
Proporcja = np.round(Proporcja, decimals=0)
Proporcja = Proporcja.astype(int)
Proporcja
Out[16]:
Na jedną daną sybskrypcje przypada 8 nieprzedłużonych subskrypcji. Powiększamy liczbę próbek niezależnych.
In [17]:
ytrain_pos_OVS = pd.concat([ytrain[ytrain==1]] * Proporcja, axis = 0)
ytrain_pos_OVS.count()
Out[17]:
Ilość zmiennych wynikowych: (1) zwiększyła się do liczby 24872
Mamy już wektor zmiennych wynikowych y, teraz trzeba zwiększyć liczbę zmiennych niezależnych
Powiększamy liczbę próbek zmiennych niezależnych X
In [18]:
Xtrain_pos_OVS = pd.concat([Xtrain.loc[ytrain==1, :]] * Proporcja, axis = 0)
In [19]:
Xtrain_pos_OVS.age.count()
Out[19]:
Powiękzyliśmy ilość zmiennych gdzie wynik przedłużenia subskrypcji jest równy 1.
Teraz mamy tą samą liczbę wierszy zmiennych wynikowych i zmiennych niezależnych.
Teraz wprowadzamy nowe, dodatkowe zmienne 1 do zbioru treningowego.
In [20]:
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)
Sprawdzamy ilość wierszy w zbiorach przed i po oversampling.
In [21]:
print("ilość elementów w zbiorze Xtrain: ", Xtrain.age.count())
print("ilość elementów w zbiorze Xtrain_OVS: ", Xtrain_OVS.age.count())
print("ilość elementów w zbiorze ytrain: ", ytrain.count())
print("ilość elementów w zbiorze ytrain_OVS: ", ytrain_OVS.count())
Teraz podstawiamy nowy zbiór testowy oversampling do siatki grid według tej same formuły, którą użyliśmy wcześniej.
In [22]:
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)
Out[22]:
Podstawienie do wzoru
In [23]:
ypred_OVS = LR_Grid.predict(Xtest)
In [24]:
from sklearn.metrics import classification_report, confusion_matrix
from sklearn import metrics
co_matrix = metrics.confusion_matrix(ytest, ypred_OVS)
co_matrix
Out[24]:
In [25]:
print(classification_report(ytest, ypred_OVS))
In [26]:
print("Accuracy: ",np.round(metrics.accuracy_score(ytest, ypred_OVS), decimals=2))
print("Precision: ",np.round(metrics.precision_score(ytest, ypred_OVS), decimals=2))
print("Recall: ",np.round(metrics.recall_score(ytest, ypred_OVS), decimals=2))
print("F1 score: ",np.round(metrics.f1_score(ytest, ypred_OVS), decimals=2))
Wynik modelu Logistic Regression przed Oversampling
- Accuracy: 0.9
- Precision: 0.66
- Recall: 0.32
- F1 score: 0.43
Wynik kodelu po Oversampling
- Accuracy: 0.84
- Precision: 0.4
- Recall: 0.87
- F1 score: 0.55
