Как разработать модель классификации одобрения потребительского кредита и легко создавать итерации с помощью PyCaret
Контекст:
Dummy Bank заметил, что у него растет объем безнадежных кредитов, и хочет отреагировать на него, построив модель машинного обучения на основе своих исторических данных о «хороших» и «плохих» кредитах. Кроме того, компания просит найти факторы, обуславливающие эти безнадежные кредиты, чтобы бизнес мог предпринять необходимые действия в будущем.
Набор данных:
Доступ к набору данных Dummy Bank можно получить по этой ссылке Kaggle: https://www.kaggle.com/datasets/mrferozi/loan-data-for-dummy-bank?select=loan_final313.csv
Цель:
- Разработать модель классификации с приоритетом отзыва, которая представляет собой показатель, ориентированный на сокращение ложноотрицательных результатов (избегая случая прогнозирования хорошего кредита, который оказывается плохим кредитом).
- Чтобы понять ключевые факторы плохих кредитов
Импорт библиотек
import pandas as pd import numpy as np import openpyxl from sklearn.preprocessing import LabelEncoder, MinMaxScaler, StandardScaler, OneHotEncoder, OrdinalEncoder from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split, cross_val_score from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, f1_score, precision_score, recall_score import sweetviz as sv import matplotlib.pyplot as plt import seaborn as sns import shap
Загрузка данных
path = "C:/Users/Laurence PC/Documents/Data Science/Machine Learning/Classification/Dummy Bank/loan_final313.csv" df = pd.read_csv(path)
Первоначальная EDA + начальная предварительная обработка данных
Данные должны пройти итерации предварительной обработки и EDA. Таким образом, должно быть реализовано следующее:
- Получение списка столбцов и исходной формы фрейма данных
- Описание статистической сводки числовых столбцов
- Проверка значений NA и NAN
- Удаление ПУСТЫХ строк, ИЗБЫТОЧНЫХ и НЕИСПОЛЬЗУЕМЫХ столбцов
- Изменение типов данных
- Обработка столбцов с порядковыми значениями
df.columns
df.shape
#REMOVING REDUNDANT, BLANK Rows, and UNUSABLE Columns #unusable columns df = df.drop(columns=['id','issue_d','final_d']) #redundant columns df = df.drop(columns=['home_ownership_cat', 'income_cat', 'income_category', 'term', 'application_type', 'application_type_cat', 'purpose_cat', 'interest_payments', 'interest_payment_cat', 'loan_condition', 'grade', 'grade_cat', 'total_pymnt', 'total_rec_prncp']) #only bad loans have recoveries, not ideal feature as it highly #correlated to the y variable df = df.drop(columns=['recoveries']) #redundant to terms and total principal df = df.drop(columns=['installment']) df.info()
Автовиз
sweet_report = sv.analyze(df) #Saving results to HTML file sweet_report.show_html('Dummy_Bank_sweet_report.html')
#COPYING ORIGINAL VALUES BEFORE TRANSFORMATIONS df_orig = df.copy() df_orig.reset_index(drop=True, inplace=True) df_orig
Преобразование данных
После того, как данные завершили этап предварительной обработки и EDA, будет выполнено следующее преобразование данных:
- Кодирование категориальных переменных
- Масштабирование функций
#Segregating the Categorical Variables categorical = df.select_dtypes(include=['object']) categorical_cols = list(categorical.columns) #Checking unique entries per categorical column for col in categorical: print(col) print(df[col].unique(),end="\n")
# Encoding Categorical Variables df = pd.get_dummies(df, columns=categorical_cols) #Segregating the Numeric Variables numerical = df.select_dtypes(include['int32', 'int64', 'float64', 'uint8']) numerical = numerical.drop(columns=['loan_condition_cat']) numerical_cols = list(numerical.columns) #FEATURE SCALING normalize = MinMaxScaler() standardize = StandardScaler() numerical_scaled = normalize.fit_transform(numerical) #numerical_scaled = standardize.fit_transform(numerical) #TRANSFORMED DATASET df_transformed = pd.DataFrame(numerical_scaled, columns=[numerical_cols]) df_transformed['loan_condition_cat'] = df['loan_condition_cat']
Стратифицированная выборка Pycaret для обучения и тестирования
data = df_transformed.copy() import pycaret from pycaret.classification import * clf1 = setup(data, target = 'loan_condition_cat', session_id=123, log_experiment=True, data_split_stratify=True, experiment_name='pycaret dummy_bank', n_jobs=-6)
Настройка модели классификации
Для достижения лучших показателей были реализованы следующие настройки:
- Управление дисбалансом классов с помощью: Вес класса = «сбалансированный»
- Пороговая оптимизация: вероятностный_порог = 0,1
Построение модели
Пикарет XGB:
xgb = create_model('xgboost', probability_threshold=0.1, class_weight="balanced")
#Visualization plot_model(xgb, plot = 'confusion_matrix')
Случайный лес Пикаре:
rf = create_model('rf', probability_threshold=0.1, class_weight="balanced")
#Visualization plot_model(rf, plot = 'confusion_matrix')
Понимание основных движущих сил с помощью SHAP
interpret_model(xgb)
Проведя все этапы, можно сделать следующие выводы:
1) С помощью модели интерпретирования Пикаре на безнадежные кредиты в основном влияют:
- Vintage of loan (recently approved loans tend to be good loans but as these loans age, bad loans starts to show)
- Higher interest rate
- Low Income
- Shorter term period
- Higher loan amount
2) Базовая модель (XGB) работает с полнотой 63%. Это было достигнуто за счет корректировки веса классов и настройки порога классификации до 10%.
3) В соответствии с этими выводами рекомендуется следующее:
- Add new features relevant to each of the loan (historical transaction of customer)
- Cluster customers based on the features available and use it as a new feature
- Build and/or combine other classification models to improve Recall
- Further optimize the classification threshold to improve Recall