Путешествие новичка в проект Udacity Data Science Nanodegree Capstone

Проект Starbucks Capstone:

В этой статье подробно рассказывается о главном проекте программы Udacity Data Science Nanodegree, который содержит смоделированные данные, содержащие сведения о портфеле предложений, данные профиля клиента и стенограммы взаимодействий из мобильного приложения Starbucks rewards.

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

Пожалуйста, смотрите Блокнот в начальном разделе (1 Введение в Udacity) для получения более подробной информации от Udacity о проекте.

План этой статьи:

  1. Данные
  2. EDA (исследовательский анализ данных)
  3. Предварительная обработка / Инжиниринг
  4. Моделирование
  5. Проблемы и выводы

Возможные бизнес-вопросы:

  1. Какие предложения и типы предложений наиболее эффективны и почему?
  2. Какие демографические группы можно выделить в зависимости от реакции на предложения?
  3. И наоборот, какие предложения / демографические данные не работают / не отвечают?
  4. Если можно создать подходящую модель, к какой метрике следует обратиться для оптимизации?

Цель проекта / Краткое описание решения:

  1. Обработайте данные и начните создавать продукт (DataFrame), который можно использовать для моделирования
    - У нас есть несколько наборов данных со значениями, которые необходимо изменить / скорректировать
    - Тогда нам придется присоединиться к ним наборы данных вместе, чтобы получить коррелированную информацию
  2. Разработайте продукт, чтобы указать или создать функции, которые сделают возможным успешное моделирование.
    -Многие функции являются информативными, но, возможно, изначально не имеют прогнозной информации. Нам нужно будет улучшить продукт, чтобы обеспечить более точную прогнозирующую информацию среди функций.
  3. Создайте модель
    - Это контролируемая задача машинного обучения для классификации
    - Вероятно, будет дисбаланс в целевой переменной, поэтому нам нужно будет устранить дисбаланс либо в данных обучения, либо в классификаторе .
    - У нас есть возможность использовать множество вариантов, включая классификаторы ансамбля и классификаторы повышения градиента.
  4. Установите и оцените модель / Настройте модель для достижения наилучших характеристик

Данные

Данные для этого проекта состояли из 3 разных файлов .json: портфолио .json, профиль .json и транскрипт .json.

Portfolio.json

Первый файл - портфолио.json, который содержит идентификаторы предложения и метаданные (вознаграждение, каналы, сложность, тип предложения).

Profile.json

Второй файл - profile.json, который содержит демографические данные по идентификатору (пол, возраст, имя_члена, доход).

Transcript.json

Последний файл - transcript.json, который содержит записи по идентификатору события, значения и времени (время записи этого исследования).

Обрабатываемые данные:

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

  1. Набор данных портфель разделяет тип предложения и каналы на фиктивные переменные, которые объединяются с исходным фреймом данных портфеля. Столбцы переименованы для удобства визуального распознавания.
  2. Фрейм данных профиля «стал_частником» преобразуется в формат даты и времени. Столбцы переименованы для облегчения визуального распознавания и объединения.
  3. Фрейм данных расшифровка обрабатывается для анализа столбца «значение» на предмет «сумма» и «идентификатор предложения / идентификатор предложения», которые разбираются в свои собственные столбцы.
  4. расшифровка и фреймы данных профиля объединяются для включения всех значений.
  5. Объединенный фрейм данных из предыдущего шага объединяется с фреймом данных портфолио для включения всех значений.
  6. столбцы: 'customer_id', 'event', 'time', 'amount', 'offer_id',
    'event_instance_days', 'пол', 'возраст', 'стал_частником_on', 'доход',
    «offer_reward», «channels», «offer_difficulty», «offer_duration»,
    «offer_type», «offer_type__bogo», «offer_type__discount»,
    «offer_type__informational», «channels_email», «channels_mobile»,
    'каналы_социальные', 'каналы_веб'

Из этого обработанного набора данных мы можем эффективно исследовать данные.

EDA (исследовательский анализ данных)

Во-первых, взгляните на предложения и типы предложений:

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

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

Из трех типов предложений (дисконтное, BOGO и информационное) мы можем сделать несколько наблюдений:

  1. В настоящее время нет возможности окончательно утверждать, что какая-либо транзакция связана с информационным. Как видно на изображении выше, с ним не связаны завершенные значения предложения.
  2. Предложения типа скидки и предложения типа BOGO имеют одинаковое количество записей «полученное предложение», но предложения со скидкой имеют меньшее количество «просмотренных» предложений и еще большее количество завершенных предложений.
  3. Некоторые интересные наблюдения можно сделать в отношении отдельных предложений по количеству «просмотренного предложения» / «завершенного предложения». Например, для предложения «2906b8» не было наибольшего количества «завершенных предложений» для типов предложений со скидкой, но у него было почти такое же количество «завершенных предложений» и «просмотренных предложений». Такое наблюдение показывает, что это конкретное предложение может быть более эффективным, чем другие.
  4. Достаточно интересно, что у предложения «0b1e1539» больше «завершено», чем «просмотрено». Это подтверждает, что предложение может быть выполнено, даже если оно не было просмотрено ». Возможно, еще слишком рано говорить об этом конкретном предложении, но само предложение может быть достаточно привлекательным, чтобы работать хорошо, не вызывая отклика.

Что касается другого второго основного бизнес-вопроса, давайте посмотрим на демографические группы:

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

Эта визуализация помогает сделать более очевидным сравнение суммы «предложение выполнено».

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

Из этой визуализации мы видим, что «0b1e1» и «2906b» из типов скидок и «9b98b» из типов BOGO, как правило, содержат больше «завершенных предложений» независимо от группы «Пол». Единственный общий фактор (на первый взгляд) в том, что продолжительность больше для всех 3 (7–10 дней).

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

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

На последнем графике мы видим, что мужчины из корзины самого молодого возраста и корзины с самым низким доходом получили наибольшее количество предложений (4664 предложения), но завершили только 1495 предложений - 32% возможных взаимодействий с предложениями (завершенное предложение разделено на полученное предложение). ). Для сравнения, женщины из корзины «Самый высокий доход» из корзины самого старшего возраста имели 61% возможное взаимодействие.

Предварительная обработка / Инжиниринг

До сих пор большая часть данных обозначалась как «возможное взаимодействие» или «связанные / влияние». Но есть еще один аспект данных, который еще не изучен - временность.

Каждое «событие» помечается значением в столбце «время», которое определяется как количество времени, прошедшее с момента начала исследования.

Мы не можем идентифицировать каждое событие «предложение завершено» как эффективное влияние предложения, если только оно не произошло в логической последовательности событий (предложение получено - предложение просмотрено - предложение завершено). Значения «Предложение выполнено» могут появляться до просмотра, указывая на то, что предложение не повлияло на взаимодействие с клиентом.

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

так что в псевдокоде:

((row[offer completed][time] - row[offer received][time]) < offer_duration)
& (row[offer completed][time] > row[offer viewed][time]

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

Это дает нам что-то вроде:

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

Теперь есть несколько проблем, созданных для достижения этой цели:

Значения «Тип предложения» для «информационного» не регистрируют событие «предложение выполнено» со значением «время». Свобода была принята в предположении, что если человек получал, то просматривал информационное предложение, что приводило к транзакции в течение того же периода времени - это, вероятно, из-за влияния информационного предложения.

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

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

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

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

Моделирование

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

  1. Масштабирование / нормализация
  2. Выбор функции
  3. PCA
  4. Передискретизация / комбинация (передискретизация / недостаточная выборка)

Масштабирование / нормализация:

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

Выбор функции:

Маловероятно, что все функции в равной степени способствуют корреляции или прогнозной информации. На этом этапе мне очень понравился и я использовал пакет Python xverse для его метода Weight of Evidence.

PCA:

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

Передискретизация / комбинация (передискретизация / недостаточная выборка):

В целом набор данных немного несбалансирован в пользу значения «offer_valid», равного «0». Хотя некоторые модели отлично справляются с дисбалансом или специально устраняют дисбаланс (например, imbalanced-learn или imblearn python намеревается выполнить), синтетическая передискретизация класса меньшинства может помочь улучшить производительность модели в отношении желаемой метрики. Я сравнил модели, направленные на устранение дисбаланса, и SMOTE (S синтетический M inority O против выборки TE chnique) и нашел результаты быть сопоставимым.

Мой дизайн входных данных:

В конечном итоге, путем тщательного тестирования всех возможных комбинаций выбора функций, PCA и передискретизации / комбинированной выборки; Я обнаружил, что наиболее подходящим дизайном был следующий:

  1. Выбор функций:
    - Многие функции имеют несбалансированное распределение. это заставило модель предположить, что клиенты, которые стали участниками в 2016 году, были более важными (было значительное количество клиентов, которые присоединились в 2016 году чаще, чем раз в два года)
    - Когда что-то вроде member_start_date закодировано для лет начала , это придает модели множество «отвлекающих маневров». Поскольку модель будет думать, что 2016 год очень важен, она попытается использовать функцию, которая может давать и давала низкую производительность, поскольку она не очень связана с нашей проблемой действительного влияния предложений на демографию.
  2. PCA:
    - Изначально я думал, что PCA будет хорошим способом решить проблему нехватки информации для прогнозирования в функциях, когда они построены в очень широкомасштабном продукте. Как оказалось, я не мог легко заставить метод PCA понять, какую группу функций следует правильно декомпозировать, и производительность модели резко упала.
  3. Передискретизация / Комбинация (Передискретизация / Недостаточная выборка):
    - Использование SMOTE () оказалось очень эффективным в балансировании производительности модели, тогда как использование таких комбинаций, как SMOTETomek, не помогло. Я предполагаю, что сам набор данных недостаточно велик или недостаточно несбалансирован для использования комбинированной выборки
    - Хотя синтетическая выборка доказала свою эффективность, она также решается и эффективна при настройке class_weight или использовании BalancedRandomForestClassifer из imblearn

Дизайн моей модели:

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

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

С помощью исследований, чтения и аналогичных средств тестирования (улучшения графиков / настройки) я закончил тестирование:

  1. RandomForestClassifier
  2. AdaBoostClassifier
  3. GradientBoostingClassifier
  4. ExtraTreesClassifier
  5. KNeighborsClassifier
  6. RidgeClassifierCV
  7. Логистическая регрессия
  8. Сбалансированный
  9. СбалансированныйСлучайныйЛесКлассификатор
  10. XGBClassifier
  11. ЛГБМ-классификатор
  12. CatBoostClassifier

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

Некоторые из них показали немного худшую производительность по сравнению с чем-то похожим (BalancedRandomForestClassifier против BalancedRandomForestClassifier, BalancedRandomForestClassifier в целом показал лучшие результаты в нескольких тестах).

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

Разработка дизайна модели:

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

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

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

Метрики

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

А. Точность

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

B. Напомним

Recall покажет нам все соответствующие случаи в нашем наборе данных.

Например, это построенная матрица путаницы GradientBoostingClassifier с точностью 70%.

Хотя получение более высокой точности желательно, какой бизнес-вопрос и случай, который мы должны стремиться решить?

Является ли отправка предложений неотзывчивым клиентам дороже? Влияет ли получение нежелательных предложений на их лояльность?

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

С помощью различных методов тестирования моделей моей последней моделью стал StackingClassifier, который состоит из ExtraTreesClassifier, GradientBoostingClassifier, XGBClassifier, KneighborsClassifier, RidgeClassifierCV и, наконец, BalancedRandomForestClassifier.

При необходимости каждый отдельный классификатор был настроен с использованием настройки гиперпараметров RandomizedSearchGrid.

Настройка общих параметров моей модели:

Веса классов были своего рода «уравновешивающим» действием с использованием методов с передискретизацией в сочетании. Но даже при небольшой настройке (+/- 0,01) отзыв / точность могут резко измениться.

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

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

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

Оценка / проверка модели:

моей последней моделью был уже упомянутый StackingClassifier.

Я выбрал это, потому что считал, что определение действительного влияния предложения на демографическую группу будет наиболее выгодным коммерческим использованием, но может потребовать различных комбинаций сильных сторон оценщиков. Изначально я использовал KNeighborsClassifier и RandomForestClassifier и просто расширил эти возможности, включив в них оценки Gradient Boosting и Extra Trees / Balanced Forest.

Базовыми оценщиками были ExtraTreesClassifier, GradientBoostingClassifier, XGBClassifier, KNeighborsClassifier, RidgeClassifierCV, BalancedRandomForestClassifier. Это довольно широкий ансамбль, но, за исключением незначительных изменений, производительность осталась примерно такой же с аналогичными комбинациями (за исключением RidgeClassifier / ExtraTreesClassifier, выбор только GradientBoostingClassifier или XGBClassifier и т. Д.).

Последним оценщиком был XGBClassifier, который, казалось, показал лучшие результаты при тестировании, чем стандартный LogisticRegression.

StackingClassifier имеет встроенную стратегию разделения с перекрестной проверкой для обучения final_estimator. По умолчанию используется 5-кратная перекрестная проверка, поскольку увеличение до 10-кратной разницы не дало.

Моя последняя модель производительности:

accuracy_score: 75.98336889326549%
f1_score: 70.60792715586503%
recall_score: 74.5089727285573%
precision_score: 67.09505026084743

Проблемы и выводы

Проблемы:

В этом процессе, безусловно, были некоторые проблемы, которые необходимо решить.

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

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

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

Я пробовал реализовать классификатор опорных векторов (SVC), понимая, что SVM (машины опорных векторов) может эффективно обрабатывать данные большой размерности, однако время подгонки было значительным. длинная. Мне удалось протестировать значения по умолчанию и некоторые незначительные настройки, но производительность была немного ниже, чем у StackingClassifier, и время настройки было слишком дорогостоящим. Я бы рассмотрел возможность дальнейшего тестирования либо отдельно, либо в качестве замены StackingClassifier.

Я также пробовал LightGBM и CatBoost в качестве других классификаторов Gradient Boosting с их уникальными подходами к эффективности, выводам и обработке категориальных значений. Хотя мне очень понравились расширенные возможности и функции обоих, они, в конечном итоге, не улучшили StackingClassifer, ни сами по себе, ни в других комбинациях.

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

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

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

Большое спасибо за ваше время и внимание!