Два разных подхода к одной и той же проблеме.

Добро пожаловать в мой последний проект для Udacity’s Data Scientist Nanodegree. Я переживаю смену карьеры, перехожу из академических кругов (у меня есть докторская степень по астрофизике) в промышленность, и эта нанодипломная степень - один из шагов, которые я делаю в этом направлении.

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

Цель

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

Данные

Данные включают 4 набора данных:

  • КЛИЕНТЫ: Демографические данные для клиентов компании по продаже товаров по почте в Германии, включают 3 столбца, которые предоставляют подробную информацию о клиентах (191 652 x 369).
  • AZDIAS: Демографические данные для населения Германии в целом (891 211 x 366).
  • MAILOUT-TRAIN: Демографические данные для целей маркетинговой кампании компании - Train Set, включают столбец ответа, в котором указано, стал ли каждый получатель клиентом компании (42 982 x 367).
  • MAILOUT-TEST: Демографические данные для целей маркетинговой кампании компании - Test Set (42 833x 366).

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

Преодоление данных

Мне пришлось много перебирать данные:

  1. Отбросьте лишние столбцы в данных CUSTOMERS.

Мы не используем эти данные.

2. Определите недостающие значения.

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

  • Все значения = -1 означают, что неизвестно.
  • Для 16 столбцов значение = 0 означает неизвестно.
  • Для 74 столбцов значение = 9 означает «неизвестно».
  • Для столбцов объекта значение = X или XX означает неизвестно.

Мне пришлось преобразовать все эти значения в NaN.

3. Удалите столбцы с большим количеством пропущенных значений.

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

В 6 столбцах пропущено более 50% значений. Мы отбрасываем эти столбцы.

4. Удалите строки с большим количеством пропущенных значений.

На следующем графике я показываю количество строк в соответствии с процентом отсутствующих данных:

В большинстве строк отсутствует менее 10% данных, мы сохраняем только эти строки.

5. Преобразуйте столбцы объекта в числовые.

У нас было шесть нечисловых столбцов:

  • На самом деле два числа, поэтому я их преобразовал.
  • Один из них - свидание. Я преобразовал столбец в тип datetime, а затем сохранил только год.
  • У одного только два значения. Я сопоставил их с 0 и 1.
  • Два оставшихся столбца были категориальными без порядкового номера, поэтому мне пришлось выполнить горячее кодирование с помощью метода Panda get_dummies ().

6. Заполните NaN.

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

7. Отбросьте столбцы с высокой степенью корреляции.

Следуя шагам здесь, я отбрасываю столбцы с корреляцией больше 0,95 в кадрах данных AZDIAS и CUSTOMERS.

8. Отбросьте столбец идентификатора.

Столбец id под названием LNR не представляет интереса для моделей.

Шаги 2–8 были реализованы в функции clean_data ().

9. Масштабируйте данные.

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

Выявление клиентских сегментов в общей популяции с помощью обучения без учителя.

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

  1. Анализ главных компонентов.

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

Я решил оставить 170 компонентов, на которые приходится около 80% совокупной объясненной дисперсии.

2. Кластеризация

Я выполнил кластеризацию K-средних. Сначала я взял только образец данных, чтобы соответствовать алгоритму с разным количеством кластеров. Я показываю результат на следующем графике:

Следуя методу локтя, я решил оставить 16 кластеров (я мог также выбрать 7 кластеров, но я решил использовать 16).

Затем я применил алгоритм K-средних с набором данных AZDIAS и предсказал номер кластера для каждой строки.

3. Данные клиентов

Я применил подобранный PCA со 170 функциями и подогнанные K-средние с 16 кластерами к данным CUSTOMERS, чтобы получить прогнозируемое количество кластеров для каждой строки.

Чтобы идентифицировать клиентские сегменты, мы должны сравнить кластеры:

Понятно, что подгруппа клиентов представлена ​​преимущественно кластерами 10, 12 и 2. Люди в этих трех кластерах являются целью компании. Какие основные компоненты (ПК) связаны с этими кластерами? И какие из них наиболее недопредставлены (13, 5, 6, 8)?

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

Провести исчерпывающий анализ ситуации действительно сложно, но можно сделать однозначный вывод:

Для ПК № 0 все недопредставленные кластеры имеют значение меньше 1, а перепредставленные - большее значение. Для ПК №1 происходит почти обратное.

Анализируя ПК № 0, мы видим, что он больше всего связан со столбцами: MOBI_REGIO, PLZ8_ANTG1, KBA13_ANTG1, KBA05_ANTG1, LP_STATUS_FEIN, KBA13_BAUMAX, HH_EINKOMMEN_SCORE, KBA13_ANTG4, KBA138_ANTG3, PLZ8.

В качестве примера посмотрим, какие значения в столбце MOBI_REGIO связаны с ПК № 0 ›1 (клиенты) и с ПК № 0‹ 1 (не-клиенты):

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

Повторив эту процедуру для остальных 9 столбцов, я обнаружил, что:

Заключение - Мы ищем людей с высоким доходом, высоким социальным статусом, малой мобильностью и микрорайоном с домами на 1–2 семьи.

Прогнозируйте вероятность ответа клиента с помощью контролируемого обучения

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

  1. Очистите данные поезда с помощью функции clean_data (), описанной на этапе обработки.
  2. Отделяйте объекты от цели. Целью является двоичная метка 0 или 1. Данные несбалансированы, как видно из следующего графика:

3. Масштабируйте функции с помощью StandardScaler ()

4. Обучите разные простые модели, чтобы увидеть, как они работают.

Я обучил 5 моделей и вычислил roc_auc. Я использовал эту метрику из-за несбалансированности данных (а также потому, что это метрика, используемая в соревновании Kaggle для проверки моих результатов).

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

5. Ищите лучшие параметры

Я просканировал следующее пространство параметров с помощью GridSearchCV.

param_grid = {'max_depth': [3,4,5],
             'loss':['deviance', 'exponential'],
             'n_estimators': [100, 150, 200]}

Я обнаружил, что лучшими параметрами были max_depth = 4, loss = deviance (по умолчанию) и n_estimators = 100 (по умолчанию), а ROC_AUC = 0,779.

6. Предскажите метки для тестовых данных.

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

Я предсказал вероятности для меток (поскольку мы используем roc_auc, нас не интересуют точные значения) с помощью метода pred_proba подобранной наилучшей модели.

7. Загрузите результаты в Конкурс Kaggle.

Я получил 0,77698 и 91-е место на момент подачи заявки.

Выводы

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

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

Модель с учителем была сложнее, мне приходилось тестировать разные модели и искать лучшие параметры. После загрузки моих результатов в Kaggle я получил 0,77698. Я доволен этим результатом, но знаю, что есть возможности для улучшения.

Что я могу сделать, чтобы улучшить модель?
- Разработайте некоторые функции: например, я могу преобразовать переменную года в сегменты
- Заполнить NaN средним значением или другим методом
- Проверить еще классификаторы или большее пространство параметров

У тебя есть другие идеи?