Модель кредитного скоринга — это математическая модель, используемая для оценки вероятности дефолта, то есть вероятности того, что клиенты могут инициировать кредитное событие (например, банкротство, невыполнение обязательств, неуплату и события перекрестного дефолта).

Для создания модели кредитного скоринга набор данных можно скачать отсюда:



Исходный набор данных 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]]