В этом проекте мы построим модель, которая может прогнозировать кредитный риск, используя набор данных, предоставленный компанией, состоящий из данных о полученных и отклоненных кредитах.
Обзор рабочего процесса проекта включает в себя:
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()
Случайная передискретизация
Давайте сбалансируем наш набор данных, используя случайную передискретизацию!
Шаги:
- Определите, насколько несбалансирован наш класс. Для этого хорошо подходит value_count(), примененный к Class. В нашем случае это 163862.
- Приведите количество плохих транзакций к количеству хороших транзакций.
- Перетасуйте данные*, чтобы проверить, может ли наша модель поддерживать определенную точность при каждом запуске скрипта.
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 считаются хорошими показателями.
Это объяснение рабочего процесса проекта прогнозирования кредитного риска. пожалуйста, посетите мой профиль для других примеров проектов машинного обучения.