Введение
Моделирование кредитного риска является важнейшим аспектом индустрии BFSI, позволяющим кредиторам оценивать вероятность дефолта заемщиков по кредитам. Мы все знаем, что происходит с прибыльностью и даже с выживанием финансовых учреждений, когда кредиты становятся мошенническими!
В этом блоге мы рассмотрим, как построить модель кредитного риска с помощью Python. Мы обсудим набор данных, попытаемся решить проблему несбалансированных данных, предварительно обработаем данные, обучим модель логистической регрессии и оценим ее производительность. Давайте погрузимся!
Обзор набора данных
Исходные данные, используемые в этом упражнении, взяты из общедоступных данных с LendingClub.com, веб-сайта, который связывает заемщиков и инвесторов через Интернет.
Переменные, используемые в данных
Зависимая переменная — 'not.full.paid': бинарная переменная, указывающая, что ссуда не была возвращена полностью, т. е. (заемщик либо не выполнил свои обязательства, либо кредит был «списан», что означало, что заемщик вряд ли когда-либо вернет его).
Независимые переменные
1) Credit.policy: 1, если клиент соответствует критериям кредитного андеррайтинга LendingClub.com, и 0 в противном случае.
2) цель: цель кредита (принимает значения «credit_card», «debt_consolidation», «образовательный», «major_purchase» и т. д.).
3) int.rate: процентная ставка по кредиту в виде доли (ставка 11% будет сохранена как 0,11). Заемщикам, которых LendingClub.com считает более рискованными, назначаются более высокие процентные ставки.
4) взнос: ежемесячный платеж (в долларах США), причитающийся заемщику, если кредит финансируется.
5) log.annual.inc:натуральный логарифм годового дохода заемщика, о котором сообщается самостоятельно.
6) dti:отношение долга к доходу заемщика (сумма долга, деленная на годовой доход).
7) fico: кредитный рейтинг FICO заемщика.
8) days.with.cr.line: количество дней, в течение которых у заемщика была кредитная линия.
9) revol.bal: оборотный баланс заемщика (сумма, не выплаченная в конце платежного цикла по кредитной карте).
10) revol.util: коэффициент использования возобновляемой линии заемщика (сумма использованной кредитной линии относительно общего доступного кредита).
12) inq.last.6mths:количество запросов заемщика от кредиторов за последние 6 месяцев.
13) delinq.2yrs:сколько раз заемщик просрочивал платеж более чем на 30 дней за последние 2 года.
14) pub.rec: количество уничижительных публичных записей заемщика (заявления о банкротстве, налоговые удержания или судебные решения).
Начнем с загрузки необходимых библиотек и данных.
# Import required libraries import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline # Import necessary modules from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import confusion_matrix, classification_report from sklearn.metrics import roc_auc_score # Load data df = pd.read_csv("loansdata.csv") print(df.shape)
Набор данных содержит 9578 строк и 14 столбцов. Всегда приятно просто взглянуть на набор данных, не так ли? Мы можем легко сделать это с помощью функции df.head()
, которая выводит следующий результат.
Итак, у нас есть первое представление о данных, и, прежде чем перейти к этапу моделирования, давайте посмотрим на сводную статистику переменных, которые у нас есть.
Функция df.describe()
будет генерировать описательную статистику числовых столбцов. Вы можете добавить transpose()
utility для переключения строк и столбцов, чтобы упростить чтение и интерпретацию, со столбцами, представляющими каждую статистику, и строками, соответствующими каждой числовой функции.
Мы могли бы отправиться в эпическое путешествие по детальному исследовательскому анализу данных, углубляясь в каждую переменную. Однако, чтобы все было быстро и лаконично, давайте нацелимся на звезду шоу: целевую переменную `not.full.paid`.
Глядя на вывод выше, мы замечаем, что эта озорная переменная играет в бинарную игру со значениями 0 и 1. Ах, среднее значение! Он стоит перед нами как секретный код, раскрывающий, что всего 16% записей осмелились бросить вызов условностям и не полностью погасили свои кредиты. Довольно мятежная банда!
Давайте рассмотрим это визуально с помощью приведенного ниже кода, который отображает количество вхождений для каждого уникального значения «not.full.paid» в наборе данных.
# Create a countplot of the target variable sns.countplot(data=df, x='not.fully.paid') # Set the plot title and axes labels plt.title("Countplot of not.fully.paid") plt.xlabel("not.fully.paid") plt.ylabel("Count") # Show the plot plt.show()
Выход:
Очевидно, у нас несбалансированный набор данных.
Подготовка данных для моделирования
Мы сделали наши первые шаги в области анализа данных, и теперь пришло время подготовить наши данные к мощному этапу моделирования! Но прежде чем мы продолжим, нам нужно пролить свет на тени отсутствующих значений, скрывающиеся в нашем наборе данных.
Приведенный ниже код выполняет задачу и генерирует количество пропущенных значений для каждой переменной.
Таким образом, мы можем ясно видеть переменные с пропущенными значениями. Давайте проведем обработку пропущенных значений с помощью вменения медианы. Конечно, есть и другие способы обработки пропущенных значений, но об этом как-нибудь в другой раз (или в блоге)!
columns_with_missing = ['days.with.cr.line', 'revol.util', 'inq.last.6mths','delinq.2yrs', 'pub.rec', 'log.annual.inc'] # Replace missing values with median in specified columns for column in columns_with_missing: median = df[column].median() df[column].fillna(median, inplace=True) # Check for the changes df.isnull().sum()
Выход:
Таким образом, преобразование отсутствующего значения выполнено, и следующее необходимое преобразование — преобразовать категориальную переменную purpose
в числовые переменные с помощью метода, называемого одним горячим кодированием.
df = pd.get_dummies(df, columns=['purpose'], drop_first=True, prefix='Pur') df.head()
Выход:
Масштабирование переменных-предикторов
Теперь у нас есть готовые переменные, и следующим шагом будет масштабирование переменных-предикторов. Масштабирование помогает нам выровнять игровое поле и гарантирует, что все предикторы имеют одинаковый диапазон значений. Это как привести всех к одному росту, чтобы никто не затмевал других!
Приведенный ниже код выполняет эту задачу.
target_column = ['not.fully.paid'] predictors = list(set(list(df.columns))-set(target_column)) df[predictors] = df[predictors]/df[predictors].max() df.describe().transpose()
Вывод ниже показывает, что теперь все независимые переменные масштабируются от 0 до 1.
Создание массивов обучающих и тестовых наборов
В этом фрагменте кода мы готовимся к обучению нашей модели машинного обучения, разделяя наши данные на наборы для обучения и тестирования. Это называется подходом к оценке модели методом удержания-валидации. Существуют и другие методы, такие как варианты перекрестной проверки, но мы будем использовать подход разделения обучения/тестирования.
Короче говоря, мы собираем наши функции из набора данных и сохраняем их в X
, присваивая целевую переменную y
. Чтобы обеспечить тщательное обучение и честное тестирование, мы разделили данные на наборы для обучения и тестирования с помощью функции train_test_split
. Отображая формы обучающих и тестовых наборов, мы можем проверить количество образцов и функций в каждом наборе, гарантируя, что все настроено для грандиозной производительности нашей модели!
X = df[predictors].values y = df[target_column].values X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=100) print(X_train.shape); print(X_test.shape)
Выход:
Обучающие и тестовые данные содержат 6704 и 2874 строки соответственно.
Обучение и оценка модели
Теперь, когда данные готовы, мы обучим модель логистической регрессии, используя обучающие данные. Алгоритм логистической регрессии широко используется для моделирования кредитного риска из-за его интерпретируемости и способности решать проблемы бинарной классификации. В реальных сценариях логистическая регрессия часто рассматривается как базовая модель, которая устанавливает цель для улучшения других алгоритмов машинного обучения.
После обучения модели мы оценим ее производительность как на обучающем, так и на тестовом наборах. Мы будем использовать показатели классификации, такие как матрица путаницы, отчет о классификации и оценка AUC, чтобы оценить эффективность модели.
logreg = LogisticRegression() logreg.fit(X_train, y_train) predict_train = logreg.predict(X_train) predict_test = logreg.predict(X_test) print(confusion_matrix(y_train,predict_train)) print(classification_report(y_train,predict_train))
Выход:
Давайте также посмотрим на производительность модели на тестовом наборе данных.
print(confusion_matrix(y_test,predict_test)) print(classification_report(y_test,predict_test))
Выход:
Приведенный выше вывод раскрывает интригующее откровение о производительности нашей модели. Похоже, он превосходно предсказывает неплательщиков, тех идеальных клиентов, которые добросовестно выплачивают свои кредиты. Однако, когда дело доходит до прогнозирования неплательщиков, наша модель немного отстает от величия.
А теперь придержите свое волнение на мгновение! Пусть вас не вводят в заблуждение кажущиеся впечатляющими показатели точности 84 % и 83 % на тренировочном и тестовом наборах соответственно. Позвольте мне сбросить на вас бомбу правды: точность — не лучший показатель для оценки моделей, работающих с несбалансированными данными, как в нашем текущем сценарии.
Вот в чем фишка: основная задача банка или финансового учреждения заключается в повышении предсказуемости неплатежеспособных клиентов (тех смельчаков, представленных числом 1 в переменной «not.full.paid»). Они хотят отточить свой хрустальный шар, чтобы точно выявлять потенциальных неплательщиков.
Итак, если не точность, то какой должна быть метрика оценки? Напомним, что в таких случаях часто используются оценка F-1 и оценка AUC, и мы рассмотрим их в следующем разделе, где мы попытаемся справиться с дисбалансом в наборе данных.
Обработка дисбаланса с помощью весов классов
Чтобы устранить дисбаланс классов, мы можем назначить веса классов, чтобы обеспечить сбалансированную перспективу для модели. Это можно сделать, передав веса аргументу class_weight
в модуле LogisticRegression
, как показано в коде ниже.
# dictionary of class weights weight_dict = {0:1.19, 1:6.25} # define the model logreg2 = LogisticRegression(random_state=10, class_weight=weight_dict) # fit the model logreg2.fit(X_train,y_train)
Назначая более высокие веса классу меньшинства, мы можем придать ему большее влияние во время обучения. Обратите внимание, что эти веса выбираются произвольно (с небольшим использованием деления), и вы также можете выбрать любую другую комбинацию.
Затем мы обучим и оценим модель логистической регрессии с этими пользовательскими весами классов, чтобы увидеть ее влияние на производительность.
predict_train = logreg2.predict(X_train) print(confusion_matrix(y_train,predict_train)) print(classification_report(y_train,predict_train)) print(roc_auc_score(y_train,predict_train))
Выход:
Давайте оценим модель на тестовом наборе данных.
predict_test = logreg2.predict(X_test) print(confusion_matrix(y_test,predict_test)) print(classification_report(y_test,predict_test)) print(roc_auc_score(y_test,predict_test))
Мы можем ясно наблюдать заметное улучшение результатов, упомянутых выше. Показатель recall
в тестовом наборе данных резко вырос с 2 % до впечатляющих 59 %, что указывает на существенное улучшение его способности правильно определять положительные случаи. Кроме того, оценка AUC, мера общей производительности модели, показала многообещающий прогресс, увеличившись с 0,5 до 0,61.
Хотя мы еще не достигли совершенства, эти улучшения служат надежной основой для производительности нашей модели. Двигаясь вперед, наша цель будет состоять в том, чтобы превзойти эти результаты, внедряя более сложные алгоритмы и стратегии, стремясь к еще более высоким показателям. Путь к безупречной модели кредитного риска продолжается!
Заключение
В этом сообщении блога мы рассмотрели моделирование кредитного риска с использованием Python. Мы обсудили набор данных, внедрили метод предварительной обработки и решили проблему несбалансированных данных. Мы обучили модель логистической регрессии, оценили ее производительность и исследовали влияние использования пользовательских весов классов.
Следующие шаги
Наше путешествие здесь не заканчивается! Есть захватывающие пути, по которым нужно следовать, и улучшения, которые необходимо внести. Ниже перечислены некоторые следующие шаги и предложения по повышению производительности нашей модели:
1. Выбор лучших весовых комбинаций:
Мы можем точно настроить веса классов, чтобы найти еще более эффективную комбинацию. Экспериментируя с различными весовыми коэффициентами, мы можем найти баланс, в котором должным образом учитываются классы как меньшинства, так и большинства. Это как найти идеальный рецепт успеха!
2. Раскрытие возможностей разработки признаков:
Мы можем вывести нашу модель на новый уровень, применив некоторые хитрости проектирования признаков. Это включает в себя изучение взаимосвязей между переменными, выявление корреляций и удаление любых избыточных или сильно коррелированных функций. Это похоже на расхламление нашего набора данных и раскрытие скрытого внутри потенциала!
3. Использование методов устранения дисбаланса:
Чтобы решить проблемы дисбаланса классов, мы можем использовать мощные методы, такие как SMOTE (метод искусственного меньшинства перед выборкой). SMOTE создает синтетические образцы класса меньшинства, повышая его представленность в наборе данных.
4. Высвобождение зверей: Random Forest, XG Boost и Deep Neural Nets
Теперь пришло время обратиться к тяжеловесам из области машинного обучения. Эти мощные алгоритмы обладают исключительными способностями к прогнозированию и могут обрабатывать сложные отношения в данных. Изучая эти передовые модели, мы можем обнаружить еще большую точность и эффективность прогнозирования.
Помните, друзья-энтузиасты науки, наши поиски идеальной модели кредитного риска продолжаются. По мере того, как мы приступаем к этим следующим шагам, давайте наслаждаться экспериментами и инновациями. Возможности безграничны, а награды велики. Мы идем вперед, стремясь к вершине производительности модели и области исключительной оценки рисков!
Свяжитесь со мной:
Пожалуйста, не стесняйтесь связаться со мной в Linkedin (https://in.linkedin.com/in/vikashsingh29)
#CreditRiskModeling #machinelearning #loandefault #BFSI