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

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

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

  1. Какое предложение следует отправить конкретному покупателю, чтобы он мог купить больше?
  2. Какие группы лучше всего реагируют на какой тип предложения?

Наборы данных и входные данные

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

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

Установив это понимание, давайте теперь посмотрим на три предоставленных файла JSON и их соответствующие элементы:

1. профиль.json

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

(17000 пользователей x 5 полей)

  • пол: (категориальный) M, F, O или null
  • возраст: (числовое) отсутствующее значение, закодированное как 118
  • идентификатор: (строка / хэш)
  • стал_член_на: (дата) формат ГГГГММДД
  • доход: (числовой)

2. портфолио.json

Этот файл содержит предложения, отправленные в течение 30-дневного тестового периода. Это послужит основой для понимания покупательских моделей наших клиентов.

(10 предложений x 6 полей)

  • награда: (числовое) деньги, присуждаемые за потраченную сумму
  • каналы: (список) Интернет, электронная почта, мобильные устройства, социальные сети
  • сложность: (число) деньги, которые необходимо потратить, чтобы получить награду
  • продолжительность: (числовое) время, в течение которого предложение будет открыто, в днях
  • offer_type: (string) бого, скидка, информационный
  • идентификатор: (строка / хэш)

3. стенограмма.json

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

(306648 событий x 4 поля)

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

Исследование и очистка данных

Для porto.json я выполнил однократное кодирование категориальных столбцов: Channels и offer_type. Затем я умножил 24 на столбец продолжительности (измеряется в днях), потому что время записи в файле Transcription.json записывается как часы.

очищенный_портфолио

Для profile.json сначала я изменил все возрасты со значением 118 на NaN, потому что отсутствующее значение в age закодировано как 118. Затем я удалил все строки с отсутствующими значениями. Наконец, я подсчитал количество дней, в течение которых пользователь был нашим участником, с даты, когда пользователь стал нашим участником.

очищенный_профиль

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

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

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

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

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

Прикладной алгоритм

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

Метрики оценки

Хорошо оценивать нашу модель, используя среднеквадратичную ошибку, и отслеживать итерации FunkSVD. Алгоритм следующий: для каждой пары пользователь-предложение, если мы отправили предложение, то вычисляем ошибку как фактическую минус скалярное произведение пользователя и предложения скрытых функций, а затем суммируем все квадратные ошибки для матрицы. Для настройки параметров мы выбираем количество скрытых функций 5, 10 и 15, чтобы проверить, какой из них является лучшим. Для 15 скрытых функций у нас есть MSE 0,003823; Для 10 скрытых функций у нас есть MSE 0,006241; Для 5 скрытых функций у нас есть MSE 0,022370. 15 скрытых функций обеспечивают самый низкий MSE.

Процесс оценки

После того, как мы разложим матрицу пользовательского предложения на матрицу пользователя и матрицу предложения, мы протестируем ее с помощью нашего тестового набора. Для тестирования мы обнаружили интересное явление: модель, построенная с 15 скрытыми функциями, показала наихудшую производительность MSE 0,3303. Тот, который построен с 10 скрытыми функциями, дает лучший результат в предсказании MSE 0,009175, в то время как тот, который построен с 5 скрытыми функциями, имел аналогичную производительность до MSE 0,02391. Этот интересный результат может быть результатом переобучения. Кроме того, это может быть связано с разделением записей, поскольку предложение отправляется часто и через несколько дней. Мы столкнемся с некоторыми случаями, когда пользователь получил предложение и просмотрел предложение в обучающем наборе, но завершил предложение в тестовом наборе. В этом случае мы не учитывали, что пользователь выполнил предложение. Исходя из вышеизложенного, мы не можем быть уверены, сколько функций использовать, потому что просто наличие лучшего способа прогнозирования значения матрицы точно не дает нам указания на то, можем ли мы дать хорошие рекомендации.

Механизм рекомендаций по строительству

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

Мы можем использовать эту модель для прогнозирования реакции пользователя при получении предложений. Например, мы прогнозируем, что для этого пользователя он положительно отреагирует на «Купи 7 долларов и получи 3 скидки в течение 7 дней» и «BOGO на 5 долларов через 5 дней». Хотя значение последнего выше, чем первого, мы предлагаем этому пользователю «BOGO с 5 долларами за 5 дней».

Список портфолио

Как мужчины и женщины реагируют на BOGO и Discount?

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

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

Какой тип предложения принесет больше дохода?

Мы суммируем все расходы ответивших клиентов на основе предложения. «Купите 10 долларов и получите скидку 2 доллара в течение 10 дней!» получает наибольшую продажу.

Список портфолио

Дальнейшее улучшение

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

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

Вывод

Мы исследовали базовое распределение профиля клиента. На основе записей расшифровки мы строим матрицу пользовательских элементов, которая показывает, как пользователи реагировали на полученные ими предложения. Затем мы разделили записи на обучающий набор и тестовый набор и обучили наш алгоритм SVD предсказывать реакцию пользователя на конкретное предложение. Мы достигли наименьшей среднеквадратичной ошибки около 0,003823 с 15 скрытыми функциями в обучающем наборе и около 0,009175 с 10 скрытыми функциями в тестовом наборе. После этого мы создали механизм рекомендаций, который рекомендует Starbucks, какие предложения следует отправить конкретному пользователю.

Женщины реагируют гораздо лучше, чем мужчины

В следующем разделе мы выяснили, какие демографические группы лучше всего реагируют на тот или иной тип предложения. Женщины реагируют намного лучше, чем мужчины, как в BOGO, так и в дисконте. Мужчины реагируют на скидки немного лучше, чем на BOGO.

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

"Купите 10 долларов и получите скидку 2 доллара в течение 10 дней по электронной почте, в Интернете, на мобильных устройствах и в социальных сетях" – лучший маркетинговый ход.

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