В этом блоге я расскажу о своем исследовании поведения покупателей на реальном наборе данных Instacart из 3 млн + записей. Я расскажу, как быстро выполнить анализ корзины покупателя с помощью алгоритма Apache Spark ML FP-growth на Databricks.

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

Правило ассоциации Mining

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

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

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

Теперь давайте посмотрим, что такое показатели поддержки, уверенности и подъема с двумя пунктами (предположим) X и Y .

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

Уверенность: - Уверенность - это частота, с которой X и Y покупаются вместе. с частотой, с которой X приобретается отдельно.

Подъем: - Подъем определяется как поддержка по сравнению с поддержкой для X, умноженная на поддержку для Y. Думайте о подъеме как о росте вероятности того, что в тележке окажется Y, если известно о наличии X. над вероятностью наличия Y в корзине без каких-либо сведений о наличии X.

Я буду использовать эти метрики позже при реализации алгоритма FP-growth.

Набор данных

В этом блоге я использую настоящий набор данных Instacart, который был выпущен на Kaggle в 2017 году.

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

Набор данных можно скачать здесь.

Используемая платформа

Я бы использовал Apache Spark для реализации этого проекта и использую языки программирования PySpark, SparkSql и более поздние версии Scala для кодирования.

Обратите внимание, что вы можете бесплатно попробовать Apache Spark в облаке Databricks по этой ссылке.

Хорошо, хватит теории, перейдем к коду.

Импорт всех доступных файлов в Spark DataFrame и создание временных таблиц

В набор данных входит шесть разных файлов .csv, которые можно объединить для выполнения анализа. Для начала я импортировал все 6 файлов в среду Spark и создал временные таблицы для выполнения на них запросов Spark SQL.

Давайте посмотрим на 5 верхних строк каждого импортированного файла и их словарь данных:

orders (3,4 млн строк, 206 тыс. пользователей):

  • order_id: идентификатор заказа
  • user_id: идентификатор клиента
  • eval_set: к какому оценочному набору принадлежит этот заказ
  • order_number: порядковый номер заказа для этого пользователя (1 = первый, n = n-й)
  • order_dow: день недели, когда был размещен заказ
  • order_hour_of_day: час дня, когда был размещен заказ
  • days_since_prior: дней с момента последнего заказа, максимум 30 (с НП для order_number = 1)
orders.show(n=5)

products (50 тыс. строк):

  • product_id: идентификатор продукта
  • product_name: название продукта
  • aisle_id: внешний ключ
  • department_id: внешний ключ
products.show(n=5)

aisles (134 строки):

  • aisle_id: идентификатор прохода
  • aisle: название прохода
aisles.show(n=5)

deptartments (21 строка):

  • department_id: идентификатор отдела
  • department: название отдела
departments.show(n=5)

order_products_train (131 тыс. + строк):

Данные обучения, предоставленные участникам Kaggle

order_products_train.show(n=5)

order_products_prior (32 млн + строк):

Данные о заказах до последнего заказа этого пользователя

order_products_prior.show(n=5)

Теперь, когда мы создали DataFrames и взглянули на 5 верхних строк каждого файла, приступим к EDA с использованием Spark SQL, чтобы найти идеи и закономерности из набора данных Instacart.

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

В какое время дня покупают покупатели?

df = sqlContext.sql("select count(order_id) as total_orders, order_hour_of_day as hour 
from orders 
group by order_hour_of_day 
order by order_hour_of_day")
df.show()

Примечание: с записными книжками Databricks мы можем использовать %sql для выполнения кода SQL в новой ячейке той же записной книжки Python. Например, эквивалентный код приведенного выше фрагмента кода будет таким, как показано ниже.

%sql
select count(order_id) as total_orders, order_hour_of_day as hour 
from orders 
group by order_hour_of_day 
order by order_hour_of_day

Примечание. Databricks поддерживает различные типы DataFrame и визуализаций SQL в ячейках записной книжки. Вы можете узнать о них подробнее здесь.

Над линейным графиком показано, что клиенты с большей вероятностью разместят заказ с 9:00 до 18:00.

Как часто клиенты размещают заказы?

%sql
select days_since_prior_order,count(order_id) as total_orders
from orders 
group by days_since_prior_order 
order by days_since_prior_order

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

Кроме того, большое количество клиентов размещают заказ через 30 дней или позже, поскольку столбец days_since_prior ограничен 30

В какой день недели клиенты покупают больше всего?

%sql
select count(order_id) as total_orders, 
  (case 
     when order_dow = '0' then 'Sunday'
     when order_dow = '1' then 'Monday'
     when order_dow = '2' then 'Tuesday'
     when order_dow = '3' then 'Wednesday'
     when order_dow = '4' then 'Thursday'
     when order_dow = '5' then 'Friday'
     when order_dow = '6' then 'Saturday'              
   end) as day_of_week 
  from orders  
 group by order_dow 
 order by total_orders desc

В воскресенье и понедельник больше всего заказов, а в четверг меньше всего заказов за неделю.

Сколько товаров покупатели покупают в заказе?

Давайте создадим главный набор данных, объединив вместе продукты, отделы, наборы данных order_products_train и order_products_prior и запустим запрос поверх этого.

%sql
create table master_table as
(select op.*,p.product_name,p.aisle_id,p.department_id,d.department from
 (select * from order_products_train 
 union
 select * from order_products_prior) as op
 inner join products as p
 on op.product_id = p.product_id
 inner join departments as d
 on p.department_id = d.department_id)
%sql
select order_id,count(product_id) as total_items
from master_table 
group by order_id

На гистограмме выше показано, что чаще всего покупатели заказывают 4 товара.

Большинство клиентов предпочитают покупать от 1 до 15 товаров за заказ.

Из каких отделов верхнего уровня размещаются заказы?

%sql
select department, count(*) as orders_count from master_table
group by department
order by orders_count desc
limit 10

Если мы посмотрим на 10 ведущих отделов, в которых закупается большинство товаров, мы сделаем вывод, что почти 50% покупаемых товаров принадлежат всего 2 отделам, которые 'производят 'и' молочные яйца '

Какие товары покупаются чаще всего?

%sql
select product_name, count(*) as orders_count from master_table
group by product_name
order by orders_count desc
limit 200

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

Давайте также составим облако слов из 200 самых популярных товаров, покупаемых клиентами Instacart.

# !pip install wordcloud
from wordcloud import WordCloud 
import matplotlib.pyplot as plt
df = sqlContext.sql("SELECT product_name FROM (select product_name, count(*) as orders_count from master_table group by product_name order by orders_count desc limit 200)")
df2 = df.rdd.flatMap(lambda x: x).collect()
fullStr = ' '.join(df2)
wordcloud = WordCloud(background_color="white").generate(fullStr)
# Display the generated image:
plt.figure(figsize=(14, 10))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()
display()

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

Алгоритм FP-роста

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

Вы можете узнать больше о этапах алгоритма FP-роста здесь.

Организация данных по корзине покупок

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

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

Реализация алгоритма FP-роста на Scala

Здесь мы будем использовать для реализации пакет spark.ml FP-growth.

Давайте начнем с того, что минимальное значение поддержки будет равно 0,001, а минимальное значение достоверности равно 0. Оба этих порога определяются пользователем. Минимальное значение поддержки выбирается таким образом, чтобы в наших наборах элементов был минимум 1 элемент, и это не занимало много времени для вычислений (более низкое минимальное значение поддержки приводит к большему времени вычислений).

Создание частых наборов товаров и создание правил связывания

А теперь давайте исследуем частые наборы предметов, которые мы сгенерировали выше.

%sql
select items, freq from mostPopularItemInABasket where size(items) > 2 order by freq desc limit 20

Чаще всего в корзины входят органические авокадо, органические клубники и органические бананы вместе.

Хороший способ подумать о правилах ассоциации состоит в том, что модель определяет, что если вы что-то купили (т. Е. предшествующий), то вы купите и эту другую вещь (т. Е. консеквент) со следующей уверенностью.

%sql
select antecedent as `antecedent (if)`, consequent as `consequent (then)`, confidence from ifThen order by confidence desc limit 20

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

Показатель рост определяет, насколько независимы предшествующее и последующее в наборах элементов. Подъем ›› 1 означает, что элементы сильно зависят друг от друга, Подъем = 1 означает, что элементы не зависят друг от друга. other и l ift ‹< 1 означает, что элементы заменяют друг друга (это означает, что наличие одного элемента отрицательно влияет на наличие другого элемента и наоборот).

%sql
select * from ifThen where lift > 1 order by lift desc

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

Реализация алгоритма FP-роста с использованием PySpark

Алгоритм FP-роста, который мы реализовали выше с помощью Scala, также можно реализовать с помощью PySpark с эквивалентным кодом, показанным ниже:

Резюме

В этом блоге мы проанализировали покупательское поведение клиентов и выполнили анализ рыночной корзины с помощью Apache Spark на огромном наборе данных. Если вы хотите реализовать анализ рыночной корзины в других средах, вы можете использовать библиотеку apyori в Python и библиотеку arules в R для алгоритма Apriori. .

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

Спасибо за чтение !!!

Использованная литература: -

i) https://spark.apache.org/docs/latest/ml-frequent-pattern-mining.html

ii) https://s3.us-east-2.amazonaws.com/databricks-dennylee/notebooks/Market+Basket+Analysis+using+Instacart+Online+Grocery+Dataset.html

iii) https://towardsdatascience.com/association-rules-2-aa9a77241654