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

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

Цель этого проекта - разработать такую ​​эффективную прогностическую модель, используя данные, полученные от клиентов Банка Португалии.

Описание набора данных

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

1 - возраст (числовой)

2 - работа: тип работы (категориальные: «админ», «рабочий», «предприниматель», «домработница», «менеджмент», «пенсионер», «самозанятый», «услуги», «студент». , «техник», «безработный», «неизвестный»)

3 - семейное положение: семейное положение (категориальное: «разведен», «женат», «холост», «неизвестен»; примечание: «разведен» означает разведенный или вдовец)

4 - образование (категориальное): 'basic.4y', 'basic.6y', 'basic.9y', 'high.school', 'неграмотный', 'professional.course', 'университет. степень ’,’ неизвестно ’)

5 - дефолт: есть кредит в дефолте? (категорично: «нет», «да», «неизвестно»)

6 - жилье: есть жилищный кредит? (категорично: «нет», «да», «неизвестно»)

7 - кредит: есть ли личный заем? (категорично: «нет», «да», «неизвестно»)

Следующее относится к последнему контакту текущей кампании.

8 - контакт: контактный вид связи (категориальный: «сотовый», «телефон»)

9 - month: месяц последнего контакта в году (категориальные: «янв», «фев», «мар»,…, «ноя», «декабрь»)

10 - day_of_week: последний контактный день недели (категориальный: «пн», «вт», «ср», «чт», «пт»)

11 - duration: длительность последнего контакта, в секундах (числовое значение). Важное примечание: этот атрибут сильно влияет на цель вывода (например, если длительность = 0, то y = ’no’). Тем не менее, продолжительность вызова до выполнения вызова неизвестна. Также после окончания звонка становится известно y. Таким образом, эти входные данные следует включать только для целей эталонного тестирования и от них следует отказаться, если предполагается получить реалистичную прогностическую модель.

# другие атрибуты:

12 - кампания: количество контактов, выполненных во время этой кампании и для этого клиента (числовое, включает последний контакт)

13 - days: количество дней, прошедших с момента последнего обращения к клиенту из предыдущей кампании (числовое значение; 999 означает, что с клиентом ранее не обращались)

14 - предыдущий: количество контактов, выполненных до данной кампании и для этого клиента (числовое значение)

15 - результат: результат предыдущей маркетинговой кампании (категориальный: «неудача», «несуществующий», «успех»).

# Ниже приведены атрибуты социально-экономического контекста.

16 - emp.var.rate: уровень вариации занятости - квартальный показатель (числовой) 17 - cons.price.idx: индекс потребительских цен - месячный показатель (числовой)

18 - cons.conf.idx: индекс доверия потребителей - месячный индикатор (числовой)

19 - euribor3m: ставка Euribor на 3 месяца - дневной индикатор (числовой)

20 - кол-во занятых: количество сотрудников - квартальный показатель (числовой) Выходная переменная (желаемая цель):

21-й - подписался ли клиент на срочный вклад? (двоичный: «да», «нет»)

Описание используемых классификаторов

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

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

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

Многослойный персептрон - это класс искусственных нейронных сетей с прямой связью (ИНС).

Ссылка на GitHub

Https://github.com/nahomneg/Bank-Institution-Term-Deposit-Predictive-Model/

Класс обработки данных

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

@author: Nahom Negussie

Класс моделирования

Этот класс занимается созданием классификаторов, созданием каналов, k-кратным разбиением и сравнением доступных классификаторов.

Пояснительный анализ данных

Импортируйте необходимые модули и библиотеки

# import the neccesary libraries
import pandas as pd
import seaborn as sb
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
from sklearn import preprocessing
from itertools import islice
import seaborn as sns
from scipy.stats import binom
from scipy.stats import norm
import statsmodels.stats.api as sms
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn import preprocessing
# import preprocessor and modelling classes
import data
from model import Model

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

#load the data set
data_frame = pd.read_csv("dataset/bank-additional-full.csv",sep=';'  , engine='python')
# initialize the modelling and preprocessing classes
processor = data.PreProcessing(data_frame)
model = Model()

Классовый дисбаланс

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

Чтобы выяснить, не являются ли данные жертвой дисбаланса классов, я использовал метод plot_target_imbalance () из класса PreProcessing.

# use the plot_target_imbalance method from the PreProcessing class processor.plot_target_imbalance()

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

Выбросы

Чтобы идентифицировать столбцы с выбросами, я использовал функцию detect_outliers_boxplot () из класса PreProcessing и передал ей числовые столбцы.

processor.detect_outliers_boxplot(['duration','age','cons.conf.idx','euribor3m'])

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

Разница медиан b / n между yes и no для euribor3m показывает, что это разделительный класс.

Приведенные выше графики показывают, что продолжительность и возраст имеют значительное количество выбросов. Я использовал метод handle_outliers () из класса PreProcessing, чтобы заменить выбросы соответствующими медианами.

processor.handle_outliers(['duration','age','cons.conf.idx'])

Влияние категориальных переменных на цель

Затем я визуализировал влияние каждой категориальной переменной на целевую переменную («y»).

Я передал несколько категориальных переменных в plot_multiple_categorical_against_target () из класса PreProcessing.

# use the plot_multiple_categorical_against_target method of the PreProcessing class
# to plot the count of each categorical variable with the target as a hue
processor.plot_multiple_categorical_against_target(['poutcome','marital','loan','housing'])

processor.plot_single_categorical_against_target('education')

processor.plot_single_categorical_against_target('day_of_week')

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

Влияние числовых переменных на цель с помощью гистограмм.

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

Графики распределения

Затем я изучил распределение числовых столбцов, используя метод plot_distribution () и передав ему некоторые числовые переменные.

processor.plot_distribution(['age','duration','campaign','emp.var.rate','euribor3m'])

Корреляция b / n числовых переменных

Функции emp.var.rate, cons.price.idx, euribor3m и nr.employed имеют очень высокую корреляцию. Самая высокая корреляция между euribor3m и числом занятых составляет 0,95!

Функциональная инженерия

Я извлек новую функцию «Год» из столбца месяца, используя метод assign_years () из класса PreProcessing.

# create a new feature 'Year' using assign years method
processor.assign_years()
processor.data_frame.sample(10)

Единое горячее кодирование и стандартизация

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

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

Я предпочел стандартизацию нормализации, потому что отклонения набора данных от среднего несколько скомпрометированы при использовании нормализации, которая пытается соответствовать данным b / n 0 и 1.

Колоночные трансформаторы и трубопроводы

Недавнее дополнение к Scikit-learn - это класс Column Transformers, который позволяет указывать различные преобразования для каждого столбца, делая предварительную обработку намного менее утомительной (и намного более легкой для чтения!). В этом случае применяются следующие преобразования: One Hot Encoding и Standardization.

Как следует из названия, конвейеры позволяют объединить несколько процессов, преобразователь столбцов и модель машинного обучения в один модуль оценки scikit-learn. В конвейерах есть метод подгонки, прогнозирования и оценки, как и в любом другом оценщике.

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

#a column transformer that handles both one hot encoding and standardization
column_transformer = processor.get_column_transformer(categorical_columns,numerical_columns,['duration','day_of_week'])

Перед созданием конвейера мне пришлось добавить классификаторы, которые будут передаваться конвейеру вместе с преобразователем столбцов. Чтобы добавить классификаторы, я использовал функцию add_model () класса Model.

# add 4 classifier models to be compared
model.add_classifier(model.get_random_forest_classifier(),'Random Forest')
model.add_classifier(model.get_logistic_classifier(),'Logistic Regressor')
model.add_classifier(model.get_xgboost_classifier(),'XGBoost')
model.add_classifier(model.get_multi_perceptron(),'MLP')
#create a pipeline using the transformer and the above classifiers
model.create_pipes(column_transformer)

Разделение данных, K-Fold и перекрестная проверка

Перекрестная проверка - важный инструмент в наборе инструментов Data Scientist. Это позволяет лучше использовать данные. Обучающий набор используется для обучения модели, а набор проверки используется для проверки ее на данных, которые она никогда раньше не видела. Я использовал следующие варианты K-кратности, чтобы придумать наборы для обучения и проверки.

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

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

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

Я разделил данные на наборы для обучения, тестирования и перекрестной проверки на 64%, 20% и 16% соответственно. Набор для проверки отделяется от данных обучения, которые изначально составляли 80%, с использованием K-Fold. Для этого я использовал класс модели.

#train_test split in 80:20 ratio
X_train,X_test,y_train,y_test=  processor.train_test_split()
#use K-fold to split the training data in 80:20 ratio
kfold = model.get_cross_validation_splitter(is_strattified = False)

Сравнение моделей

Я использовал метод compare_models () класса модели, чтобы сравнить 4 классификатора, используя 5 кратных оценок и взяв их средний балл на основе различных показателей оценки.

Я использовал LabelBinarizer, чтобы сообщить классификатору, какой класс целевой переменной (да или нет) является положительным и отрицательным. Метод compare_models должен знать, какой класс положительный, а какой отрицательный, чтобы сравнивать классификаторы на основе отзыва, точности и f1_score.

# Label Binarizer to identify which target class is positive
lb = preprocessing.LabelBinarizer()
y_train = np.array([number[0] for number in lb.fit_transform(y_train)])

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

#compare the models based on roc_auc
models_k_fold = model.compare_models(kfold , X_train, y_train,scoring = 'roc_auc')
#compare the models based on accuracy
models_k_fold_accuracy = model.compare_models(kfold , X_train, y_train,scoring='accuracy')
#compare the models based on recall
models_k_fold_recall = model.compare_models(kfold , X_train, y_train,scoring='recall')
#compare the models based on precision
models_k_fold_precision = model.compare_models(kfold , X_train, y_train,scoring='precision')
#compare the models based on f1_score
models_k_fold_f1 = model.compare_models(kfold , X_train, y_train,scoring='f1')

Метод compare_models () класса модели возвращает средние оценки (из пяти) вместе с именем классификатора. Я использовал возвращенные данные для создания таблицы, в которой показаны оценки классификаторов на основе различных показателей.

#create a performance for each criteria based on the different metrics
classifiers = models_k_fold['classifiers']
scores_auc = models_k_fold['scores']
scores_accuracy = models_k_fold_accuracy['scores']
scores_recall = models_k_fold_recall['scores']
scores_precision = models_k_fold_precision['scores']
scores_f1 = models_k_fold_f1['scores']
data = {'Classifier':classifiers , 'Auc':scores_auc, 'Accuracy': scores_accuracy,
        'Recall':scores_recall, 'Precision':scores_precision }
#change the dictionary to data frame
performance_df = pd.DataFrame(data)
performance_df = performance_df.set_index('Classifier')
performance_df

#create a stratified k-fold by passing True to is_strattified 
kfold = model.get_cross_validation_splitter(is_strattified = True)

В приведенных выше таблицах приведены средние показатели эффективности каждого классификатора на основе различных показателей для каждого типа K-Fold. Из приведенной выше таблицы видно, что оценки обоих типов K-Fold примерно одинаковы, но всегда лучше полагаться на метод Stratified K-Fold для наборов данных с высоким классовым дисбалансом, например, ниже рассмотрение здесь.

Каждый из приведенных выше показателей лучше подходит для разных ситуаций.

Выбор оценочной метрики

  1. Точность - количество сделанных правильных прогнозов как отношение ко всем сделанным прогнозам.
  2. ROC - рассчитывается путем построения графика зависимости истинно положительного (TPR) показателя от ложноположительного (FPR) при различных настройках пороговых значений. Площадь под кривой - это ROC_Score.
  3. Напомнить - количественно определяет количество обнаруженных истинных положительных результатов.
  4. Точность - количественно определяет количество положительных прогнозов класса, которые фактически принадлежат к положительному классу.

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

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

ROC может достичь этого, рассматривая как истинную положительную частоту (TPR), так и ложную положительную скорость (FPR). Мы получим высокий ROC, если TPR и FPR будут выше случайной линии.

Глядя на обе таблицы, я заметил, что XGBoost - лучший результат согласно ROC_AUC с оценкой около 0,764.

Заключение

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

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

После EDA набор данных был предварительно обработан с использованием быстрого кодировщика для категориальных переменных, тогда как StandardScaler использовался для числовых столбцов.

Затем я создал конвейеры, состоящие из 4 классификаторов, для сравнения с помощью K-Fold и перекрестной проверки.

Я выбрал ROC_AUC как наиболее надежную метрику оценки из-за ее устойчивости к дисбалансу классов. По показателю ROC_AUC классификатор XGBoost вышел на первое место с оценкой около 0,76.

Благодарность

Я собрал это как часть пакета 3 тренинга 10academy.org и хотел бы выразить свою благодарность всем моим однокурсникам и сотрудникам за их поддержку.

использованная литература

[1]: Тереза ​​Фауэрбак h. (16 апреля 2017 г.). Данные более ценны, чем нефть, в сегодняшней экономике данных

Https://www.northridgegroup.com/blog/more-valuable-than-oil-data-reigns-in-todays-data-economy/#:~:text=Oil%20has%20reigned%20for%20centuries,it % 2C% 20is% 20 потенциально% 20more% 20цена .