Правило ассоциации (ассоциация) – это метод определения взаимосвязи элементов друг с другом. В отличие от Корреляции (Correlation), где отыскиваются взаимосвязи между Признаками (Feature) Датасета (Dataset), здесь идет речь о взаимосвязях внутри признака, например, дополняющие друг друга покупки в гипермаркете.
Ассоциацию можно измерить тремя распространенными способами. Для простоты адаптируем концепцию к тем же покупкам в гипермаркете.
$$S_M = \frac{Число\space{корзин}\space{с}\space{набором}\space{M}}{Общее\space{число}\space{корзин}}\space{, где}$$
$$S_M\space{–}\space{Поддержка}$$
$$С_{M_1 -> M_2} = \frac{Число\space{корзин}\space{с}\space{наборами}\space{M_1}\space{и}\space{M_2}}{Число\space{корзин}\space{с}\space{набором}\space{M_1}}\space{, где}$$
C_M_1 -> M_2\space{–}\space{Степень}\space{уверенности}
$$L_{M_1 -> M_2} = \frac{С_{M_1 -> M_2}}{S_{M_2}}\space{, где}$$
$$L_{M_1 -> M_2}\space{–}\space{Степень}\space{подъема}$$
Для демонстрации выделения ассоциаций мы используем готовый датасет покупок и специальную библиотеку Apriori. Для начала импортируем все необходимые компоненты:
!pip install apyori
import pandas as pd
import numpy as np
import apyori
from apyori import apriori
Мы используем готовый датасет с историей покупок, содержащий идентификатор покупателя, дату покупки и купленные товары. Посмотрим, какого размера наш набор:
groceries = pd.read_csv('https://www.dropbox.com/s/qoo8k66kxke52cw/Groceries_dataset.csv?dl=1')
groceries.shape
Датасет состоит из 38+ тысяч записей с тремя признаками:
(38765, 3)
Создадим несколько вспомогательных признаков. С помощью сочетания методов groupby()
и nunique()
мы сможем сгруппировать покупки по покупателям и подсчитать количество посещений гипермаркета:
# Разобъем записи на группы по дате и подсчитаем количество уникальных товаров
groceries_time = pd.DataFrame(groceries.groupby('Date')['itemDescription'].nunique().index)
# Разобъем записи на группы по дате и подсчитаем количество уникальных посетителей
groceries_time['members_count'] = groceries.groupby('Date')['Member_number'].nunique().values
# Разобъем записи на группы по дате и запишем все купленные отдельным посетителем товары в один список
groceries_time['items_count'] = groceries.groupby('Date')['itemDescription'].nunique().values
groceries_time['items'] = groceries.groupby('Date')['itemDescription'].unique().values
# Зададим новый индекс
groceries_time.set_index('Date', inplace = True)
groceries_time.head()
Теперь понятно, сколько за раз купил каждый пришедший:
Нас интересует перечень покупок, потому мы выделим этот признак в отдельный список:
transactions = groceries_time['items'].tolist()
Теперь применим функцию apriori. Зададим функции параметры по умолчанию – какой объект рассматривать (transactions
), минимальный уровень поддержки и уверенности, форма выдачи результата. Ко всему прочему нам понадобится вспомогательная функция inspect()
, которая сформирует Датафрейм (DataFrame) из обнаруженных ассоциативных пар:
rules = apriori(transactions = transactions, min_support = 0.00030, min_confidance = 0.01, min_lift = 3, min_length = 2, max_length = 2)
results = list(rules)
def inspect(results):
lhs = [tuple(result[2][0][0])[0] for result in results]
rhs = [tuple(result[2][0][1])[0] for result in results]
supports = [result[1] for result in results]
confidences = [result[2][0][2] for result in results]
lifts = [result[2][0][3] for result in results]
return list(zip(lhs, rhs, supports, confidences, lifts))
resultsinDataFrame = pd.DataFrame(inspect(results), columns = ['Предмет #1', 'Предмет #2', 'Поддержка', 'Уверенность', 'Подъем'])
resultsinDataFrame.head()
Мы получили обширный список из 242 ассоциаций – настоящая кладезь для маркетолога! Посетитель гипермаркета и не поймет, почему в отделе с кухонными принадлежностями звучит ненавящевая реклама мужской косметики:
Посмотрим, какие ассоциации самые ярковыраженные, отсортировав результирующий датафрейм resultsDataFrame
от большего к меньшему:
resultsinDataFrame.nlargest(n = 10, columns = 'Lift')
Наш Топ-10 выглядит весьма и весьма неожиданно:
Ликер и консервы! Вот это сочетание. Кухонные принадлежности и просекко – весьма вероятно и обыденно, впрочем, на перебор таких "очевидных" сочетаний может уйти много времени и рекламного бюджета, не так ли? В топ-3 попала пара "Кухонные принадлежности и Мужская косметика". Да, удивительное рядом. Так реклама становится гораздо точнее и эффективнее, а ведь это сокращает и баннерную нагрузку на конечных пользователей ритейла, что само по себе замечательно.
Ноутбук, не требующий дополнительной настройки на момент написания статьи, можно скачать здесь.
Автор оригинальной статьи: Gaurav Chopra
Фото: @montylov
© Лена Капаца. Все права защищены.