Модель кредитного скоринга — это математическая модель, используемая для оценки вероятности дефолта, то есть вероятности того, что клиенты могут инициировать кредитное событие (например, банкротство, невыполнение обязательств, неуплату и события перекрестного дефолта).
Для создания модели кредитного скоринга набор данных можно скачать отсюда:
Исходный набор данных 1000 записей с 10 атрибутами.
В этом наборе данных каждая запись представляет человека, который берет кредит в банке.
Каждое лицо классифицируется как человек с хорошим или плохим кредитным риском в соответствии с набором атрибутов.
#Импорт библиотек и загрузка набора данных
import pandas as pd #Для работы с набором данных
import numpy as np #Math library
import seaborn as sns #Graph library, которая использует matplot в фоновом режиме
import matplotlib.pyplot as plt #для построения графика параметры в море
df_credit = pd.read_csv("german_credit_data.csv",index_col=0)
#Поиск уникальных значений
print(df_credit.nunique())
#Просмотр данных
print(df_credit.head())
Age 53 Sex 2 Job 4 Housing 3 Saving accounts 4 Checking account 3 Credit amount 921 Duration 33 Purpose 8 Risk 2 dtype: int64 Age Sex Job Housing Saving accounts Checking account Credit amount \ 0 67 male 2 own NaN little 1169 1 22 female 2 own little moderate 5951 2 49 male 1 own little NaN 2096 3 45 male 2 free little little 7882 4 53 male 2 free little little 4870 Duration Purpose Risk 0 6 radio/TV good 1 48 radio/TV bad 2 12 education good 3 42 furniture/equipment good 4 24 car bad
sns.countplot(df_credit['Риск'])
#Возрастное распределение
#Создание категориальной переменной для обработки с помощью переменной Age
#Давайте посмотрим на столбец "Сумма кредита"
interval = (18, 25, 35, 60, 120)
коты = ['Студент', 'Молодой', 'Взрослый', 'Старший']
df_credit["Возраст_кота"] = pd.cut(df_credit.Возраст, интервал, метки=кошки)
df_good = df_credit[df_credit["Риск"] == "хорошо"]
df_bad = df_credit[df_credit["Риск"] == "плохо"]
sns.boxplot(
df_credit['Age_cat'],df_credit['Сумма кредита'],hue=df_credit['Риск]
)
print("Значения описывают: ")
print(pd.crosstab(df_credit.Purpose, df_credit.Risk))
plt.figure(figsize = (14,12))
plt.subplot(221)
g = sns.countplot(x="Цель", data=df_credit,
палитра="hls", hue = "Риск")
g.set_xticklabels( g.get_xticklabels(),rotation=45)
g.set_xlabel("", размер шрифта=12)
g.set_ylabel("Количество", размер шрифта=12)
g.set_title(" Количество целей», размер шрифта = 20)
plt.subplot(222)
g1 = sns.violinplot(x="Цель", y="Возраст", data=df_credit,
палитра="hls", hue = "Риск",split= True)
g1.set_xticklabels(g1.get_xticklabels(),rotation=45)
g1.set_xlabel(“”, fontsize=12)
g1.set_ylabel(“Count”, fontsize=12 )
g1.set_title("Цели по возрасту", размер шрифта=20)
plt.subplot(212)
g2 = sns.boxplot(x="Цель", y="Сумма кредита", data=df_credit,
палитра="hls", hue = "Риск")< br /> g2.set_xlabel("Цели", fontsize=12)
g2.set_ylabel("Сумма кредита", fontsize=12)
g2.set_title("Распределение суммы кредита по целям", fontsize= 20)
plt.subplots_adjust (hspace = 0,6, верх = 0,8)
plt.show()
Values describe: Risk bad good Purpose business 34 63 car 106 231 domestic appliances 4 8 education 23 36 furniture/equipment 58 123 radio/TV 62 218 repairs 8 14 vacation/others 5 7
печать (pd.crosstab (df_credit.Sex, df_credit.Job))
Job 0 1 2 3 Sex female 12 64 197 37 male 10 136 433 111
plt.figure(figsize = (10,6))
g = sns.violinplot(x="Жилье", y="Работа", data=df_credit,
hue="Риск", палитра="hls", split=True)
g.set_xlabel( "Жилье", размер шрифта=12)
g.set_ylabel("Работа", размер шрифта=12)
g.set_title("Жилье x Работа — Расст", размер шрифта=20)
plt.show()
date_int = [«Цель», «Пол»]
cm = sns.light_palette («зеленый», as_cmap = True)
pd.crosstab(df_credit[date_int[0]], df_credit[date_int[1 ]]).style.background_gradient(cmap = cm)
#Просматриваем общее количество значений в каждой категориальной функции
print("Цель: ",df_credit.Purpose.unique())
print("Пол: ",df_credit.Sex.unique())
print("Жилье: ",df_credit.Housing.unique ())
print("Сберегательные счета: ",df_credit['Сберегательные счета'].unique())
print("Риск: ",df_credit['Риск'].unique())< br /> print("Расчетный счет: ",df_credit['Расчетный счет'].unique())
print("Aget_cat: ",df_credit['Age_cat'].unique())
Purpose : ['radio/TV' 'education' 'furniture/equipment' 'car' 'business' 'domestic appliances' 'repairs' 'vacation/others'] Sex : ['male' 'female'] Housing : ['own' 'free' 'rent'] Saving accounts : [nan 'little' 'quite rich' 'rich' 'moderate'] Risk : ['good' 'bad'] Checking account : ['little' 'moderate' nan 'rich'] Aget_cat : [Senior, Student, Adult, Young] Categories (4, object): [Student < Young < Adult < Senior]
#Давайте поработаем над этими значениями и создадим переменную #Dummies для значений
def one_hot_encoder(df, nan_as_category = False):
original_columns = list(df.columns)
categorical_columns = [столбец для столбца в df.columns, если df[col].dtype == 'object']< br /> df = pd.get_dummies(df, columns= categorical_columns, dummy_na= nan_as_category, drop_first=True)
new_columns = [c для c в df.columns, если c нет в original_columns]
вернуть df, новые_колонки
#Преобразование данных в фиктивные переменные
df_credit['Сберегательные счета'] = df_credit['Сберегательные счета'].fillna('no_inf')
df_credit['Расчетный счет'] = df_credit['Расчетный счет '].fillna('no_inf')
#Цель для чайников Переменная
df_credit = df_credit.merge(pd.get_dummies(df_credit.Purpose, drop_first=True, prefix='Purpose'), left_index=True, right_index=True)
#Функция пола в манекены
df_credit = df_credit.merge(pd.get_dummies(df_credit.Sex, drop_first=True, prefix='Sex'), left_index=True, right_index=True)
# Жилье получают манекены
df_credit = df_credit.merge(pd.get_dummies(df_credit.Housing, drop_first=True, prefix='Housing'), left_index=True, right_index=True)
# Жилье получает сберегательные счета
df_credit = df_credit. merge(pd.get_dummies(df_credit["Сберегательные счета"], drop_first=True, prefix='Savings'), left_index=True, right_index=True)
# Жилье получает риск
df_credit = df_credit.merge (pd.get_dummies(df_credit.Risk, prefix='Risk'), left_index=True, right_index=True)
# Жилье получить Текущий счет
df_credit = df_credit.merge(pd.get_dummies(df_credit[“ Проверка учетной записи», drop_first = Истина, префикс = «Проверка»), left_index = Истина, right_ind ex=True)
# Возраст получения жилья категориальный
df_credit = df_credit.merge(pd.get_dummies(df_credit["Age_cat"], drop_first=True, prefix='Age_cat'), left_index=True, right_index = Верно)
#Удаление старых функций
del df_credit["Сберегательные счета"]
del df_credit["Текущий счет"]
del df_credit["Цель"]
del df_credit["Секс"]
del df_credit[“ Жилье»]
del df_credit[«Age_cat»]
del df_credit[«Risk»]
del df_credit['Risk_good']
#Ищем корреляцию данных
plt.figure(figsize=(14,12))
sns.heatmap(df_credit.astype(float).corr(),linewidths=0,1,vmax=1,0,
Square=True, linecolor=' белый', annot=True)
plt.show()
#Импорт библиотек машинного обучения
from sklearn.model_selection import train_test_split, KFold, cross_val_score # для разделения данных
from sklearn.metrics import аккуратность_оценка, путаница_матрица, классификация_отчет, fbeta_score #Для оценки нашей модели
из sklearn.model_selection импортировать GridSearchCV
# Модели алгоритмов для сравнения
из sklearn.ensemble import RandomForestClassifier
из sklearn.linear_model import LogisticRegression
из sklearn.tree import DecisionTreeClassifier
из sklearn.neighbors import KNeighborsClassifier
из sklearn.ensemble импортировать RandomForestClassifier
из sklearn.discriminant_analysis импортировать LinearDiscriminantAnalysis
из sklearn.naive_bayes импортировать GaussianNB
из sklearn.svm импортировать SVC
из xgboost импортировать XGBClassifier
df_credit['Сумма кредита'] = np.log(df_credit['Сумма кредита'])
#Создание переменных X и y
X = df_credit.drop('Плохой_риск', 1).values
y = df_credit["Плохой_риск"].values
# Разделение X и y на обучающую и тестовую версии
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0,25, random_state=42)
# для подачи случайного состояния
seed = 7
# подготовить модели
models = []
models.append(('LR', LogisticRegression()))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('CART', DecisionTreeClassifier()))
models.append(('NB', GaussianNB()) )
models.append(('RF', RandomForestClassifier()))
models.append(('SVM', SVC(gamma='auto')))
models.append( ('XGB', Классификатор XGB()))
# оцениваем каждую модель по очереди
results = []
name = []
scoring = ‘recall’
для имени, модели в моделях:
kfold = KFold(n_splits=10, random_state=seed)
cv_results = cross_val_score(model, X_train, y_train, cv=kfold, scoring=scoring)
results .append(cv_results)
names.append(name)
msg = «%s: %f (%f)» % (имя, cv_results.mean(), cv_results.std())
print(msg)
# сравнение алгоритмов для диаграмм
fig = plt.figure(figsize=(11,6))
fig.suptitle('Сравнение алгоритмов')< br /> ax = fig.add_subplot(111)
plt.boxplot(результаты)
ax.set_xticklabels(имена)
plt.show()
LR: 0.387574 (0.077970) LDA: 0.428815 (0.093162) KNN: 0.263130 (0.035560) CART: 0.519622 (0.083569) NB: 0.596300 (0.081365) RF: 0.363725 (0.067627) SVM: 0.182230 (0.088462) XGB: 0.422917 (0.110550)
#Установка гиперпараметров
param_grid = {"max_depth": [3,5, 7, 10,Нет],
"n_estimators":[3,5,10, 25,50,150],
«max_features»: [4,7,15,20]}
#Создание классификатора
model = RandomForestClassifier(random_state=2)
grid_search = GridSearchCV (модель, param_grid = param_grid, cv = 5, оценка = «отзыв», verbose = 4)
grid_search.fit (X_train, y_train)
print(grid_search.best_score_)
print(grid_search.best_params_)
0.49111239935587764 {'max_depth': None, 'max_features': 20, 'n_estimators': 5}
rf = RandomForestClassifier (max_depth = None, max_features = 10, n_estimators = 15, random_state = 2)
#обучение с лучшими параметрами
rf.fit(X_train, y_train)
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini', max_depth=None, max_features=10, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=15, n_jobs=None, oob_score=False, random_state=2, verbose=0, warm_start=False)
#Тестирование модели
#Прогнозирование с использованием нашей модели
y_pred = rf.predict(X_test)
# Проверка результатов проверки
print(accuracy_score(y_test,y_pred))
print("\n")
print(confusion_matrix(y_test, y_pred))
print("\ n")
print(fbeta_score(y_test, y_pred, beta=2))
0.736 [[158 20] [ 46 26]] 0.3892215568862275
из sklearn.utils import resample
из sklearn.metrics import roc_curve
# Criando или classificador logreg
GNB = GaussianNB()
# Подбор данных поезда
model = GNB.fit(X_train, y_train)
# Печать результатов обучения
print("Данные результатов обучения: ")
print(model.score(X_train, y_train))
Training score data: 0.7053333333333334
y_pred = модель.предсказание(X_тест)
print(accuracy_score(y_test,y_pred))
print("\n")
print(confusion_matrix(y_test, y_pred))
print("\n")
print( classification_report (y_test, y_pred))
0.648 [[124 54] [ 34 38]] precision recall f1-score support 0 0.78 0.70 0.74 178 1 0.41 0.53 0.46 72 accuracy 0.65 250 macro avg 0.60 0.61 0.60 250 weighted avg 0.68 0.65 0.66 250
#Прогнозирование вероятности
y_pred_prob = model.predict_proba(X_test)[:,1]
# Генерация значений кривой ROC: fpr, tpr, thresholds
fpr, tpr, thresholds = roc_curve(y_test, y_pred_prob)
# Построить кривую ROC
plt.plot([0, 1], [0, 1], 'k — ')
plt.plot(fpr, tpr)
plt.xlabel(' Ложноположительный показатель')
plt.ylabel('Истинно положительный показатель')
plt.title('Кривая ROC')
plt.show()
из sklearn.model_selection импортировать KFold
из sklearn.model_selection импортировать cross_val_score
из sklearn.pipeline импортировать Pipeline
из sklearn.pipeline импортировать FeatureUnion
из sklearn.linear_model импортировать LogisticRegression
из sklearn.decomposition импортировать PCA
из sklearn.feature_selection импортировать SelectKBest
features = []
features.append(('pca', PCA(n_components=2)))
features.append(('select_best', SelectKBest(k=6)))
feature_union = FeatureUnion(features)
# создать конвейер
estimators = []
estimators.append(('feature_union', feature_union))
estimators.append(('logistic', GaussianNB()))
model = Pipeline(оценщики)
# оценка конвейера
seed = 7
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(model, X_train, y_train, cv=kfold)
print(results.mean())
0.7066666666666668
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(accuracy_score(y_test,y_pred))
print("\n")
print(confusion_matrix(y_test, y_pred))
print("\n")
print( fbeta_score (y_test, y_pred, бета = 2))
0.72 [[149 29] [ 41 31]] 0.44540229885057464
#Настройка гиперпараметров
param_test1 = {
'max_depth':[3,5,6,10],
'min_child_weight':[3,5,10],
'gamma':[0.0, 0.1, 0.2, 0.3, 0.4],
# 'reg_alpha':[1e-5, 1e-2, 0.1, 1, 10],
'subsample':[ i/100.0 для i в диапазоне (75,90,5)],
'colsample_bytree':[i/100.0 для i в диапазоне (75,90,5)]
}
#Создание классификатора
model_xg = XGBClassifier(random_state=2)
grid_search = GridSearchCV (model_xg, param_grid = param_test1, cv = 5, оценка = «отзыв»)
grid_search.fit (X_train, y_train)
GridSearchCV(cv=5, error_score='raise-deprecating', estimator=XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1, gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=3, min_child_weight=1, missing=None, n_estimators=100, n_jobs=1, nthread=None, objective='binary:logistic', random_state=2, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None, silent=None, subsample=1, verbosity=1), iid='warn', n_jobs=None, param_grid={'colsample_bytree': [0.75, 0.8, 0.85], 'gamma': [0.0, 0.1, 0.2, 0.3, 0.4], 'max_depth': [3, 5, 6, 10], 'min_child_weight': [3, 5, 10], 'subsample': [0.75, 0.8, 0.85]}, pre_dispatch='2*n_jobs', refit=True, return_train_score=False, scoring='recall', verbose=0)
grid_search.best_score_
grid_search.best_params_
{'colsample_bytree': 0.85, 'gamma': 0.2, 'max_depth': 6, 'min_child_weight': 3, 'subsample': 0.8}
y_pred = grid_search.predict(X_test)
# Проверка полученного результата
print(accuracy_score(y_test,y_pred))
print("\n")
print(confusion_matrix(y_test, y_pred))
0.748 [[158 20] [ 43 29]]