1. Деловая проблема:

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

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

2. О наборе данных:

Набор данных был взят с kaggle. Набор данных состоит из следующих таблиц:

а. application_record.csv

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

б. кредит_record.csv

Эта таблица содержит данные, относящиеся к прошлым
кредитным записям клиента (идентификатора), которые содержат месяц извлеченных
данных и статус платежа. Статус поясняет
количество дней, в течение которых должен быть погашен его долг.
i. id — номер клиента
ii. month_balance –месяц извлеченных данных — это начальная
точка, наоборот, 0 – текущий месяц, -1 – предыдущий
месяц и т. д.
III. статус

Недостатки набора данных:

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

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

3. Предварительная обработка данных и исследовательский анализ данных:

3.1 таблица application_record:

а. Проверка отсутствующих или нулевых значений в таблице.

application_record.isnull().sum(axis = 0)

ID                          0
CODE_GENDER                 0
FLAG_OWN_CAR                0
FLAG_OWN_REALTY             0
CNT_CHILDREN                0
AMT_INCOME_TOTAL            0
NAME_INCOME_TYPE            0
NAME_EDUCATION_TYPE         0
NAME_FAMILY_STATUS          0
NAME_HOUSING_TYPE           0
DAYS_BIRTH                  0
DAYS_EMPLOYED               0
FLAG_MOBIL                  0
FLAG_WORK_PHONE             0
FLAG_PHONE                  0
FLAG_EMAIL                  0
OCCUPATION_TYPE        134203
CNT_FAM_MEMBERS             0
dtype: int64 

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

  • Итак, для отсутствующих значений мы заменяем их новой функцией как «NAN» для лучшего анализа данных.

б. Мы конвертируем DAYS_BIRTH в AGE и DAYS_EMPLOYED в YEARS_EMPLOYED для лучшего понимания и интерпретации.

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

в. CODE_GENDER: представляет пол заявителя.

application_record['CODE_GENDER'].value_counts().plot(kind='bar')
plt.title('GENDER vs FREQUENCY')
plt.xlabel('gender')
plt.ylabel('frequency')

Наблюдения:

  • Женщин-абитуриентов значительно больше, чем мужчин.
  • Количество абитуриентов-женщин почти вдвое превышает количество абитуриентов-мужчин.

д. FLAG_OWN_CAR: указывает, есть ли у заявителя автомобиль или нет.

application_record.groupby(["FLAG_OWN_CAR", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')
plt.title('GENDER COMPARISON OF OWN_CAR vs FREQUENCY')
plt.xlabel('FLAG OWN CAR')
plt.ylabel('frequency')

Наблюдения:

  • Заявителей, не имеющих автомобиля, значительно больше
  • Сравнительно большее число соискателей-мужчин имеют автомобиль

е. FLAG_OWN_REALTY: показывает, владеет ли заявитель недвижимостью или нет.

application_record.groupby(["FLAG_OWN_REALTY", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')
plt.title('GENDER COMPARISON OF OWN_REALITY vs FREQUENCY')
plt.xlabel('FLAG OWN REAL ESTATE')
plt.ylabel('frequency')

Наблюдения:

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

ф. NAME_INCOME_TYPE:

application_record.groupby(["NAME_INCOME_TYPE", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')
plt.title('GENDER COMPARISON OF INCOME TYPE vs FREQUENCY')
plt.xlabel('FLAG OWN CAR')
plt.ylabel('frequency')

Наблюдения:

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

г. EDUCATION_TYPE:

application_record.groupby(["NAME_EDUCATION_TYPE", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')
plt.title('GENDER COMPARISON OF EDUCATION TYPE vs FREQUENCY')
plt.xlabel('FLAG OWN CAR')
plt.ylabel('frequency')

Наблюдения:

  • Всего существует 5 видов образовательного ценза: «Высшее образование», «Среднее/среднее специальное», «Неполное высшее», «Неполное среднее», «Ученая степень».
  • Большинство абитуриентов имеют среднее образование и лишь немногие имеют ученую степень.
  • Неплохое количество абитуриентов с высшим образованием
  • Также несколько абитуриентов не получили там высшего среднего образования.
  • Имея в виду, что соотношение женщин и мужчин почти вдвое выше, мы можем сказать, что у абитуриентов-мужчин выше процент незавершенных высших учебных заведений.

час NAME_FAMILY_STATUS:

application_record.groupby(["NAME_FAMILY_STATUS", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')
plt.title('GENDER COMPARISON OF FAMILY STATUS vs FREQUENCY')
plt.xlabel('NAME_FAMILY_STATUS')
plt.ylabel('frequency')

Наблюдения:

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

я. NAME_HOUSING_TYPE:

application_record.groupby(["NAME_HOUSING_TYPE", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')
plt.title('Gender comparison of HOUSING TYPE vs FREQUENCY')
plt.xlabel('HOUSING TYPE')
plt.ylabel('frequency')

Наблюдения:

  • Всего в записи шесть типов жилья: «Съемная квартира», «Дом/квартира», «Муниципальная квартира», «С родителями», «Кооперативная квартира», «Офисная квартира».
  • Большинство заявителей проживают в квартирах/домах.
  • Немногие живут с родителями, в служебной или съемной квартире или муниципальных квартирах.
  • Довольно похожие распределения для обоих полов

Дж. OCCUPATION_TYPE:

application_record.groupby(["OCCUPATION_TYPE", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')
plt.title('Gender comparison of OCCUPATION_TYPE vs FREQUENCY')
plt.xlabel('OCCUPATION_TYPE')
plt.ylabel('frequency')

Наблюдения:

  • Есть много соискателей, профессия которых не указана, и для них мы создали новую категорию-NAN
  • Среди тех, чья профессия была упомянута, большинство из них были разнорабочими или основным персоналом, торговцами, менеджерами или водителями.
  • Немногие кандидаты были ИТ-специалистами, сотрудниками отдела кадров, агентами по реалити-шоу или другими.
  • Мы видим, что соискателей-мужчин намного больше, чем соискателей-женщин по роду занятий — «РАБОЧИЕ», «НИЗКОКВАЛИФИЦИРОВАННЫЕ РАБОТНИКИ», «ОХРАННИКИ», «ВОДИТЕЛИ».
  • Для остальных типов занятий у нас есть аналогичные распределения

к. FLAG_MOBILE:

application_record['FLAG_MOBIL'].value_counts().plot(kind='bar')
plt.title('OWNS MOBILE vs FREQUENCY')
plt.xlabel('OWNS MOBILE')
plt.ylabel('frequency')

Наблюдения:

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

л. FLAG_WORK_PHONE :

application_record.groupby(["FLAG_WORK_PHONE", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')
plt.title('GENDER COMPARISON OF OWNS WORK PHONE vs FREQUENCY')
plt.xlabel('OWNS PHONE')
plt.ylabel('frequency')

Наблюдения:

  • У большинства заявителей не было рабочего телефона.

м. FLAG_PHONE :

application_record['FLAG_PHONE'].value_counts().plot(kind='bar')

Наблюдения:

  • У большинства соискателей нет телефона

н. FLAG_EMAIL:

application_record['FLAG_EMAIL'].value_counts().plot(kind='bar')

Наблюдения:

  • Почти все заявители использовали электронную почту или имели идентификатор электронной почты.

о. CNT_CHILDREN:

application_record.groupby(["CNT_CHILDREN", "CODE_GENDER"]).size().unstack(level=1).plot(kind='bar')

Наблюдения:

  • Количество детей заявителя варьируется от 0 до 19
  • У большинства заявителей нет детей, и лишь немногие имеют одного, двух и более детей.
  • По полу у них довольно похожее распределение

п. CNT_FAM_MEMBERS:

application_record['CNT_FAM_MEMBERS'].value_counts().sort_index(ascending = True).plot(kind='bar')

Наблюдения:

  • У большинства заявителей было два члена семьи.
  • Есть значительное количество заявителей с одним, тремя или четырьмя членами семьи.
  • У очень немногих заявителей было более 6 членов семьи.
  • Максимальное количество членов семьи для одного заявителя – 20 человек.

кв. ВОЗРАСТ:

application_record['AGE'].plot(kind='kde')

application_record.groupby('CODE_GENDER').AGE.plot.hist()
plt.legend()

Наблюдения:

  • Возрастной диапазон соискателей варьируется от 20 до 70 лет.
  • Максимальное количество абитуриентов находится в возрастном диапазоне 30–40 лет.
  • Для заявителей-женщин большинство заявителей находятся в диапазоне от 35 до 45 лет.
  • Среди заявителей-мужчин наибольшее количество заявителей находится в диапазоне от 25 до 35 лет.

р. ГОД РАБОТЫ:

application_record['YEARS_EMPLOYED'].plot(kind='kde')

application_record.groupby('CODE_GENDER').YEARS_EMPLOYED.plot.hist()
plt.legend()

Заключение:

  • Анализируя, я обнаружил, что люди, которые были безработными, имели одинаковую ценность. То есть количество дней, в течение которых они были безработными, одинаково для всех, что составляет 365243, что почти равно 1001 году.
  • Таким образом, для таких значений мы заменили количество дней безработицы на их возраст.
  • Кроме того, мы видим, что большинство людей, проработавших от 0 до 10 лет, имеют наибольшее количество заявок, и их частота экспоненциально уменьшается с увеличением количества лет работы.
  • Также мы наблюдаем, что люди, которые являются безработными более 40 лет (их текущий возраст), также обращаются за кредитными картами.

3.2 таблица Credit_record:

а. При проверке нулевых значений мы обнаружили, что в этой таблице нет нулевых значений.

credit_record.isnull().sum(axis = 0)

ID                0
MONTHS_BALANCE    0
STATUS            0
dtype: int64

б. СТАТУС:

credit_record.STATUS.value_counts().plot(kind = "bar")
plt.legend()

Наблюдения:

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

3.3 Сравнение application_record и credit_record:

print(len(application_record.ID.unique()))
print(len(credit_record.ID.unique()))
438510
45985

После пересечения двух таблиц:

app_record_id_list = application_record.ID.unique()
cred_record_id_list = credit_record.ID.unique()
print(len(np.intersect1d(app_record_id_list, cred_record_id_list)))
36457
  • Есть много заявителей, которые обращаются за кредитной картой и не имеют каких-либо предыдущих кредитов.
  • Из 438 510 заявителей только 36 457 заявителей ранее имели кредитную историю.
  • Итак, для обучения нашей модели у нас будет только 36 457 точек данных.

4. Некоторые из существующих решений и наблюдений:

1.https://www.kaggle.com/code/samuelcortinhas/credit-cards-data-cl
значение

Наблюдения:
● Только одна из характеристик имеет отсутствующее значение: тип_оккупации
● Существует 6 двоичных категориальных переменных, т. е. каждая из характеристик
является переменной-флагом. Например, есть ли у клиента автомобиль или нет
● Для создания целевой переменной он говорит, что пользователь относится к группе «высокого риска», если
и только если он опаздывает с платежами более чем на 30 дней
в противном случае «низкий риск»
Выводы -
● Для бинарной категориальной функции они используют 0 для реализации
отрицательного значения и 1 для реализации положительного во всех шести случаях< br /> ● По количеству дней со дня рождения определите возраст, который
лучше и проще интерпретировать.

2. https://www.kaggle.com/code/umerkk12/credit-card-predictive-anal
ysis

Наблюдения:
● Только одна из характеристик имеет отсутствующее значение: тип_оккупации
● Существует 6 двоичных категориальных переменных, т. е. каждая из характеристик
является переменной-флагом. Например, есть ли у клиента автомобиль или нет
● Для создания целевой переменной он говорит, что пользователь относится к группе «высокого риска», если
и только если он опаздывает с платежами более чем на 30 дней
в противном случае «низкий риск»
Выводы -
● Для бинарной категориальной функции они используют 0 для реализации
отрицательного значения и 1 для реализации положительного во всех шести случаях< br /> ● По количеству дней со дня рождения определите возраст, который
лучше и проще интерпретировать.

3. https://www.kaggle.com/code/rikdifos/credit-card-approval-predicti
on-using-ml#Algorithms

Наблюдения -
● Для создания целевой переменной он говорит, что пользователь плохой, если и
только если он задерживает платежи более чем на 30 дней, в противном случае
хороший
● Использована концепция of Weight of Evidence (WoE), который измеряет
способность переменной предсказывать
Выводы -
● Среди множества используемых алгоритмов XGBoost
показал себя лучший с точностью 93 % и работает намного
лучше, чем логистическая регрессия и SVM.

4.https://www.kaggle.com/code/tanulkumarsrivastava/99-4-accuracy-
credit-card-approval-model

Наблюдения -
● Использована очень хорошая и разумная методика для определения
целевой переменной
● Использована кодировка меток для категориальных функций
● Преобразовано количество дней в удобочитаемое формат
● Создание новых отношений с использованием образования и рода занятий,
чтобы восполнить недостающие значения характеристик род занятий
Выводы -
● Разработка функций в точку в частности, построение целевой
переменной
● В то время как другие отказались от признака занятия, он блестяще заполнил
признак занятия, используя построенную им взаимосвязь
● Достиг максимальной точности 99,4% используют дерево решений

5. Показатели производительности

  • Имея в виду, что это бинарная классификация, мы можем использовать F1-Score или AUC_ROC в качестве показателя для обучения наших моделей.
  • Также нам нужно следить за точностью и отзывом, потому что неправильная классификация может быть дорогостоящей, поскольку ложноотрицательный результат может привести к убыткам, а ложноположительный результат может привести к тому, что компания будет иметь дело с клиентами. кто не платит долги.
  • Мы также построим метрики путаницы для каждой из моделей для лучшего понимания.

6. Разработка функций:

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

6.1. кредит_запись

  • Сначала мы классифицируем СТАТУС каждой кредитной записи на ХОРОШИЕ, ПЛОХИЕ и НЕЙТРАЛЬНЫЕ записи.
  • После этого мы подсчитаем количество ХОРОШИХ, ПЛОХИХ и НЕЙТРАЛЬНЫХ записей для каждого идентификатора.
  • Теперь, в зависимости от количества хороших, плохих и нейтральных записей, мы будем классифицировать каждого кандидата либо как ХОРОШЕЕ (1), либо как ПЛОХОЕ (0), используя следующую логику:

  • Итак, сейчас у нас есть 3 новые функции, а именно Bad_Debt, Good_Debt, Neutral_Debt и целевая переменная с именем CREDIT_APPROVAL_STATUS.

Затем мы объединяем две таблицы: updated_credit_record и application_record.

merged_data = application_record.merge(credit_record, how='inner', on=['ID'])
print(merged_data.columns)
print(merged_data.shape)
merged_data.head()
Index(['ID', 'CODE_GENDER', 'FLAG_OWN_CAR', 'FLAG_OWN_REALTY', 'CNT_CHILDREN',
       'AMT_INCOME_TOTAL', 'NAME_INCOME_TYPE', 'NAME_EDUCATION_TYPE',
       'NAME_FAMILY_STATUS', 'NAME_HOUSING_TYPE', 'AGE', 'FLAG_MOBIL',
       'FLAG_WORK_PHONE', 'FLAG_PHONE', 'FLAG_EMAIL', 'OCCUPATION_TYPE',
       'CNT_FAM_MEMBERS', 'YEARS_EMPLOYED', 'Bad_Debt', 'Good_Debt',
       'Neutral_Debt', 'CREDIT_APPROVAL_STATUS'],
      dtype='object')
(36457, 22)

6.2. слитная_запись

а. Одно горячее кодирование. Мы выполняем однократное кодирование категориальных признаков: «ИМЯ_ДОХОД_ТИП», «ИМЯ_ОБРАЗОВАНИЕ_ТИП», «ИМЯ_СЕМЕЙНЫЙ_СТАТУС», «ИМЯ_ДОМА_ТИП». Мы используем одну горячую кодировку, потому что одна горячая кодировка предпочтительнее, когда в наборе данных не так много признаков, как в нашем случае.

б. Кодировка меток. Мы преобразуем все двоичные категориальные функции, такие как FLAG_OWN_CAR, FLAG_OWN_REALTY, FLAG_WORK_PHONE, FLAG_PHONE, FLAG_EMAIL, в числовые функции, используя 0 и 1 с помощью кодировщика меток.

в. Стандартизация числовых функций

д. Методы вменения пропущенных значений:

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

я. удаление функции: точность 99,2%

II. замена отсутствующего в качестве новой функции: точность 99,9%

III. обучение Дерева принятия решений по другим функциям для определения типа занятий: точность 98,9%

IV. обучение Random Forest другим функциям для определения типа занятия: точность 98,9%

  • Итак, мы использовали второй тип для заполнения наших недостающих значений.
  • После этого мы также выполнили одно горячее кодирование для объекта OCCUPATION_TYPE.

7. Обучение модели:

7.1. Обработка несбалансированных данных:

  • Мы знаем, что наши данные сильно несбалансированы, поэтому мы использовали SMOTE для обучающих данных, чтобы справиться с проблемой несбалансированных данных.
  • Перед использованием SMOTE:
oversample = SMOTE()
X_train, y_train = oversample.fit_resample(X_train, y_train)
print(“The number of classes before fit {}”.format(Counter(y_train)))
print(“The number of classes after fit {}”.format(Counter(y_train)))
print(Counter(y_train))
print(Counter(y_test))

Counter({1.0: 32660, 0.0: 151})
Counter({1.0: 3621, 0.0: 25})
  • После использования SMOTE:
oversample = SMOTE()
X_train, y_train = oversample.fit_resample(X_train, y_train)
print("The number of classes before fit {}".format(Counter(y_train)))
print("The number of classes after fit {}".format(Counter(y_train)))

The number of classes before fit Counter({1.0: 32660, 0.0: 32660})
The number of classes after fit Counter({1.0: 32660, 0.0: 32660})

7.2. Логистическая регрессия с поиском по сетке CV

  • Для значений C мы использовали

c_values ​​= [0.00000000000001,0.000000000001,0.0000000001,0.00000001,0.000001,0.0001,0.01,1]

# define models and parameters
model = LogisticRegression(max_iter = 10000,n_jobs=-1,verbose = 3)
c_values = [0.00000000000001,0.000000000001,0.0000000001,0.00000001,0.000001,0.0001,0.01,1]

# define grid search
grid = dict(C=c_values)
clf = GridSearchCV(estimator=model, param_grid=grid, verbose = 3, cv=5, scoring='roc_auc',error_score=0,return_train_score=True)
clf.fit(X_train, y_train)

Наблюдения:

  • Используя C = 0,0001, мы получаем довольно хороший результат, поэтому мы используем C = 0,0001 для обучения нашей модели логистической регрессии.
  • Используя C = 0,01 и C = 0,1, производительность модели не сильно улучшается, поэтому мы не рассматриваем эти значения для C.
  • Со значением по умолчанию для max_iteration модель не смогла сойтись, использовалось max_iter = 1000

Обучение:

clf = LogisticRegression(max_iter = 10000,n_jobs=-1,verbose = 3,C = 0.0001)
clf.fit(X_train,y_train)
y_cv_pred = clf.predict(X_cv)
[Parallel(n_jobs=-1)]: Using backend LokyBackend with 2 concurrent workers.
[Parallel(n_jobs=-1)]: Done   1 out of   1 | elapsed:    2.2s finished

Результаты перекрестной проверки данных:

cm = confusion_matrix(y_cv, y_cv_pred)
print_confusion_matrix(y_cv,y_cv_pred)
print("ACCURACY SCORE-->",accuracy_score(y_cv, y_cv_pred))
sn.heatmap(cm/np.sum(cm), annot=True,fmt='.2%', cmap='Blues')
print(classification_report(y_cv,y_cv_pred))
True positive =  7370
False positive =  724
False negative =  70
True negative =  8166
ACCURACY SCORE--> 0.9513778322106552
              precision    recall  f1-score   support

         0.0       0.99      0.91      0.95      8094
         1.0       0.92      0.99      0.95      8236

    accuracy                           0.95     16330
   macro avg       0.95      0.95      0.95     16330
weighted avg       0.95      0.95      0.95     16330

7.3. Дерево решений с CV поиска по сетке

  • Для max_depth мы использовали max_depth = [1,2,5,10,20,30] для поиска наилучшего значения с помощью поиска по сетке.
# define models and parameters
model = DecisionTreeClassifier()
max_depth = [1,2,5,10,20,30]

# define grid search
grid = dict(max_depth=max_depth)
clf = GridSearchCV(estimator=model, param_grid=grid, verbose = 3, cv=5, scoring='roc_auc',error_score=0,return_train_score=True)
clf.fit(X_train, y_train)

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

Обучение:

clf = DecisionTreeClassifier(max_depth = 2)
clf.fit(X_train,y_train)
y_cv_pred = clf.predict(X_cv)

Результаты перекрестной проверки данных:

cm = confusion_matrix(y_cv, y_cv_pred)
print_confusion_matrix(y_cv,y_cv_pred)
print("ACCURACY SCORE-->",accuracy_score(y_cv, y_cv_pred))
sn.heatmap(cm/np.sum(cm), annot=True,fmt='.2%', cmap='Blues')
print(classification_report(y_cv,y_cv_pred))
True positive =  8088
False positive =  6
False negative =  27
True negative =  8209
ACCURACY SCORE--> 0.9979791794243723
              precision    recall  f1-score   support

         0.0       1.00      1.00      1.00      8094
         1.0       1.00      1.00      1.00      8236

    accuracy                           1.00     16330
   macro avg       1.00      1.00      1.00     16330
weighted avg       1.00      1.00      1.00     16330

7.4. Случайный лес с поиском по сетке CV

  • Для количества оценок мы использовали: n_estimators = [1,2,3,4,5,10,20,50]
# define models and parameters
model = RandomForestClassifier(random_state = 7)
n_estimators = [1,2,3,4,5,10,20,50]

# define grid search
grid = dict(n_estimators=n_estimators)
clf = GridSearchCV(estimator=model, param_grid=grid, verbose = 3, cv=5, scoring='roc_auc',error_score=0,return_train_score=True)
clf.fit(X_train, y_train)

  • Мы получаем довольно хороший результат с n_estimators равным 2.

Обучение:

clf = RandomForestClassifier(n_estimators = 2,random_state = 7)
clf.fit(X_train,y_train)
y_cv_pred = clf.predict(X_cv)

Результаты перекрестной проверки данных:

cm = confusion_matrix(y_cv, y_cv_pred)
print_confusion_matrix(y_cv,y_cv_pred)
print("ACCURACY SCORE-->",accuracy_score(y_cv, y_cv_pred))
sn.heatmap(cm/np.sum(cm), annot=True,fmt='.2%', cmap='Blues')
print(classification_report(y_cv,y_cv_pred))
True positive =  8092
False positive =  2
False negative =  24
True negative =  8212
ACCURACY SCORE--> 0.998407838334354
              precision    recall  f1-score   support

         0.0       1.00      1.00      1.00      8094
         1.0       1.00      1.00      1.00      8236

    accuracy                           1.00     16330
   macro avg       1.00      1.00      1.00     16330
weighted avg       1.00      1.00      1.00     16330

  • Хотя это дает нам достаточно приличные результаты, но производительность не намного улучшается, чем дерево решений.

7.5 Оценка модели и сравнение:

  • Точность перекрестной проверки для логистической регрессии составляет 95,1%.
  • Точность перекрестной проверки для дерева решений составляет 99,7%.
  • Точность перекрестной проверки для логистической регрессии составляет 99,8%.
  • Precision, Recall и F1 Score почти идеальны как для дерева решений, так и для случайного леса.
  • Поскольку дерево решений и случайный лес работают почти одинаково, мы будем использовать дерево решений в качестве окончательной модели из-за меньшей сложности и лучшей интерпретируемости.

Всю работу можно найти на гитхабе: https://github.com/sagardas-7/Credit-Card-Approval

8. Список преимуществ, проблем и ограничений адаптации AI/ML при одобрении кредитных карт

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

Каковы преимущества автоматизации в финансовом учреждении?

  1. Сокращение затрат
  2. Оптимизация операций
  3. Сохраняйте мотивацию сотрудников
  4. Оцифровка и структурирование данных
  5. Сокращение времени отклика бизнеса
  6. Обеспечьте лучшее обслуживание клиентов

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

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

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

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

Итак, в этом блоге представлены этапы реализации прогностической модели для утверждения кредитной карты. Типичные этапы профилактического обслуживания, такие как проектирование функций, маркировка, обучение и оценка, объясняются с использованием примеров наборов данных. Здесь также перечислены основные преимущества, ограничение списка различных проблем при адаптации AI / ML при одобрении кредитных карт в компаниях. Прогнозные модели с использованием техники машинного обучения могут быть построены как с использованием пакетов Python, так и с помощью сервисов облачных вычислений, предоставляемых Amazon Web Service (AWS), Google Cloud Platform (GCP), Microsoft Azure и т. д., что дает множество преимуществ.

9. Ссылки

Спасибо за ваше время.

Сагар Дас

[email protected]

https://www.linkedin.com/in/sagardas7/