Какие продукты снова будут покупать потребители Instacart?

Содержание

  1. Бизнес-проблема
  2. Бизнес-цели и ограничения
  3. Обзор данных и анализ столбца набора данных
  4. Сопоставление проблемы реального мира с проблемой машинного обучения
  5. Метрика производительности
  6. Исследовательский анализ данных
  7. Существующие решения / подходы
  8. Первый подход
  9. Функциональная инженерия
  10. Построение модели
  11. Конвейер вывода
  12. Резюме
  13. Будущая работа
  14. Профиль
  15. использованная литература

1. Деловая / реальная проблема

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

Instacart - американская компания, предоставляющая услуги доставки в тот же день. Набор данных Instakart содержит выборку из более чем 3 миллионов заказов на продукты от более чем 200 000 пользователей Instacart. Команда специалистов по обработке данных Instacart играет большую роль в обеспечении этого восхитительного покупательского опыта. В настоящее время они используют транзакционные данные для разработки моделей, которые предсказывают, какие продукты пользователь купит снова, попробует впервые или добавит в корзину в следующий раз во время сеанса. Нам необходимо использовать эти анонимные данные о заказах клиентов с течением времени, чтобы предсказать, какие ранее приобретенные продукты будут в следующем заказе пользователя.

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

2. Бизнес-цели и ограничения

Цели:

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

Ограничения:

  • Некоторая форма взаимодействия
  • Нет строгих ограничений по задержке

3. Обзор данных и анализ столбцов набора данных

Источник данных:



Набор данных для этой проблемы представляет собой реляционный набор файлов, описывающих заказы клиентов с течением времени. Набор данных анонимизирован и содержит выборку из более чем 3 миллионов заказов на продукты от более чем 200 000 пользователей Instacart. На каждого пользователя мы получаем от 4 до 100 заказов с указанием последовательности приобретенных продуктов в каждом заказе. Нам также сообщается неделя и час дня, когда был размещен заказ, и относительная мера времени между заказами.

Имя файла: orders.csv

Имя файла: aisles.csv

Имя файла: sizes.csv

Имя файла: order_products __ *. csv (* включает предыдущий, поезд)

предыдущий файл содержит историю предыдущих покупок пользователя [до (N-1) -го заказа]

Файл train содержит историю последних покупок пользователя [только N-й заказ]

4. Сопоставление реальной проблемы с проблемой машинного обучения.

Тип проблемы машинного обучения:

Учитывая пользователя и номер заказа, нам нужно предсказать, какие продукты будут заказаны следующими.
Мы также можем представить это как проблему двоичной классификации прогнозирования временных рядов
, поскольку у нас есть метка с именем reordered, которая принимает значение 0 / 1.
Мы называем это прогнозированием временных рядов, поскольку для каждого пользователя у нас есть заказанные продукты и номер заказа, который показывает поведение пользователя при покупке с течением времени.
Мы можем использовать предыдущий набор данных, чтобы фиксировать поведение продукта пользователя X в течение time и
создавать связанные с этим функции с помощью функций агрегирования.

5. Показатель эффективности:

  • Средний балл F1
  • Матрица путаницы

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

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

Основные проверки работоспособности данных

Наблюдение: только столбец days_since_prior_order содержит значения NaN. Это может быть связано с тем, что люди разместили свой первый продукт, поскольку из приведенного выше анализа мы видим, что для всех таких строк NaN в 'days_since_prior_order' у нас есть order_number как 1. И это также имеет смысл, что люди, размещающие свой первый заказ, не имеют никаких История заказов.

Распределение данных в разных файлах

Наблюдение. У нас есть много данных (3,2 миллиона) о предыдущих покупках пользователей. Нам нужно дать прогнозы на тестовом наборе, который составляет 75000 (2,2% от общего количества точек данных), как указано в описании проблемы.

Общее количество заказов / повторных заказов в день

Наблюдение. Люди чаще размещают заказы в субботу (день 0) и воскресенье (день 1), чем в другие дни. Такая же тенденция наблюдается и для повторных заказов.

Общее количество заказов в час

Наблюдение: большинство людей покупают товары с 7:00 до 20:00. 10 часов утра - час пик, когда поступает самый высокий заказ.

Общее количество заказов по сравнению с days_since_prior_order

Наблюдение: Совершенно очевидно, что люди, скорее всего, будут повторно заказывать товары после 7, 14, 21, 30 дней после 0-го дня, поскольку мы можем ясно видеть всплески каждые 7, 14, 21, 30-е по сравнению с соседними днями. имеет смысл, поскольку люди склонны покупать продукты еженедельно и ежемесячно. 30-й день - максимальное количество размещенных заказов

Общее количество заказов, размещенных пользователем, по сравнению с количеством заказов

Наблюдение: нет пользователей, которые разместили менее 4 заказов, а максимальное количество размещенных пользователями заказов составляет 100.

Размер сегмента пользователей и количество заказов

Наблюдение. Чаще всего встречаются сегменты размером 5 и 6. Максимальный размер корзины - 145, и только один пользователь купил 145 товаров в заказе.

Mean_add_to_cart_order vs Reorder

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

Облако слов заказанных продуктов

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

Топ-10 отделов по заказам и количеству их повторных заказов

Наблюдение: отдел производства имеет наивысший заказ и повторный заказ.

10 лучших проходов по заказам и количеству повторных заказов

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

Вклад каждого отдела и прохода в общее количество повторных заказов

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

7. Существующие решения / подходы

Подход1:

Здесь также используется подход к созданию пользовательских характеристик продукта.

  • Пользовательские функции включают в себя для каждого пользователя среднее количество дней между заказами, nb_orders, total_items куплено, all_products куплено, средний размер корзины и т. Д.
  • Пользователь X Характеристики продукта включают для каждого продукта количество заказов, последний идентификатор заказа, суммарную позицию в корзине.
  • Затем для каждого заказа поездов он сочетает в себе пользовательские функции с функциями пользовательского продукта, а также добавляет новый набор функций. Ниже приведены некоторые из функций.

○ 'user_total_orders', ○ 'user_total_items', ○ 'total_distinct_items', ○ 'user_average_days_between_orders', ○ 'user_average_basket', ○ 'order_hour_of_day', ○ 'days_since_pr_of_day', ○ 'days_since_prior_order' раз, сколько раз заказано пользователем, 'UP_orders_ratio' [общее количество раз, когда пользователь не заказывает продукт / user_total_orders] И т. Д.

На диаграмме ниже описан последующий процесс.

Подход 2:

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

Схема ниже описывает процесс

Подход 3:

  • После объединения данных для набора данных выполняется EDA, чтобы понять, как частота повторного заказа меняется по дням недели и часам дня. Чтобы понять интервал повторного заказа, самые популярные продукты, продажи по отделам.
  • Для рекомендации продуктов в приведенной выше записной книжке для определения рекомендуемых продуктов используются счетчики в двух граммах. Сначала продукты группируются по идентификатору заказа. Затем он заменит пробел, присутствующий в каждом продукте, на подчеркивание (_), а для каждого заказа продукты будут разделены пробелом. Для каждого продукта X он будет рассматривать биграммы, содержащие X, и сортировать биграммы на основе общего количества биграмм для всех заказов в порядке убывания (т.е. сумма по оси = 0). Затем он выберет N лучших продуктов из биграмм, содержащих X, и порекомендует их. Если N больше, чем общее количество биграммов (скажем, K) X, тогда он сначала порекомендует k продуктов из k биграммов, а затем попытается найти аналогичные продукты для продукта, который находится в наивысшем биграммах. количество граммов X.

8. Первый подход.

Подход:

Наш первый подход к сокращению - для каждого продукта пользователя X в каждом заказе, который мы собираемся просматривать историю покупок пользователя в окне в недавнем прошлом, что означает, что для каждого пользователя в нашем окне есть номер заказа, который меньше текущего рассматриваемого order_number. Затем мы вычисляем определенную сводную статистику в этом конкретном окне в рамках разработки функций. Например, давайте рассмотрим последний order_id на рисунке выше, как указано стрелкой, а размер окна равен 1. Затем мы посмотрим назад во времени, где номер заказа ‹текущий номер заказа (= 3). Для этого user_id есть 2 порядковых номера (= 3). Поскольку размер нашего окна равен 1, мы учитываем только последний номер заказа, равный 2 для этого user_id (= 3). Окно выделено на рисунке выше. Размер окна - это гиперпараметр, который необходимо настроить.

Теперь проблема возникает при обработке такого большого объема данных.

Я использовал виртуальную машину Linux в GCP с 8 ЦП и 32 ГБ ОЗУ.

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

Функция feature_engineering вычисляет определенные функции в окне.

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

  • uxp_reorder_bias
  • u_total_orders
  • u_reordered_ratio
  • u_average_days_between_orders
  • u_dow_most_orders
  • u_hod_most_orders
  • u_total_items_bought
  • u_avg_basket_size
  • uxDeparment_reorder_count
  • is_organic

После предварительной обработки я отправил данные в модели ансамбля на основе дерева (например, Random forest, GBDT, Light GBM). Хотя матрица путаницы и оценка F1 для данных по обучению и валидации были очень хорошими, но моя оценка отправки по тестовым данным была низкой.

Было всего 0,23. Почему-то этот подход не помогал прогнозировать следующий сегмент покупок пользователя.

Рабочий подход:

Ниже представлена ​​схема рабочего подхода.

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

9. Разработка функций

Возможности пользователя

  • u_total_orders: количество заказов на пользователя
  • u_reordered_ratio: как часто пользователь переупорядочивал товары
  • u_average_days_between_orders: среднее количество дней между покупками пользователя
  • u_days_between_orders_std: стандартное отклонение в days_since_prior_order пользователя
  • u_dow_most_orders: День недели, когда пользователи заказывают больше всего
  • u_hod_most_orders: час дня, когда пользователь заказал больше всего.
  • u_total_items_bought: Общее количество товаров, купленных одним пользователем
  • u_total_unique_prod: Общее количество заказанных уникальных товаров
  • u_avg_basket_size, стандартное отклонение корзины, корзина_sum
  • u_date_inscription: максимальная дата для каждого пользователя, исключая последний заказ
  • u_tot_active_prod: количество продуктов, заказанных пользователем
  • u_reorder_ratio_bool: среднее значение повторного заказа по продуктам

Особенности продукта

  • p_total_purchases: Количество покупок для каждого продукта.
  • p_reorder_ratio: Как часто товар повторно заказывался
  • p_avg_cart_position: означает добавление в корзину для каждого продукта
  • p_unique_user_count: база пользователей для каждого продукта
  • p_recency_order: средний номер_порядка
  • p_recency_order_rev: среднее число_порядка
  • p_recency_date: средняя дата
  • p_freq_days: Среднее количество дней до повторного заказа товара
  • p_freq_order: Среднее количество заказов до повторного заказа товара.
  • p_tot_active_usr: количество пользователей продукта, заказ которого был изменен
  • p_reorder_ratio_bool: средняя стоимость повторного заказа для конкретного продукта через usres
  • p_trend_rt: количество раз, когда продукт был заказан в последнем заказе / количество раз, когда продукт был заказан во 2-м последнем заказе среди пользователей
  • p_trend_diff: количество раз, когда продукт был заказан в последнем заказе минус количество раз, когда продукт был заказан во 2-м последнем заказе для пользователя
  • * Тенденция продукта - мы берем последние 2 заказа для пользователей и рассчитываем тенденцию повторного заказа продукта.

Возможности продукта User X

  • uxp_total_bought: сколько раз пользователь покупал продукт
  • uxp_reorder_ratio: как часто пользователь делал повторный заказ определенного продукта.
  • uxp_avg_cart_position: среднее значение add_to_cart_order пользователя для определенного продукта
  • uxp_add_to_cart_order_relative_mean: среднее значение add_to_cart_order_relative пользователя для определенного продукта
  • uxp_add_to_cart_order_inverted_mean: среднее значение add_to_cart_order_inverted пользователя для конкретного продукта
  • uxp_last_order_number: последний заказ_пользователя для определенного продукта
  • uxp_first_order_number: первый заказ_пользователя для определенного продукта
  • up_last_order_date: последняя дата пользователя для определенного продукта
  • up_first_order_date: первая дата пользователя для определенного продукта
  • uxp_bought_last5: товар, купленный пользователями в последних_пять заказах. Это позволит зафиксировать новизну пользовательского продукта.
  • uxp_date_strike: 1/2 ** (дата / 7)
  • uxp_order_strike: 1/2 ** (порядковый_номер_ обратный)

Для последних двух функций концепция выглядит так, как показано ниже.

Для пользователя с 5 заказами (NA означает, что продукт еще не был куплен)
0 0 0 0 1 = 1/2 ** 5 = 0,03125 продукт, купленный в первый раз и больше не купленный
1 1 NA NA NA = 1/2 ** 1 + 1/2 ** 2 = 0,75 продукт, приобретенный в последние два раза
1 0 0 1 NA = 1/2 ** 1 + 1/2 ** 4 = 0,5625
Это помогает сосредоточиться на продукте, который пользователь недавно начал переупорядочивать.

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

  • a_total_purchases: количество покупок для каждого прохода
  • a_reorder_ratio: Как часто менялся порядок прохода
  • a_avg_cart_position: означает добавление в корзину для каждого прохода.
  • a_unique_user_count: база пользователей для каждого прохода
  • a_tot_active_user: количество пользователей прохода, порядок которого был изменен
  • a_reorder_ratio_bool: среднее значение повторного заказа через usres для определенного прохода
  • uxa_unique_products_ratio: Соотношение продуктов, купленных пользователем в этом проходе

отделение

  • d_total_purchases: Количество покупок для каждого отдела
  • d_reorder_ratio: как часто менялся порядок отдела
  • d_avg_cart_position: означает добавление в корзину для каждого отдела.
  • d_unique_user_count: база пользователей для каждого отдела
  • a_tot_active_user: количество пользователей для отдела, который был переупорядочен
  • a_reorder_ratio_bool: среднее значение повторного заказа по usres для определенного отдела
  • uxa_unique_products_ratio: Соотношение продуктов, приобретенных пользователем в этом отделе

Word2Vec о продуктах

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

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

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

Кодирование циклических функций

Здесь order_dow и order_hour_of_day - циклические функции. Для order_dow цикл повторяется от 0 до 6, а для order_hour_of_day цикл повторяется от 0 до 23. Есть определенные проблемы с циклическими функциями, если мы не кодируем их должным образом. Например, разница между 23 и 22 часами равна 1, но для часов 23 и 0 разница составляет 23, хотя реальная разница для них обоих составляет 1 час. Нам нужно закодировать эти циклические функции таким образом, чтобы часы 23 и 0 были близки, хотя абсолютная разница между ними составляет 23.

One common way to encode cyclic features is to use sine an cosine transformations. 
We can do that using following transformation.
Xsin = sin(2∗π∗x/max(x))
Xcos = cos(2∗π∗x/max(x))

Является ли продукт органическим или нет

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

10. Построение модели

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

Можно попробовать разные модели, но в большинстве случаев ансамблевые модели лучше всего работают в классических моделях. Итак, начнем с одного из моих любимых Light GBM. Поскольку он обеспечивает более высокую скорость обучения и меньшее использование памяти, чем XGboost.

Мы применили метод случайного поиска, чтобы найти лучший набор параметров Light GBM. Теперь, чтобы предсказать результаты, важно определить правильный порог вероятности. Мы попробовали разные значения и обнаружили, что порог 0,22 дает нам максимальный балл F1.

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

Я также пробовал с другими моделями, такими как Случайный лес, XGboost, Классификатор логистической регрессии, но результат был ниже по сравнению с Легким GBM.

11. конвейер вывода

12. Резюме

Как и ожидалось, лучше всех показала модель Light GBM. Полученный балл за подачу заявки составил 0,38. Ниже приведен снимок экрана с оценкой, полученной по данной задаче. Моя таблица лидеров входит в 10% лучших.

13. Будущая работа

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

14. Профиль

Полный анализ с развертываемым кодом можно найти в моем репозитории GitHub.



15. Ссылки

  1. Https://netflixtechblog.com/netflix-recommendations-beyond-the-5-stars-part-1-55838468f429
  2. Https://www.kaggle.com/c/instacart-market-basket-analysis/discussion/34977
  3. Https://www.kaggle.com/errolpereira/xgboost-with-minimal-feature-engineering#Creating-user-product-features.
  4. Https://www.kaggle.com/c/instacart-market-basket-analysis/discussion/38097
  5. Http://blog.davidkaleko.com/feature-engineering-cyclical-features.html