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

Это был конкурс Starbucks Capstone Challenge для Data Scientist Nano Degree в Udacity. Я получил набор данных от программы, которая создает данные, моделирующие, как люди принимают решения о покупке и как рекламные предложения влияют на эти решения. Я хотел узнать, каковы основные факторы привлекательного предложения в приложении Starbucks, а также предсказать, примет ли пользователь предложение, если будут предоставлены данные, а именно характеристики предложения и демографические данные пользователей?

Бизнес-понимание:

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

Мне было интересно ответить на следующие два вопроса:

Каковы были основные факторы привлекательного предложения в приложении Starbucks?

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

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

Данные содержались в трех файлах:

Portugal.json — содержит идентификаторы предложений и метаданные о каждом предложении (длительность, тип и т. д.).

profile.json — демографические данные по каждому клиенту

Transcript.json — записи для «транзакций», «полученных предложений», «просмотренных предложений» и «завершенных предложений».

Вот схема и объяснение каждой переменной в файлах:

portfolio.json

  • id (string) — id оффера
  • offer_type (string) — тип предложения, т.е. BOGO, дисконтное, информационное
  • сложность (int) — минимальная сумма, необходимая для завершения предложения
  • вознаграждение (инт) — плата, которая была дана за выполнение предложения
  • duration (int) — время открытия оффера, в днях
  • каналы (список строк)

profile.json

  • age (int) — возраст клиента
  • стал_member_on (целое число) — дата, когда клиент создал учетную запись приложения.
  • гендер (str) — пол клиента (обратите внимание, что некоторые записи содержат «O» вместо M или F)
  • id (str) — идентификатор клиента
  • доход (float) — доход клиента

транскрипт.json

  • event (str) — описание записи (т. е. транзакция, полученное предложение, просмотренное предложение и т. д.)
  • person (str) — идентификатор клиента
  • time (int) — время в часах с начала теста. Данные начинаются в момент времени t = 0
  • value — (dict of strings) — либо идентификатор предложения, либо сумма транзакции в зависимости от записи

Определен подход к предварительной обработке данных для модели:

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

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

Во-первых, я изучил, какие события были в каждом типе предложения.

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

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

Для BOGO и предложения со скидкой эффективное предложение будет определено, если следующие события будут записаны в правильной последовательности во времени:

предложение получено -› предложение просмотрено -› транзакция -› предложение выполнено

Между тем, для информационного предложения, поскольку с ним было связано событие «Предложение выполнено», я должен был бы определить транзакции как преобразование в эффективное предложение:

предложение получено -> предложение просмотрено -> транзакция

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

Для предварительной обработки данных были предприняты следующие шаги:

  • Идентификаторы предложений, назначенные транзакциям

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

1. Люди, на которых повлияли и успешно конвертировали — эффективные предложения:

- предложение получено -> предложение просмотрено -> транзакция -> предложение завершено (BOGO/дисконтные предложения)

- предложение получено -› предложение просмотрено -› транзакция (информационные предложения — должны быть в пределах срока действия предложения)

2. Люди, которые получили и просмотрели оффер, но не конвертировались — неэффективные офферы:

предложение получено -> предложение просмотрено

3. Люди, купившие/выполнившие предложения вне зависимости от осведомленности о каких-либо предложениях:

- транзакция

- предложение получено -› транзакция -› предложение завершено -› предложение просмотрено

- транзакция -› предложение получено -› предложение завершено -› предложение просмотрено

- предложение получено -› транзакция -› предложение просмотрено -› предложение выполнено

- предложение получено -› транзакция (информационные предложения)

- предложение получено -› транзакция -› предложение просмотрено (информационные предложения)

4. Люди, которые получили предложения, но не предприняли никаких действий:

предложение получено

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

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

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

  • Определено целевое переменное эффективное предложение
  • Помеченные транзакции и предложения, завершенные после просмотра предложений
  • Учитывается продолжительность/действительность предложений в конверсионных продажах от информационных предложений

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

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

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

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

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

Со столбцами флагов valid_completed и valid_completed_duration у меня было четыре возможных сценария для информационного предложения в наборе данных расшифровки_информации:

Следуя приведенным выше сценариям, только Сценарий 3 будет считаться моим ярлыком Effective_offers = 1 для информационных предложений (группа клиентов 1).

Между тем, сценарии 1 и 2 можно рассматривать как действия, которые помещают клиента в мою группу 3 клиентов — людей, которые купили/выполнили предложения, независимо от осведомленности о каких-либо предложениях.

Для клиентов в Сценарии 1, несмотря на то, что, согласно моему флагу valid_completed, они просматривали предложение перед транзакцией, но не в течение срока действия. Таким образом, предложение не повлияло на них.

Между тем, для клиентов в Сценарии 2 они были в группе 3, так как они совершали транзакции, не просматривая предложение.

Сценарий 4 можно отнести к группе 4, так как они состояли только из транзакций.

Мне нужно было выделить этих пользователей в группу 2 — тех, кто, возможно, получил и просмотрел предложение, но после этого никаких транзакций. Мне нужно было разделить те, где Effective_offer != 1, на группы 2, 3 и 4.

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

От остальных людей я разделил его на группы 2 и 4. Я использовал шаги, аналогичные тем, что я делал с предложениями BOGO и Discount, поскольку я не учитывал продолжительность.

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

Я объединил наборы данных вместе, чтобы сделать набор данных offer_info готовым к моделированию.

Я разделил все свои наборы данных на эффективные и неэффективные предложения в зависимости от типа предложения; Я соответственно добавил наборы данных в наборы данных для моделирования.

  • Разработка функций
  • Стабил_member_on столбец, который нужно спроектировать
  • Количество полученных предложений

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

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

Выполнение:

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

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

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

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

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

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

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

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

Реализация модели:

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

Во-первых, я определил свою цель и переменные функции.

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

Я определил функции для запуска моей модели, так как планировал реализовать три разные модели; следовательно, было бы легче реализовать повторно. Как было сказано выше, я планировал сравнить оценку f1 с оценкой точности как лучший показатель производительности модели, тем более что классы для BOGO и предложений скидок были неодинаковыми.

BOGO предлагает модель:

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

Точность модели случайного лесного классификатора (RF) немного превзошла модель классификатора дерева решений (DT). Тем не менее, в целом производительность обеих моделей была примерно одинаковой (82,14% против 81,77% соответственно с точки зрения точности). Точность для первой попытки была неплохой, более 80%. Я бы попытался настроить модель дальше, чтобы повысить эффективность.

Однако с точки зрения оценки F1 обе модели были ниже 80%, при этом модель случайного леса работала хуже по сравнению с классификатором дерева решений, с 75,91% по сравнению с. 79,63%.

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

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

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

Учитывая этот случай, я бы все равно выбрал модель RF.

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

Модель со скидкой:

Я повторил те же шаги, что и выше, но с набором данных offer_discounts.

На этот раз модель классификатора случайного леса имела такую ​​же производительность по сравнению с классификатором дерева решений с точки зрения точности (87,23%), но оценка f1 была ниже для DT (81,43% против 81,28%).

Оценка f1 для этих моделей в целом была ниже по сравнению с оценкой точности. Это может указывать на то, что в некоторых случаях обе модели ошибочно классифицировали отрицательные случаи (efficient_offer = 0). Опять же, меня это не слишком беспокоило, так как меня больше интересовала модель, точно предсказывающая положительные случаи, поэтому вместо этого я бы выбрал модель с более высокой точностью, где показатель f1 для случаев Effective_offer = 1 был выше, для чего мой классификатор DT имел лучшую производительность. (0,9318 против 0,9317).

Модель информационных предложений:

Производительность этих моделей была хуже по сравнению с двумя другими наборами данных с точностью ниже 80% для обеих моделей, но модель RF по-прежнему работала лучше. Оценка f1 также была хуже: 67,54% RF Classifier, что хуже, чем у модели DT (68,04%).

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

Уточнение:

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

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

Поиск по сетке для определения оптимальных параметров:

Я решил провести GridSearch, чтобы определить оптимальные параметры модели.

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

У меня были оптимальные параметры для модели BOGO. Я перезапустил свою модель с новыми параметрами, сохранив базовую модель DecisionTree с теми же настройками для сравнения.

Точность модели RF немного увеличилась — с 82,14% до 82,51%, а показатель f1 увеличился с 75,91% до 77,64%. Это был хороший прирост производительности, но минимальный, что указывало на то, что, возможно, мало что можно было сделать для улучшения производительности модели с настройкой параметров.

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

Точность дисконтной модели немного увеличилась с 87,23% до 87,47%, а показатель f1 улучшился с 77,64% до 82,06%. Хорошо было то, что теперь и точность, и оценка f1 для модели RF были лучше, чем для модели DT.

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

Я снова увидел некоторое улучшение точности информационной модели RF с 75,09% до 75,30% и небольшое увеличение показателя f1 с 67,54% до 67,78%. Это улучшение было минимальным, поэтому я решил улучшить выбор функций модели.

Удалены разреженные функции, например, amount_invalid:

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

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

Точность модели BOGO и оценка f1 действительно улучшились, поэтому я исключил функцию amount_invalid из своей модели.

Точность дисконтной модели снизилась, а показатель f1 модели остался прежним. В этом случае я также удалил функцию amount_invalid для модели скидок.

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

Отброшен один уровень фиктивных переменных/горячее кодирование:

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

Тем не менее, есть некоторые споры о том, следует ли это делать или нет. Согласно некоторым статьям (например, здесь) вообще не рекомендуется кодировать категориальные переменные, поскольку они будут генерировать разреженные матрицы, в результате чего:

Полученная в результате разреженность фактически гарантировала, что непрерывным переменным будет присвоена более высокая важность признаков. Один уровень категориальной переменной должен соответствовать самой верхней полосе, чтобы его можно было выбрать для разделения на ранней стадии построения дерева. Это может снизить эффективность прогнозирования. В научно-технических реализациях RF и DT нужно было кодировать переменные. Поэтому я решил проверить производительность моей модели, если бы я отбросил один уровень моих категориальных переменных (в моих данных — переменные канала и гендерные переменные), просто чтобы уменьшить разреженность и шум в данных для моей модели.

Производительность этой модели BOGO была не такой хорошей, как у предыдущей модели BOGO, поэтому я сохранил все уровни переменных.

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

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

Используемые полиномиальные признаки:

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

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

Я мог видеть, что производительность модели RF немного снизилась. Следовательно, возможно, было бы лучше просто оставить модель такой, какой она была. Максимальная точность 75,30% была приемлемой для информационных предложений, хотя она не была такой высокой, как у BOGO или предложений со скидками. В конце концов, я уже включил некоторые предположения о «влиянии» предложения на основе продолжительности.

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

Я мог бы еще больше повысить точность и производительность информационной модели, используя информационную модель RF 5. Тем не менее, добавляя больше данных, как я уже отмечал, набор данных для набора данных offer_info был вдвое меньше, чем наборы данных BOGO и Discount. Следовательно, в конечном счете, с большим количеством данных и с настройкой производительности, удалением ненужных переменных и преобразованием функций, с большим количеством данных, я мог бы в конечном итоге получить производительность модели, возможно, выше 80%.

Лучшие модели и особенности:

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

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

Для предложения BOGO срок членства был существенной характеристикой, а другие переменные были намного меньше в пропорции. Доход, возраст и offer_received_cnt были 2-м, 3-м и 4-м наиболее важными характеристиками, но их пропорции были крошечными.

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

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

Изучение демографических характеристик:

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

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

В трех сегментах большинство людей попадают в средний диапазон доходов (50–100 тысяч). Распределение доходов между тремя секциями относительно одинаково.

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

Группу 2 составили люди, которые вообще не тратили, так как предложения для них были неэффективны, поэтому их не было на графике. Но для групп 1 и 3 + 4 я мог видеть, что потраченная сумма была относительно одинаковой, за исключением того, что люди в группе 1 тратили немного больше. Этого следовало ожидать, поскольку я мог предположить, что предложения стимулировали их покупать больше. Следовательно, их общие расходы увеличились.

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

Потенциальная универсальная модель?

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

Для этого мне нужно было немного подготовить данные для мультиклассовой модели.

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

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

Следовательно, я бы предположил, что три отдельные модели были более полезными. Учитывая эффективное предложение, можем ли мы предсказать, сколько кто-то потратит?

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

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

Я учитывал только транзакции, на которые повлияло предложение (т. е. valid_completed = 1), поскольку хотел предсказать расходы с учетом (т. е. на основе) влияния эффективного предложения.

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

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

Регрессионные модели неэффективны с точки зрения прогнозирования потраченной суммы. Он появился с текущими данными в нашей группе 1 клиентов; не было достаточно информации, чтобы предсказать сумму, которая может быть обусловлена ​​типом предложения. Я мог видеть, что модель регрессора дерева решений превосходит данные с очень высокой оценкой обучения, но неудовлетворительной оценкой тестирования. Между тем, модель линейной регрессии (с регуляризацией гребня/l2) также показала минимальную корреляцию между признаками и целевой переменной. Модель действительно не соответствовала данным.

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

Вывод:

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

  1. Каковы были основные факторы эффективного предложения в приложении Starbucks?
  2. Можем ли мы предсказать, примет ли пользователь предложение, если будут предоставлены данные, а именно характеристики предложения и демографические данные пользователей?

Отражение:

Выводы по вопросу 1:

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

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

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

Выводы по вопросу 2:

Мое решение использовать три отдельные модели для прогнозирования эффективности каждого типа предложений оказалось с достаточной точностью для моделей BOGO и моделей скидок (82,83% для BOGO и 87,35% для скидок), но немного менее точно для информационных предложений (75,3%). . Тем не менее, я бы счел 75% приемлемыми в бизнес-среде, что касается информационных предложений, не было никаких затрат на информирование пользователей о продукте.

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

Основные проблемы и возможные улучшения:

При анализе и построении моделей машинного обучения для ответа на поставленные выше вопросы я размышлял над своими основными проблемами и выводами следующим образом:

Структура атрибуции для назначения offer_id для транзакций:

Чтобы ответить на вопрос 1, мне сначала нужно было определить, что означает «эффективное предложение», используя записи о транзакциях. Это оказалось самой сложной частью проекта. Мне нужно было настроить воронку того, как будет выглядеть эффективная конверсия, так как у меня были данные как о полезных, так и о неэффективных конверсиях. Таким образом, я разрабатывал модель атрибуции для событий конверсии (совершенных предложений и событий транзакций) на основе событий, которые произошли до каждого человека.

В итоге мне пришлось разделить пользователей на четыре разных пула на основе их действий в данных стенограммы:

Группа 1: Люди, которые попали под влияние предложений и таким образом купили/завершили предложение (успешная/эффективная конверсия предложения)

Группа 2: люди, которые получили предложение, но не подверглись влиянию и, следовательно, не совершили конверсию (неэффективная конверсия предложения).

Группа 3: люди, у которых были конверсионные события, но на которых не повлияло предложение.

Группа 4: люди, которые получили предложения, но не просмотрели или не предприняли никаких действий.

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

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

Особенности разработки:

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

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

Решения по реализации модели:

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

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

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

Изучена демография различных групп клиентов:

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

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

Точность модели при прогнозировании потраченной суммы с учетом эффективного предложения:

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

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

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

Чтобы узнать больше об этом анализе, см. ссылку на мой Github, доступную здесь.