. Пример решения задачи кредитного скоринга c помощью связки python+pandas+scikit-learn
Пример решения задачи кредитного скоринга c помощью связки python+pandas+scikit-learn

Пример решения задачи кредитного скоринга c помощью связки python+pandas+scikit-learn

Задача состоит в том, чтобы на выборке «train» необходимо построить модель, определяющую вероятность «дефолта», и проставить вероятности ее по клиентам из выборки «test». Для оценки модели будет использоваться характеристика Area Under ROC Curve (также указано в условиях задачи).

Предварительная обработка данных

Для начала загрузим исходные файлы и посмотрим на них:

tcs_customer_id bad sample_type 0 1 NaN test 1 2 0 train 2 3 1 train 3 4 0 train 4 5 0 train

Из условий задачи можно предположить, что набор SampleAccounts содержит несколько записей по одному заемщику давайте проверим это:

Наше предположение оказалось верным. Уникальных заемщиков 50000 из 280942 записей. Это связано с тем, что у одно заемщика быть несколько кредитов и по каждому из них в разных бюро моте быть разная информация. Следовательно, надо выполнить преобразования над SampleAccounts, чтобы одному заемщику соответствовала одна строка. Теперь давайте получим список все уникальных кредитов по каждому заемщику:

Следовательно, когда мы получили список кредитов, мы сможем вывести какую-либо общую информацию по каждому элементу списка. Т.е. можно было бы взять связку из перечисленных выше полей и сделать ее индексом, относительно которого мы бы производили дальнейшие манипуляции, но, к сожалению, тут нас подстерегает один неприятный момент. Он заключается в том, что поле 'final_pmt_date' в наборе данных имеет незаполненные значения. Давайте попробуем избавиться от них. У нас в наборе есть поле фактическая дата закрытия кредита, следовательно, если она есть, а поле 'final_pmt_date' не заполнено, то можно в него записать данное значение. Для остальных же просто запишем 0.

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

inf_confirm_date tcs_customer_id open_date final_pmt_date credit_limit currency 1 39261 39629 19421 RUB 39924 39505 39870 30000 RUB 39862 39644 40042 11858 RUB 40043 39876 41701 300000 RUB 40766 39942 40308 19691 RUB 40435 40421 42247 169000 RUB 40756 40428 51386 10000 RUB 40758 40676 41040 28967 RUB 40764 2 40472 40618 7551 RUB 40661 40652 40958 21186 RUB 40661 3 39647 40068 22694 RUB 40069 40604 0 20000 RUB 40624 4 38552 40378 75000 RUB 40479 39493 39797 5000 RUB 39823 39759 40123 6023 RUB 40125 Теперь добавим полученные нами даты к основному набору:

  • pmt_string_84m
  • pmt_freq
  • type
  • status
  • relationship
  • bureau_cd
  • 0 — не было последнего платежа
  • 1 — последний платеж был

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

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

  1. Убрать ненужные столбцы
  2. Привести все кредитные лимиты в рубли
  3. Посчитать какое количество кредитов у каждого заемщика по информации от бюро

Далее переведем все кредитные лимиты к рублям. Для простоты я взял курсы валют на текущий момент. Хотя правильнее наверное было бы брать курс на момент открытия счета. Еще один нюанс, в том, что для анализа нам надо убрать текстовое поле «сurrency», поэтому после перевода валют в рубли мы проведем с этим полем манипуляцию, которые мы провели с полями выше:

Итак перед заключительной группировкой добавим к нашему набору поле заполненное единицами. Т.е. когда мы выполним последнюю группировку, сумма по нему даст количество кредитов у заемщика:

Теперь, когда у нас в наборе данных все данные количественные, можно заполнить пробелы в данных 0 и выполнить заключительную группировку по клиенту:

Предварительный анализ

Ну что же первичная обработка данных завершена и можно приступить к их анализу. Для начала разделим наши данные на обучающую и тестовую выборки. В этом нам поможет столбец «sample_type» из SampleCustomers, по нему как раз сделано такое разделение. Для того чтобы разбить наш обработанный DataFrame, достаточно объединить его с SampleCustomers поиграться фильтрами:

Далее давайте посмотрим, как признаки коррелирует между собой, для этого построим матрицу с коэффициентами корреляции признаков. С помощью pandas это можно сделать одной командой:

После действия выше CorrKoef будет содержать матрицу размеров 61x61. Строками и столбцами ее будут соответствующие имена полей, а на их пересечении — значение коэффициента корреляции. Например: fact_close_date status_13 0.997362 Возможен случай, когда коэффициента корреляции нет. Это значит, что в данные поля скорее всего заполнены только одним одинаковым значением и их можно опустить при анализе. Проверим:

  • pmt_string_84m_6
  • pmt_string_84m_8
  • pmt_freq_5
  • pmt_freq_A
  • pmt_freq_B
  • status_12

На выходе получим следующие:

fact_close_date-->status_13: r^2=0.997362 ttl_delq_5_29-->ttl_delq_30: r^2=0.954740 ttl_delq_5_29-->pmt_string_84m_A: r^2=0.925870 ttl_delq_30_59-->pmt_string_84m_2: r^2=0.903337 ttl_delq_90_plus-->pmt_string_84m_5: r^2=0.978239 delq_balance-->max_delq_balance: r^2=0.986967 pmt_freq_3-->relationship_1: r^2=0.909820 pmt_freq_3-->currency_RUB: r^2=0.910620 pmt_freq_3-->count_credit: r^2=0.911109

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

Построение и выбор модели

Ну что же первичные данные обработаны и теперь можно перейти к построению модели. Отделим признак класса от обучающей выборки:

Теперь давайте уменьшим размерность нашей выборки, дабы взять только значимые параметры. Для этого воспользуемся методом главных компонент и его реализацией PCA() в модуле sklearn. В параметре мы передаем количество компонент, которые мы хотим сохранить(я выбрал 20, т.к. при них результаты моделей практически не отличались от результатов по исходным данным)

Итак модели выбраны. Давайте сейчас разобьем нашу обучающую выборку на 2 подвыборки: тестовую и обучающую. Данное действие нужно чтобы мы могли посчитать характеристику auc для наших моделей. Разбиение можно провести функцией train_test_split() из модуля sklearn:

  1. Стандартными средствами модуля sklearn при помощи функции roc_auc_score или auc
  2. С помощью стороннего пакета ml_metrics и функции auc()

Итак, по результатам анализа наших моделей можно сказать, что лучше всего себя показал градиентный бустинг, его точность порядка 69%. Соответственно для обучения тестовой выборки мы выберем его. Давайте заполним информацию в тестовой выборке, предварительно обработав ее до нужного формата:

📎📎📎📎📎📎📎📎📎📎