В этом проекте мы построим модель, которая может прогнозировать кредитный риск, используя набор данных, предоставленный компанией, состоящий из данных о полученных и отклоненных кредитах.
Обзор рабочего процесса проекта включает в себя:
1. Подготовка данных
2. Очистка данных
3. Исследовательский анализ данных
4. Разработка функций
5 .Моделирование
6. Оценка
хорошо для начала нам нужны необходимые библиотеки в этом проекте.

Импорт необходимых библиотек

import numpy as np
import pandas as pd
import tensorflow as tf
import missingno as msno
import os
import seaborn as sns
import pickle
from matplotlib import pyplot as plt
from collections import Counter
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split, cross_val_score, KFold
from sklearn.metrics import classification_report, confusion_matrix
from imblearn.over_sampling import RandomOverSampler
#the type of machine learning to use
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier

1. Подготовка данных

Сначала нам нужно загрузить данные во фрейм данных, который будет использоваться для прогнозирования кредитного риска. затем просмотрите содержимое данных, чтобы получить обзор данных до выполнения предварительной обработки данных.

# Check is Link to Drive is OK
google = !if [ -d 'GDrive/' ]; then echo "1" ; else echo "0"; fi
if (google[0] is '0' ):
from google.colab import drive
drive.mount('/content/GDrive/')
!if [ -d 'GDrive/' ]; then echo "Connection to Google drive successful" ; else echo "Error to connect to Google drive"; fi

# loading the dataset to pandas DataFrame
loan_dataset = pd.read_csv('/content/GDrive/MyDrive/Loandata/loan_data_2007_2014.csv')
loan_dataset

2. Очистка данных

После того, как данные будут загружены в фрейм данных, мы выполним очистку данных, чтобы удалить отсутствующие значения или столбцы, которые не важны в этом проекте.

# number of rows and columns
loan_dataset.shape

# number of missing values in each column
loan_dataset.isnull().sum()

#dropping irrelevant columns
columns_to_ = ['id', 'member_id', 'sub_grade', 'emp_title', 'url', 'desc', 'title', 'zip_code', 'next_pymnt_d',
'recoveries', 'collection_recovery_fee', 'total_rec_prncp', 'total_rec_late_fee', 'desc', 'mths_since_last_record',
'mths_since_last_major_derog', 'annual_inc_joint', 'dti_joint', 'verification_status_joint', 'open_acc_6m', 'open_il_6m',
'open_il_12m', 'open_il_24m', 'mths_since_rcnt_il', 'total_bal_il', 'il_util', 'open_rv_12m', 'open_rv_24m',
'max_bal_bc', 'all_util', 'inq_fi', 'total_cu_tl', 'inq_last_12m','policy_code',]
loan_dataset.drop(columns=columns_to_, inplace=True, axis=1)
# drop na values
loan_dataset.dropna(inplace=True)
loan_dataset.info()

duplicate_rows_data = loan_dataset[loan_dataset.duplicated()]
print("number of duplicate rows: ", duplicate_rows_data.shape)
loan_dataset = loan_dataset.drop_duplicates()

3. Исследовательский анализ данных

Исследовательский анализ данных (EDA) – это подход к анализу данных с использованием визуальных методов. Он используется для выявления тенденций, закономерностей или проверки предположений с помощью статистических сводок и графических представлений.

# statistical measures
loan_dataset.describe()

plt.figure(figsize=(15,10))
sns.heatmap(loan_dataset.corr(),annot=True)

columns = ['loan_amnt', 'funded_amnt','funded_amnt_inv','installment','total_pymnt_inv','out_prncp_inv']
loan_dataset.drop(columns=columns,axis=1,inplace=True)
plt.figure(figsize=(15,10))
sns.heatmap(loan_dataset.corr(),annot=True)

4. Особенности проектирования

Далее нам нужно нормализовать и стандартизировать данные, выполнив проектирование признаков.

loan_dataset['term']

def Term_Numeric(data, col):
data[col] = pd.to_numeric(data[col].str.replace(' months', ''))
Term_Numeric(loan_dataset, 'term')
def Emp_Length_Convert(data, col):
data[col] = data[col].str.replace('\+ years', '')
data[col] = data[col].str.replace('< 1 year', str(0))
data[col] = data[col].str.replace(' years', '')
data[col] = data[col].str.replace(' year', '')
data[col] = pd.to_numeric(data[col])
data[col].fillna(value = 0, inplace = True)
def Date_Columns(data, col):
today_date = pd.to_datetime('2020-08-01')
data[col] = pd.to_datetime(data[col], format = "%b-%y")
data['mths_since_' + col] = round(pd.to_numeric((today_date - data[col]) / np.timedelta64(1, 'M')))
data['mths_since_' + col] = data['mths_since_' + col].apply(lambda x: data['mths_since_' + col].max() if x < 0 else x)
data.drop(columns = [col], inplace = True)
Emp_Length_Convert(loan_dataset,'emp_length')
Date_Columns(loan_dataset,'last_credit_pull_d')

проверка данных после разработки некоторых функций

loan_dataset.head()

Далее мы определим цель/метку. При моделировании кредитного риска проекта основная цель состоит в том, чтобы спрогнозировать способность отдельных лиц производить платежи по займам/кредитам. Следовательно, используемая целевая переменная должна отражать способности человека в этом отношении.

В этом наборе данных переменная кредит_статус — это переменная, которую можно использовать в качестве целевой переменной, поскольку она отражает эффективность каждого человека в осуществлении платежей по ссудам/кредитам на данный момент.

loan_status = list(loan_dataset['loan_status'].unique())
print(f'Number of loan_status: {len(loan_status)}')
print(f'loan_status: {loan_status}')

# creating a new column based on the loan_status
loan_dataset['good_bad'] = np.where(loan_dataset.loc[:, 'loan_status'].isin(['Charged Off', 'Default', 'Late (31-120 days)',
'Does not meet the credit policy. Status:Charged Off']), 0, 1)
# Drop the original 'loan_status' column
loan_dataset.drop(columns = ['loan_status'], inplace = True)
loan_dataset.head()

мы определили цель/метку модели кредитного риска, которую мы создадим. но перед моделированием и обучением данных нам нужно проверить, сбалансировано ли распределение данных по меткам, чтобы создаваемая нами модель была оптимальной.

# loc locates all data by column or conditional statement
good = loan_dataset.loc[loan_dataset['good_bad'] == 1] # find all rows that are fraudulent
bad = loan_dataset.loc[loan_dataset['good_bad'] == 0] # final all rows that aren't fraudulent
print('Good ', len(good), ' transactions or ', round(loan_dataset['good_bad'].value_counts()[1]/len(loan_dataset)*100, 2), '% of the dataset')
print('Bad ', len(bad), ' transactions or ', round(loan_dataset['good_bad'].value_counts()[0]/len(loan_dataset)*100, 2), '% of the dataset')

Равное распределение и корреляция:

colors = ['Blue', 'Orange']
print('Distribution of the Classes in the subsample dataset')
print(loan_dataset['good_bad'].value_counts()/len(loan_dataset)) 
# percentage for each class
sns.countplot('good_bad', data=loan_dataset, palette=colors)
plt.title('Equally Distributed Classes', fontsize=14)
plt.show()

Кодирование категориальных переменных

categorical_column = loan_dataset.select_dtypes('object').columns
for i in range(len(categorical_column)):
le = LabelEncoder()
loan_dataset[categorical_column[i]] = le.fit_transform(loan_dataset[categorical_column[i]])
loan_dataset.head()

Случайная передискретизация

Давайте сбалансируем наш набор данных, используя случайную передискретизацию!

Шаги:

  1. Определите, насколько несбалансирован наш класс. Для этого хорошо подходит value_count(), примененный к Class. В нашем случае это 163862.
  2. Приведите количество плохих транзакций к количеству хороших транзакций.
  3. Перетасуйте данные*, чтобы проверить, может ли наша модель поддерживать определенную точность при каждом запуске скрипта.
loan_dataset

fitur = loan_dataset.loc[:,:'mths_since_last_credit_pull_d']
# Features are our matrix of tf-idf values
X = fitur
y = loan_dataset.good_bad
# How many are bad?
y.value_counts()

rus = RandomOverSampler(random_state=42)
X_res, y_res = rus.fit_resample(X, y)
print('Resampled dataset shape {}'.format(Counter(y_res)))

loan_data = X_res
loan_data['good_bad'] = y_res
colors = ['Blue', 'Orange']
print('Distribution of the Classes in the subsample dataset')
print(loan_data['good_bad'].value_counts()/len(loan_data)) # percentage for each class
sns.countplot('good_bad', data=loan_data, palette=colors)
plt.title('Equally Distributed Classes', fontsize=14)
plt.show()

5. Моделирование

Наконец данные готовы для обучения на модели. мы делаем разбиение данных для обучения и тестирования.

X = loan_data.drop(['good_bad'],axis=1)
y = loan_data['good_bad']
# Splitting data
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.20,random_state=42)
import warnings
warnings.filterwarnings('ignore')

мы будем обучать данные 5 различным типам моделей, чтобы сравнить, какую модель лучше всего использовать в этом проекте прогнозирования кредитного риска.

# compare models
models = []
models.append(('LR', LogisticRegression()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('DT', DecisionTreeClassifier()))
models.append(('NB', GaussianNB()))
models.append(('RF', RandomForestClassifier()))
results = []
names = []
for name, model in models:
kfold = KFold(n_splits=10)
cv_results = cross_val_score(model, X_train, y_train, cv=kfold)
results.append(cv_results)
names.append(name)
msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
print(msg)

мы получаем результаты обучения с использованием модели классификатора случайного леса с лучшими результатами, чем другие модели. поэтому мы выберем модель случайного леса, чтобы доработать модель в этом проекте.

rfc = RandomForestClassifier()
rfc.fit(X_train,y_train)

arr_feature_importances = rfc.feature_importances_
arr_feature_names = X_train.columns.values
df_feature_importance = pd.DataFrame(index=range(len(arr_feature_importances)), columns=['feature', 'importance'])
df_feature_importance['feature'] = arr_feature_names
df_feature_importance['importance'] = arr_feature_importances
df_all_features = df_feature_importance.sort_values(by='importance', ascending=False)
df_all_features

6. Оценка

Проверка

Для измерения эффективности модели в мире кредитного риска обычно используются две метрики: AUC и KS.

y_pred_proba = rfc.predict_proba(X_test)[:][:,1]
df_actual_predicted = pd.concat([pd.DataFrame(np.array(y_test), columns=['y_actual']), pd.DataFrame(y_pred_proba, columns=['y_pred_proba'])], axis=1)
df_actual_predicted.index = y_test.index

ППК

from sklearn.metrics import roc_curve, roc_auc_score
fpr, tpr, tr = roc_curve(df_actual_predicted['y_actual'], df_actual_predicted['y_pred_proba'])
auc = roc_auc_score(df_actual_predicted['y_actual'], df_actual_predicted['y_pred_proba'])
plt.plot(fpr, tpr, label='AUC = %0.4f' %auc)
plt.plot(fpr, fpr, linestyle = '--', color='k')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend()

KS

df_actual_predicted = df_actual_predicted.sort_values('y_pred_proba')
df_actual_predicted = df_actual_predicted.reset_index()
df_actual_predicted['Cumulative N Population'] = df_actual_predicted.index + 1
df_actual_predicted['Cumulative N Bad'] = df_actual_predicted['y_actual'].cumsum()
df_actual_predicted['Cumulative N Good'] = df_actual_predicted['Cumulative N Population'] - df_actual_predicted['Cumulative N Bad']
df_actual_predicted['Cumulative Perc Population'] = df_actual_predicted['Cumulative N Population'] / df_actual_predicted.shape[0]
df_actual_predicted['Cumulative Perc Bad'] = df_actual_predicted['Cumulative N Bad'] / df_actual_predicted['y_actual'].sum()
df_actual_predicted['Cumulative Perc Good'] = df_actual_predicted['Cumulative N Good'] / (df_actual_predicted.shape[0] - df_actual_predicted['y_actual'].sum())
df_actual_predicted.head()

KS = max(df_actual_predicted['Cumulative Perc Good'] - df_actual_predicted['Cumulative Perc Bad'])
plt.plot(df_actual_predicted['y_pred_proba'], df_actual_predicted['Cumulative Perc Bad'], color='r')
plt.plot(df_actual_predicted['y_pred_proba'], df_actual_predicted['Cumulative Perc Good'], color='b')
plt.xlabel('Estimated Probability for Being Bad')
plt.ylabel('Cumulative %')
plt.title('Kolmogorov-Smirnov:  %0.4f' %KS)

Построенная модель привела к производительности AUC = 1.00 и KS = 0.99. В мире моделирования кредитного риска, как правило, AUC выше 0,7 и KS выше 0,3 считаются хорошими показателями.

Это объяснение рабочего процесса проекта прогнозирования кредитного риска. пожалуйста, посетите мой профиль для других примеров проектов машинного обучения.