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

Определение проблемы:

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

Starbucks выдает три вида предложений:

  1. BOGO - Купи один, получи один бесплатно

2. Информационное предложение. Оно в основном рассылает информацию о некоторых продуктах.

3. Предложение со скидкой - Предоставляет скидку на выбранные продукты.

Всего есть три набора данных:

а) portfolio.json

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

б. профиль.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) — либо идентификатор предложения, либо сумма транзакции в зависимости от записи

Подход к проблеме:

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

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

Визуализация данных:

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

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

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

  • Одно горячее кодирование было выполнено для двух категориальных столбцов: «каналы» и «события».
  • Значения столбца «became_member_on» были преобразованы в объекты даты и времени, а столбец был переименован в «joining_date».
  • Значения «offer_id» и «количество» были извлечены из словарей, присутствующих в столбце «значение».
  • Для каждого уникального значения в «customer_id» и «offer_id» в качестве новых идентификаторов был назначен номинальный идентификатор.
  • Во всех столбцах, соответствующих значению «транзакция» 0, «сумма» была назначена равной 0, чтобы исключить нулевые значения.
  • Два столбца «возрастная_группа» и «группа_дохода» были назначены путем разделения столбца «возраст» на группы, кратные 5, и столбца «доход» на группы, кратные 10000.
  • Нулевые значения в столбце «доход» были заменены его средним значением.

Исследовательский анализ данных:

Давайте приступим к анализу данных и получим некоторые идеи.

Наибольшее количество пользователей относится к возрастной группе 55–60 лет, а среди пользователей больше мужчин, чем женщин.

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

1. К какой возрастной группе относится большинство пользователей каждого типа предложения?

Пользователи, принадлежащие к возрастной группе 115–120 лет, в основном взаимодействовали с каждым из предложений.

2. К какой доходной группе относится большинство пользователей каждого типа предложения?

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

3. Каково гендерное распределение среди пользователей, участвующих в каждом предложении?

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

  • Среди пользователей, которые взаимодействовали с предложением «bogo», 35,96% — женщины и 49,67% — мужчины.
  • Среди пользователей, взаимодействовавших с информационным предложением, 36,25% составляют женщины и 49,32% — мужчины.
  • Среди пользователей, которые взаимодействовали со скидкой, 35,92% — женщины и 49,59% — мужчины.

4. Каково распределение различных взаимодействий пользователей для каждого предложения?

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

  • 83% пользователей, получивших предложение «bogo», просмотрели его.
  • 72,9% пользователей, получивших информационное предложение, просмотрели его.
  • 83% пользователей, получивших предложение о скидке, просмотрели его.

5. Каково участие каждого канала в распространении этих предложений?

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

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

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

6. Каковы атрибуты каждого предложения?

Предложение «BOGO»:

  • Средняя сложность прохождения — 7,615.
  • Средняя награда за выполнение этого предложения составляет 7,615.
  • Средняя продолжительность этого предложения составляет 5,937 дней.

Информационное предложение:

  • Средняя сложность выполнения этого задания равна 0.
  • Средняя награда за выполнение этого предложения равна 0.
  • Средняя продолжительность этого предложения составляет 3,451 дня.

Скидка:

  • Средняя сложность прохождения — 11,12.
  • Средняя награда за выполнение этого предложения составляет 2,88.
  • Средняя продолжительность этого предложения составляет 8 457 дней.

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

Реализация модели классификатора:

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

Функции, которые я использовал для создания классификатора, были:

«customer_id», «время», «сумма», «offer_id», «время», «возраст», «доход».

X = df[['customer_id','time','amount','offer_id',
        'time','age','income']] # store the features in X
y = df['interaction'] # store the target variable in y
# split the data into training and testing set
X_train, X_test, y_train, y_test = train_test_split(X, y)

Я построил три модели классификатора и сравнил их:

Модель 1 — AdaBoostClassifier:

ada_model = AdaBoostClassifier() # initialise AdaBoostClassifier
ada_model.fit(X_train,y_train) # fit the training data
y_pred = ada_model.predict(X_test) # predict for the test set

Модель 2 — RandomForestClassifier:

# initialise  RandomForestClassifier
rfc_model = RandomForestClassifier(max_depth = 2)
rfc_model.fit(X_train,y_train)  # fit the training data
y_pred = rfc_model.predict(X_test) # predict for the test set

Модель 3 — KNeighborsClassifier:

knn_model = KNeighborsClassifier(5) # Initialise KNN Classifier
knn_model.fit(X_train,y_train) # fit the training data
y_pred = knn_model.predict(X_test) # predict for the test set

Показатели:

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

  • Оценка F1 - (2 * Точность * Отзыв) / (Точность + Отзыв)
  • Матрица путаницы - для анализа значений TP, FP, TN, FN каждого класса.

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

  • Классификатор повышения Ады:
F1 score:  0.811167366965
Confusion Matrix: [[ 8369,     0,     0,     0],
                   [    0, 19196,     0,     0],
                   [    0, 14456,     0,     0],
                   [    0,     0,     0, 34613]]
  • Случайный лесной классификатор:
F1 score:  0.705287470313
Confusion Matrix: [[ 3087,    47,     0,  5235],
                   [  439, 17600,     0,  1157],
                   [  297, 13466,     0,   693],
                   [    0,    52,     0, 34561]]
  • K означает классификатор:
F1 score:  0.367291280633
Confusion Matrix: [[  519,  2471,  1097,  4271],
                   [ 1863,  7388,  3981,  6107],
                   [ 1520,  6916,   754,  5281],
                   [ 2835,  8576,  3569, 19486]]

Результаты:

1) AdaBoostClassifier имеет наивысший балл F1 0,811.

2) Классификатор Random Forest имеет второй по величине балл F1, равный 0,706.

3) Классификатор KNN имеет наименьший балл F1 0,367.

Уточнение модели:

Настройка гиперпараметров:

Я реализовал поиск по сетке по следующему набору параметров для двух моделей. :

АдаБустКлассификатор:

parameters = {'n_estimators': [50, 100, 200],
             'learning_rate': [1.0, 1.5, 2.0, 2.5]}

Случайный классификатор леса:

parameters = {'n_estimators': [50, 100],
              'min_samples_split': [2, 3, 4]}

Поиск по сетке, похоже, не улучшил оценку F1 обеих моделей.

Методы ансамбля:

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

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

Метаоценщик пакетов:

bag = BaggingClassifier(KNeighborsClassifier(),
                             max_samples=0.5, max_features=0.5)
bag.fit(X_train,y_train)
y_pred = bag.predict(X_test) # predict for the test set

Оценка:

F1 score:  0.764021191638
Confusion Matrix: [[  171,   858,   524,  6805],
                   [   0, 19329,    10,     0],
                   [  169,  3817,  5781,  4704],
                   [   40,   933,   224, 33269]]

Чрезвычайно рандомизированные деревья:

clf = ExtraTreesClassifier(n_estimators=10, max_depth=None,
                           min_samples_split=2, random_state=0)
clf.fit(X_train,y_train)
y_pred = clf.predict(X_test) # predict for the test set

Оценка:

F1 score:  0.912297413681
Confusion Matrix: [[ 7886,     0,     0,   472],
                   [    0, 16688,  2651,     0],
                   [    0,  3257, 11214,     0],
                   [  341,     0,     0, 34125]]

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

Отражение:

  • Анализ, чтобы определить, какие демографические группы лучше всего реагируют на тот тип предложения, который был успешно реализован.
  • Тот факт, что ни одно из трех предложений не имело записи о его завершении или транзакциях по нему в этом наборе данных, затрудняло четкое определение успешных предложений.
  • Хотя модели классификатора не дали очень точных результатов, использование ансамблевых методов значительно улучшило оценку F1. Важность ансамблевых методов была очевидна в этом проекте.
  • Самый высокий балл F1 0,9123 был достигнут среди всех моделей классификатора.

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

Возможные области улучшения:

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

Я представил свой подробный код проекта здесь, на моей странице Github.

Спасибо Udacity и Starbucks за доступ к этому набору данных.