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

«Нам нужна машина, которая может учиться на собственном опыте, - Алан Тьюринг»

1. Введение

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

Анализ риска кредитного дефолта с использованием машинного обучения может быть важным способом для кредиторов понять, насколько вероятно, что конкретная ссуда будет погашена. Другими словами, это инструмент для понимания кредитного риска заемщика. Это особенно важно, потому что профиль кредитного риска постоянно меняется со временем и обстоятельствами. Это определенно поможет банкам ускорить процесс одобрения кредита.

1.1 Что такое кредитный риск?

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

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

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

1.2 Проблема бизнеса / реального мира

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

1.3 Постановка проблемы

На основании имеющихся данных мы должны предсказать, будет ли заявитель дефолт по кредиту или нет. Целевые метки доступных данных следующие:

1 = заявитель не выплачивал ссуду

0 = заявитель не допустил дефолта по кредиту

1.4 Информация о данных

Источник данных: данные можно скачать здесь.

  • application_train / application_test: основные данные для обучения и тестирования с информацией о каждой кредитной заявке в Home Credit. Каждая ссуда имеет свою строку и обозначается признаком SK_ID_CURR. Данные обучающего приложения содержат TARGET, указывающее 0: ссуда была погашена или 1: ссуда не была возвращена.
  • бюро: данные о предыдущих кредитах клиента в других финансовых учреждениях. Каждый предыдущий кредит имеет свою собственную строку в бюро, но у одного кредита в данных заявки может быть несколько предыдущих кредитов.
  • bureau_balance: ежемесячные данные о предыдущих кредитах в бюро. Каждая строка представляет собой один месяц предыдущего кредита, а один предыдущий кредит может иметь несколько строк, по одной на каждый месяц продолжительности кредита.
  • previous_application: предыдущие заявки на получение ссуд в Home Credit от клиентов, у которых есть ссуды в данных приложения. Каждая текущая ссуда в данных приложения может иметь несколько предыдущих ссуд. Каждое предыдущее приложение имеет одну строку и обозначается функцией SK_ID_PREV.
  • POS_CASH_BALANCE: ежемесячные данные о предыдущих торговых точках или кредитах наличными, которые клиенты получали в Home Credit. Каждая строка представляет собой один месяц предыдущей торговой точки или ссуды наличными, а одна предыдущая ссуда может состоять из нескольких строк.
  • credit_card_balance: ежемесячные данные о предыдущих кредитных картах, которые клиенты использовали с Home Credit. Каждая строка представляет собой один месяц баланса кредитной карты, а на одной кредитной карте может быть много строк.
  • installments_payment: история платежей по предыдущим займам в Home Credit. Есть одна строка для каждого произведенного платежа и одна строка для каждого пропущенного платежа.

1.5 Оценочная метрика

Здесь мы будем использовать AUC для оценки производительности модели. Площадь под кривой (AUC) объясняется своим названием. Это просто область под кривой ROC. (Это интеграл кривой.) Этот показатель находится в диапазоне от 0 до 1, при этом лучшая модель получает более высокие баллы. Модель, которая просто угадывает наугад, будет иметь ROC AUC 0,5.

1.6 Ограничения

  • Задержка. Как таковых ограничений по задержке нет. Банку не нужно сразу же оценивать, станет ли заявитель невыполненным по кредиту. Следовательно, существует требование низкой задержки.
  • Интерпретируемость: банк может быть заинтересован в понимании причин отказа определенному заявителю. Следовательно, требуется интерпретируемость . Это позволяет банку предотвратить отказ подходящих клиентов.
  • Возможности. В нескольких таблицах данных содержится большое количество функций, что делает визуальное изучение функций довольно громоздким.
  • Переоборудование. Поскольку существует множество функций, есть вероятность переобучения наших данных. Итак, мы должны быть осторожны при извлечении функций.

1.7 Тип проблемы

  • Контролируемое обучение: здесь мы сопоставляем входные данные с выходными на основе примеров пар вход-выход. (Для дополнительной информации щелкните здесь")
  • Двоичная классификация. Здесь мы классифицируем соискателей независимо от того, не имеют ли они дефолта по ссуде или нет.

1.8 Библиотеки

  • Pandas: предлагает мощные, выразительные и гибкие структуры данных.
pip3 install pandas
  • XgBoost: оптимизированная библиотека распределенного повышения градиента.
pip3 install xgboost
  • Scikit-learn: простые и эффективные инструменты для интеллектуального анализа и анализа данных.
pip3 install scikit-learn

2. Распространение данных

  • Несбалансированные: это несбалансированные данные, поскольку проблема классификации имеет неодинаковые экземпляры для разных классов, т. е. более 2,5 тысяч человек не выполнили обязательства по ссуде, тогда как только 24 тысячи человек не выполнили свои обязательства по ссуде. .

  • Форма данных: у нас есть семь таблиц данных, одна из которых основная, две - второстепенные, а остальные - третичные . Первичная таблица данных связана с вторичными таблицами данных через SK_ID_CURR, а вторичные данные связаны с третичными данными через SK_ID_PREV и SK_ID_BUREAU.

3. Отсутствующая информация

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

def missing_values(df):
    a=pd.DataFrame(df.isnull().sum(), columns=["missing_values"])
    a["% of missing values"]= np.round((df.isnull().sum()*100)\
    /1en(df),2)

    b=a.sort_values("missing_values", ascending=False)
    print("The number of columns with missing values are ",len
    (b[b["missing_values"]>0]),"out of ",df.shape[1], "columns")
    return b

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

4. Типы данных

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

def data_type(df):
    print("The types of data present are as follows: ")
    print("="*50)
    print(df.dtypes.value_counts())
    print("="*50)
    print("Number of unique data names in categorical data are: ")
    print("="*50)
    print(df.select_dtypes('object').apply(pd.Series.nunique,\
    axis = 0))

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

5. Разделение данных на обучение, тестирование и перекрестную проверку.

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

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

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

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

6. Данные приложения (основные)

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

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

6.1 Исследовательский анализ данных

Аномалии. Одна из проблем, которую мы всегда должны учитывать при выполнении EDA, - это аномалии в данных. Это может быть из-за неправильного набора чисел, ошибок в измерительном оборудовании или из-за допустимых, но крайних значений. Как правило, мы можем использовать коробчатые диаграммы, чтобы найти выбросы.

  • Дни занятости: Это относится к количеству лет, в течение которых человек работал при подаче заявления на ссуду. Здесь мы находим несколько точек данных с более чем 1000-летним стажем работы и, следовательно, отбрасываем их.

  • Количество детей на каждого заявителя: Это относится к количеству детей, которые есть у каждого заявителя. Большинство поступающих имеют не более двух детей. Мы будем исключать претендентов с более чем 8 детьми.

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

Корреляция. Один из способов попытаться понять данные - найти корреляции между функциями и целью. Мы можем рассчитать коэффициент корреляции Пирсона между каждой переменной и целью, используя метод .corr dataframe.

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

Здесь мы получили корреляцию характеристик с целевыми данными.

Для дальнейшего анализа данных мы рассмотрим сильно коррелированные характеристики, такие как внешний источник 1,2 и 3 и возраст заявителя. Здесь возраст заявителя положительно коррелирует, а это означает, что человек, скорее всего, не выплатит ссуду по мере увеличения возраста. Это потому, что данные о возрасте отрицательны. В общем, мы можем сделать вывод, что с возрастом вероятность дефолта по ссуде снижается.

Здесь мы обнаруживаем, что возраст клиента отрицательно коррелирует с внешним источником 1, подразумевая, что эта оценка зависит от возраста клиента.

В качестве финального исследовательского участка мы сделаем парные графики с переменными Внешнего источника и возрастом заявителя.

6.2 Разработка функций

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

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

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

  • CREDIT_INCOME_PERCENT: процент суммы кредита относительно дохода клиента.
  • ANNUITY_INCOME_PERCENT: процент аннуитета по ссуде относительно дохода клиента.
  • CREDIT_TERM: продолжительность платежа в месяцах (так как аннуитет - это ежемесячная сумма, причитающаяся
  • DAYS_EMPLOYED_PERCENT: процент отработанных дней по отношению к возрасту клиента.
X_train_check['CREDIT_INCOME_PERCENT'] = X_train_check['AMT_CREDIT'] / X_train_check['AMT_INCOME_TOTAL']
X_train_check['ANNUITY_INCOME_PERCENT'] = X_train_check['AMT_ANNUITY'] / X_train_check['AMT_INCOME_TOTAL']
X_train_check['CREDIT_TERM'] = X_train_check['AMT_ANNUITY'] / X_train_check['AMT_CREDIT']
X_train_check['DAYS_EMPLOYED_PERCENT'] = X_train_check['DAYS_EMPLOYED'] / X_train_check['DAYS_BIRTH']

Используя парный сюжет, трудно сказать, будут ли полезны эти новые функции. На данный момент мы не будем отказываться от этих функций.

7. Данные бюро (вторичные)

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

Эти данные содержат информацию о заявителях, которые ранее подавали заявки на ссуды в различных других учреждениях. SK_ID_CURR связывает с этим первичные данные приложения.

7.1 Разработка функций

Подсчет заявок: мы подсчитаем предыдущие заявки от клиентов из других учреждений и добавим их к данным заявки. Это требует ряда операций Pandas.

  • Группировать по: операция включает в себя некоторую комбинацию разделения объекта, применения функции и объединения результатов. В этом случае мы сгруппируем по уникальному клиенту, столбцу SK_ID_CURR
  • Агрегировать: агрегирование с использованием одной или нескольких операций по указанной оси. Мы можем либо вызвать функцию напрямую (grouped_df.mean()), либо использовать функцию agg вместе со списком преобразований (grouped_df.agg([mean, max, min, sum]))
  • Слияние: легко объединяет вместе объекты Series, DataFrame и Panel с различными видами логики набора. Нам нужно объединить исходные данные обучения с вычисленной статистикой в ​​столбце SK_ID_CURR, который вставит NaN в любую ячейку, для которой у клиента нет соответствующей статистики.

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

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

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

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

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

group_var = 'SK_ID_CURR'
columns = ['SK_ID_CURR']
for var in categorical_grouped.columns.levels[0]:
    if var != group_var:
        for stat in categorical_grouped.columns.levels[1][:-1]:
            columns.append('%s_%s' % (var, stat))categorical_grouped.columns = columns

Агрегирование данных баланса бюро (третичное): данные баланса бюро содержат информацию о ежемесячной информации о кредитах предыдущих займов от других организаций. SK_ID_BUREAU свяжите с этим данные вторичного бюро.

Чтобы объединить эти данные с первичными данными:

  • Мы объединяем числовые и категориальные столбцы в данных баланса бюро по SK_ID_BUREAU с такими функциями, как сумма, среднее, количество, максимальное, минимальное, как обсуждалось ранее.
  • После агрегирования Мы объединяем эти данные с идентификатором заявителя данных вторичного бюро SK_ID_CURR на SK_ID_BUREAU.
  • Далее агрегируем полученные данные по SK_ID_CURR.
  • Наконец, мы объединяем данные, полученные на предыдущем шаге, с данными первичного приложения к SK_ID_CURR.

Следующий фрагмент кода выполняет все шаги, упомянутые выше.

categorical_grouped = categorical_data.groupby('SK_ID_BUREAU', as_index=False).agg(['sum', 'mean']).reset_index()
group_var = 'SK_ID_BUREAU'
columns_cat = ['SK_ID_BUREAU']
for var in categorical_grouped.columns.levels[0]:
    if var != group_var:
        for stat in categorical_grouped.columns.levels[1][:-1]:
            columns_cat.append('%s_%s' % (var, stat))
categorical_grouped.columns = columns_cat
categorical_grouped.SK_ID_BUREAU.astype(int)
numerical_grouped = bureau_balance_21.groupby('SK_ID_BUREAU', as_index = False.agg(['count', 'mean', 'max', 'min','sum']).reset_index()
columns_num = ['SK_ID_BUREAU']
for var in numerical_grouped.columns.levels[0]:
    if var != 'SK_ID_BUREAU':
        for stat in numerical_grouped.columns.levels[1][:-1]:
            columns_num.append('bureau_%s_%s' % (var, stat))
numerical_grouped.columns = columns_num
bureau_balance_papplication = categorical_grouped.merge(numerical_grouped,on = 'SK_ID_BUREAU', how ="outer") 
bureau_papplication = bureau_2[['SK_ID_BUREAU', 'SK_ID_CURR']]\
.merge(bureau_balance_papplication, on = 'SK_ID_BUREAU', how = 'left')
bureau_papplication=bureau_papplication.drop(['SK_ID_BUREAU'],axis=1)
bureau_papplication.rename(columns={'SK_ID_CURR_x':'SK_ID_CURR'}, inplace=True)
bureau_papplication = bureau_papplication.groupby('SK_ID_CURR', as_index=False).count()

8. Предыдущие данные приложения (второстепенные)

Как и данные Бюро, данные предыдущей заявки состоят из информации о предыдущих кредитах заявителей. Единственное отличие состоит в том, что данные Бюро состоят из информации о предыдущих займах от других организаций, тогда как данные из предыдущих заявок состоят из информации о предыдущих займах от того же учреждения (Home Credit). Мы будем извлекать информацию так же, как и для данных бюро.

8.1 Разработка функций

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

Подсчет предыдущих заявок. Мы подсчитываем предыдущие заявки для клиентов в Home Credit так же, как и для данных бюро, и добавляем их к данным первичной заявки.

Агрегирование числовых и категориальных данных. Как обсуждалось ранее, мы будем агрегировать данные по SK_ID_CURR и объединить их с данными первичного приложения. Получаем корреляции агрегированных w.r.t. целевые данные.

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

Третичные данные: у нас есть 3 таблицы данных, которые связаны с данными предыдущего приложения. Это POSH_CASH_BALANCE, credit_card_balance и installments. Все трое по нашим вторичным данным на SK_ID_PREV. Мы будем следовать тому же методу агрегации, чтобы извлекать характеристики из этих таблиц, как и в случае с данными баланса Бюро.

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

9. Оптимизация функций

Когда мы извлекли функции из всех таблиц, мы увидели огромное количество функций, которые могут легко перекрыть наши данные. В конце извлечения признаков количество объектов увеличилось со 122 до 957. Также мы столкнулись с большим количеством шума при извлечении этих функций. Следовательно, нам необходимо устранить некоторые из этих функций, чтобы наша модель не переобучалась.

Отсутствующая информация. Один из способов отказа от функций - это отбросить столбцы с большим количеством недостающей информации. Не существует четко установленного порога для удаления пропущенных значений, и лучший способ действий зависит от проблемы. Здесь, чтобы уменьшить количество функций, мы удалим все столбцы в данных обучения, тестирования и перекрестной проверки, которые имеют более 70% пропущенных значений. Это можно делать через регулярные промежутки времени при извлечении функций, если есть вычислительные ограничения, или это можно сделать полностью в конце с помощью следующей функции.

def column_optimization(train, test,cv, threshold = 70):
    train_1 = pd.DataFrame(train.isnull().sum())
    train_1['percent'] = 100 * train_1[0] / len(train)
    
    test_1 = pd.DataFrame(test.isnull().sum())
    test_1['percent'] = 100 * test_1[0] / len(test)
    
    cv_1 = pd.DataFrame(cv.isnull().sum())
    cv_1['percent'] = 100 * cv_1[0] / len(test)
  
    train_2 = list(train_1.index[train_1['percent'] > threshold])
    test_2  = list(test_1.index[test_1['percent'] > threshold])
    cv_2    = list(cv_1.index[cv_1['percent'] > threshold])
 
    useless_columns = list(set(train_2 + test_2+cv_2))
    
    print('There are %d columns with greater than %d%%\
    missing   values.' % (len(useless_columns), threshold))
    
    train = train.drop(columns = useless_columns)
    test = test.drop(columns = useless_columns)
    cv =   cv.drop(columns = useless_columns)
    
    return train, test, cv

Коллинеарные переменные. Как мы видели ранее, мы можем вычислить не только корреляции переменных с целью, но также корреляцию каждой переменной со всеми остальными переменными. Это позволит нам увидеть, есть ли сильно коллинеарные переменные, которые, возможно, следует удалить из данных. Мы удалим переменные с корреляцией больше 0,8 с другими переменными. Мы можем использовать следующий код, чтобы отбросить коллинеарные переменные.

def collinear_removal(train,test,cv,threshold=0.8):
    from tqdm import tqdm
    Y_train=train["TARGET"]
    Y_test=test["TARGET"]
    Y_cv=cv["TARGET"]
    
    train= train.drop(["TARGET"],axis=1)
    test= test.drop(["TARGET"],axis=1)
    cv= cv.drop(["TARGET"],axis=1)
    correlations= train.corr()
    above_threshold_features = {}

    for column in tqdm(correlations):
        above_threshold_features[column] = list\
        (correlations.index  [correlations[column] > threshold])
    columns_to_remove = []
    columns_seen = []
    columns_to_remove_pair = []
    for key, value in tqdm(above_threshold_features.items()):
        columns_seen.append(key)
        for x in value:
            if x == key:
                next
            else:
                # Only want to remove one in a pair
                if x not in columns_seen:
                    columns_to_remove.append(x)
                    columns_to_remove_pair.append(key)
     columns_to_remove = list(set(columns_to_remove))
     print('These many columns will be removed: ',\
     len(columns_to_remove))
    X_train2 = train.drop(columns = columns_to_remove)
    X_test2 = test.drop(columns = columns_to_remove)
    X_cv2=    cv.drop(columns = columns_to_remove)
    X_train2["TARGET"] =Y_train
    X_test2["TARGET"]  =Y_test
    X_cv2["TARGET"]    =Y_cv
    
    return X_train2,X_test2,X_cv2

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

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

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

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

from sklearn.preprocessing import MinMaxScaler, Imputer
import warnings
warnings.filterwarnings("ignore")
Y_train= list(X_train["TARGET"])
Y_test= list(X_test["TARGET"])
Y_cv= list(X_cv["TARGET"])
train = X_train.drop(columns = ['TARGET'])
cv= X_cv.copy()
cv = X_cv.drop(columns = ['TARGET'])
test= X_test.copy()
test = X_test.drop(columns = ['TARGET'])
features = list(train.columns)
imputer = Imputer(strategy = 'median')
imputer.fit(train)
train_final = imputer.transform(train)
cv_final = imputer.transform(cv)
test_final = imputer.transform(test)

Нормализация: всегда рекомендуется масштабировать числовые атрибуты с действительными значениями в диапазоне от 0 до 1. Изменение масштаба входных атрибутов необходимо для некоторых моделей, таких как KNN, которые зависят от величины значений.

scaler = MinMaxScaler(feature_range = (0, 1))
scaler.fit(train_final)
train_final = scaler.transform(train_final)
cv_final = scaler.transform(cv_final)
test_final = scaler.transform(test_final)

11. Модели машинного обучения

Для базовой модели мы можем угадать одно и то же значение для всех примеров из набора перекрестной проверки. Для случайного классификатора мы знаем, что он даст нам область рабочих характеристик приемника под кривой (AUC ROC) 0,5. Мы можем использовать этот параметр для сравнения производительности нашей модели машинного обучения.

Чтобы построить нашу настроенную модель гиперпараметров, мы можем следовать этому методу:

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

11.1 Логистическая регрессия

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

Результаты: Здесь наш гиперпараметр - C. (Для получения дополнительной информации нажмите здесь)

Важность функции: здесь мы используем coef_ в качестве параметра для расчета будущей важности.

Наблюдения:

  • Мы обнаружили, что AUC для обучения и тестирования практически не изменилась для всех значений альфа.
  • Мы выбрали C = 0,6 и получили значение 0,754 на тестовых данных.
  • Можно смело сказать, что наша модель неплохо работает.
  • Самая важная особенность - DEF_30_CNT_SOCIAL_CIRCLE.
  • Из определений, это относится к тому, сколько наблюдений за социальным окружением клиента не выполнили 30 DPD (просроченных дней).

11.2 XGBoost

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

Результаты. Здесь у нас есть два гиперпараметра, которые нужно настроить: максимальная глубина и количество оценок.

Важность функции: здесь мы вычисляем важность функции на основе атрибута feature_importance_.

Наблюдения:

  • Мы выбрали нашу глубину равной 8 и оценки равной 60.
  • Данные поезда имеют значение AUC 0,827, а данные испытаний имеют значение AUC 0,750.
  • Самая важная особенность - CREDIT_TERM.
  • Из определений, это относится к продолжительности платежа в месяцах (поскольку аннуитет - это ежемесячная сумма, подлежащая выплате).

11.3 Случайный лес

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

Результаты:

Важность функции:

Наблюдения:

  • Мы выбрали нашу глубину равной 32 и оценки равной 100.
  • Данные поезда имеют значение AUC 0,981, а данные испытаний имеют значение AUC 0,742.
  • Самая важная особенность - EXT_SOURCE_2.
  • Эта функция нормализована, поэтому у нас мало информации о ней.

Точно так же я обучил эти данные с помощью классификатора SGD с потерей шарнира и наивным байесовским методом. Я обобщу все полученные результаты ниже.

12. Резюме

13. Заключение

Я кратко расскажу, как мы подошли к этой проблеме прогнозирования невозврата кредитов.

  1. У нас было 7 фреймов данных, из которых мы должны были извлечь информацию.
  2. Мы разделили данные на train, test и cv, чтобы предотвратить утечку данных во время работы над функциями.
  3. С этого момента мы работали над наборами данных для поездов и соответствующим образом преобразовали резюме и тестирование.
  4. Мы провели исследовательский анализ данных по основному фрейму данных и постарались удалить все возможные выбросы.
  5. Основываясь на знании предметной области и имеющейся у нас информации, мы рассчитали процент кредитного дохода, процент аннуитетного дохода, срок кредита и процент дней занятости и включили их в качестве фьючерсов в данные приложения.
  6. Мы извлекли признаки из вторичных и третичных данных, используя методы группировки и агрегирования.
  7. Мы оптимизировали функции, удалив по крайней мере одну из пары сильно коллинеарных функций.
  8. После извлечения функций из всех наборов данных мы предварительно обработали данные с помощью функции imputer, чтобы заполнить недостающие значения, и нормализовали данные с помощью масштабатора mini max.
  9. На основе этих данных мы применили наши модели машинного обучения, такие как логистическая регрессия, случайный лес и XgBoost.

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

14. Дальнейшие возможности

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

15. Ссылки

  1. Http://scikit-learn.org/stable/
  2. Https://xgboost.readthedocs.io/en/latest/
  3. Https://pandas.pydata.org/
  4. Http://robertmitchellv.com/blog-bar-chart-annotations-pandas-mpl.html
  5. Https://matplotlib.org/
  6. Https://docs.scipy.org/doc/numpy/reference/