Прогнозы одобрения ссуд | Понимание и ретроспективный взгляд

Сопровождение Jupyter Notebook

Недавно мне было предложено делать прогнозы по запросам заявок на получение кредита, предсказывая их результаты, используя набор данных, состоящий всего из 13 функций. Выбор прогнозов ограничивался утверждением запроса на ссуду или отказом в запросе ссуды, что делало это проблемой классификации. Сможем ли мы построить модель, которая будет работать лучше, чем просто выбор наиболее частого результата для утверждения ссуд?

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

Шаг 1. Изучите и проанализируйте данные

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

В наборе данных 13 переменных, и, похоже, есть МНОГО категориальных переменных, многие из которых имеют только бинарные опционы. Характеристики, связанные с доходом и суммой кредита, являются единственными непрерывными количественными переменными в наборе данных. В некоторых столбцах отсутствуют значения, представленные как NaN. Также следует отметить, что размер набора данных невелик, всего 614 записанных наблюдений, поэтому важно сохранить как можно больше наблюдений.

«Loan_ID» является уникальным идентификатором, поэтому он не поможет при составлении прогнозов. Мы планируем убрать этот столбец с высоким числом элементов.
«Пол» - это двоичная категориальная переменная, и ее назначение (указанное выше) - «Мужской» или «Женский». Предполагается, что объекты NaN не имеют особого значения и будут заполнены режимом функции.
'Женат - еще одна двоичная категориальная характеристика, и ее назначение - Y или N. Объекты NaN предполагается, что они не имеют значения и будут заполнены "наиболее частой" записью для этого столбца.
"Зависимые" - это категориальный признак с присвоением 0, 1, 2 или 3+. Предполагается, что объекты NaN не имеют смысла и будут заполнены режимом переменной.

«Образование» - это двоичная категориальная функция без объектов NaN.

«Самостоятельная работа» - это двоичная категориальная характеристика с присвоением Y или N. NaN-объекты не имеют значения и будут заполнены наиболее частым значением функции.

«Доход заявителя», «Доход соискателя» и «Сумма кредита» являются количественными переменными.

Доходы заявителя и созаявителя будут пересчитаны. Информация от автора набора данных показывает, что суммы ссуд указаны в тысячах. Это означало бы, что минимальный запрос на ссуду составлял 9000 долларов, а максимальный - 700000 долларов. Если использовать ту же шкалу для доходов заявителей, это будет означать, что минимальный доход составит 150 000 долларов США, а максимальный - 81 миллион долларов, что крайне маловероятно. Это также будет означать, что максимальный доход со-заявителя превышает 41 миллион долларов! При масштабировании доход соискателя будет составлять от 15 000 до 810 000 долларов, а доход второго заявителя - от 0 до 410 000 долларов. Выбросы будут удалены - доходы больше 250 000 долларов.

Есть много нулевых записей о доходах со-заявителей! Нулевая запись о доходе совместных заявителей может указывать на то, что заявители принадлежат к домохозяйствам с одним доходом. Однако нули составляют почти половину записей в столбцах! Более вероятно, что многие запросы на ссуду были поданы одним заявителем, и этот столбец заполнялся 0 даже в тех случаях, когда не было второго заявителя. Мы можем создать новую функцию под названием «total_income», которая добавляет доход заявителя и второго заявителя. В распределении этой новой функции не будет уродливого нулевого столбца.

Наконец, мы отбросим строки, в которых запрашиваемая сумма кредита не указана, и создадим новую функцию, «ссуду_до_доходу», которая покажет отношение запрошенной суммы ссуды к общему доходу.

Вот пик некоторых переработанных распределений переменных.

Loan_Amount_Term’ - категориальная переменная с числом элементов 10. Предполагается, что значения NaN не имеют значения и будут заполнены наиболее распространенным значением. Мы видим, что наиболее распространенный срок кредита - 30 лет, скорее всего, ипотека. Срок в 12 месяцев может указывать на личный заем, а срок действия 3 и 5 лет более типичен для автокредитования.

Что странно, так это то, что в функции «Property_Area» нет значений NaN; либо городские, полугородские или сельские районы заполняются для каждого наблюдения (без значений NaN), подразумевая, что набор данных представляет собой ссуды на недвижимость / жилье. Было бы предпочтительнее дальнейшее уточнение данных.

«Credit_History» - это двоичная категориальная переменная - кандидат соответствует требованиям или не соответствует требованиям. Предполагается, что значения NaN не имеют смысла и будут заполнены наиболее частым значением. Но разве это негерметичная функция? Все ли запросы на получение ссуды с кредитными историями, не соответствующими требованиям, приводят к отказу?

1.0    469
0.0     87
Name: Credit_History, dtype: int64
Y    417
N    188
Name: Loan_Status, dtype: int64

Не каждая запись, приводящая к отказу, имеет кредитную историю, не отвечающую требованиям.

neg_credit_approved_loan = train[ (train['Credit_History'] == 0) &
       (train['Loan_Status'] == 'Y')]
print(neg_credit_approved_loan['Credit_History'])
print(neg_credit_approved_loan['Loan_Status'])
122    0.0
201    0.0
267    0.0
326    0.0
453    0.0
527    0.0
Name: Credit_History, dtype: float64
122    Y
201    Y
267    Y
326    Y
453    Y
527    Y
Name: Loan_Status, dtype: object

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

Loan_Status ’- это цель, или то, что мы пытаемся предсказать. «Была ли эта ссуда одобрена, да или нет?»

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

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

Шаг 2. Разделите данные

После обработки данных у нас осталось 583 из 614 исходных записей. Мы отделим «Loan_Status» от матрицы функций и сделаем его нашим целевым массивом. Поскольку набор данных для наблюдений невелик, данные будут разделены на наборы для обучения и тестирования; набор проверки не будет использоваться. В наборе данных отсутствуют какие-либо маркеры даты или времени, поэтому он будет разделен случайным образом. Двадцать процентов данных зарезервировано для нашего тестового набора.

Шаг 3. Установите базовый уровень

Классы целевого вектора умеренно несбалансированы в сторону утверждения, но менее 70%, поэтому мы все еще можем посмотреть на точность модели для оценки.

Помимо точности модели, мы рассмотрим оценки перекрестной проверки наших моделей, их точность и запоминаемость, а также их кривые ROC, чтобы оценить их производительность.

Шаг 4. Постройте модели

Поскольку мы имеем дело с проблемой классификации, мы подгоним наши данные к 3 различным моделям - линейной модели, древовидной модели и той, которая использует усиление градиента. Мы выберем LogisticRegressionClassifier, RandomForestClassifier и XGBoostClassifier. Мы построим конвейер и будем использовать одно горячее кодирование со стандартным скейлером для нашей линейной модели, а также будем использовать порядковый кодировщик для наших древовидных моделей и моделей повышения градиента.

Шаг 5. Проверьте показатели

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

LogisticRegressionClassifier

Training Accuracy (LOGR): 82.40%
Test Accuracy (LOGR): 81.20%
Cross Validation Score (LOGR):
76.60%
79.57%
84.95%
82.80%
82.80%

RandomForestClassifier

Training Accuracy(RF): 100.00%
Test Accuracy (RF): 80.34%
Cross Validation Score (LOGR):
76.60%
78.49%
83.87%
84.95%
82.80%

XGBoostClassifier

Training Accuracy(XGB): 100.00%
Test Accuracy (XGB): 78.63%
Cross Validation Score (XGB):
73.40%
76.34%
82.80%
83.87%
81.72%

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

Давайте посмотрим на их матрицы путаницы.

Logistic Regression model precision: 78.64%
Logistic Regression model recall: 100.00%

Модель логистической регрессии улавливала все утверждения (точный отзыв), но не была очень точной (включала множество ложных утверждений - ссуд, которые были отмечены как одобренные, но на самом деле им было отказано).

Random Forest Classifier precision: 80.21%
Random Forest Classifier recall: 95.06%

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

XGBoost Classifier precision: 79.17%
XGBoost Classifier recall: 93.83%

Модель XBGBoost демонстрирует те же показатели точности и запоминаемости, что и две другие модели.

Кривая ROC - это еще один способ измерить эффективность модели, который отображает соотношение истинной положительности и ложной положительности. Чем больше площадь под этой кривой, тем выше производительность модели.

Logistic: ROA-AUC Score: 0.6944
Random Forest: ROC-AUC Score:: 0.7114
XGBoost: ROC-AUC Score:: 0.6914

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

Шаг 6. Настройте модель и перепроверьте показатели

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

Давайте посмотрим на важность функций модели случайного леса.

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

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

Модель логистической регрессии

Training Accuracy(RF): 82.19%
Test Accuracy (RF): 81.20%

Модель случайного леса

Training Accuracy(RF): 84.55%
Test Accuracy (RF): 82.91%

Обе модели теперь имеют показатель точности 80% и показатель отзываемости 100%.

Давайте, наконец, еще раз посмотрим на кривую ROC и область под ней.

Logistic: ROA-AUC Score: 0.6944
Random Forest: ROC-AUC Score:: 0.7222
XGBoost: ROC-AUC Score:: 0.6806

После удаления отвлекающих элементов и настройки наших моделей мы объявили победителя! Наша модель случайного леса не только превосходит нашу базовую точность, равную 69,64%, и превосходит другие модели, но и больше не соответствует обучающим данным!

Это хорошие новости.

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

Результаты с этой функцией упали?

Результаты не лучше базовых, что делает модель бесполезной.

Развязка

Набор данных отсутствовал по многим причинам - ни кредитных рейтингов, ни записей о том, когда были приняты решения о ссуде, никакого статуса занятости (только статус самозанятого) и так далее. Наши модели в конечном итоге не зарекомендовали себя как суперполезные или полезные - они просто много говорили «да». Особенность кредитной истории имеет огромное значение. Модели помещают большинство соискателей в груду утверждения ссуды «это было легко», а затем сразу же приступают к делу. Добавление всех этих ложных срабатываний в совокупность приводит к поражению цели повышения эффективности кредитных специалистов.

Этот проект очень четко демонстрирует пословицу: «Мусор на входе, мусор на выходе». Получение хороших данных в начале проекта имеет огромное значение и облегчит создание полезных моделей.