Априори, Ассоциативный анализ, Машинное обучение

Выполнение анализа рыночной корзины с помощью машинного обучения

Улучшайте маркетинг с помощью ИИ. Полный код доступен в моем репозитории Github

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

Цель анализа ассоциаций, в общем, состоит в том, чтобы найти следующие взаимосвязи:

Уточнение терминологии

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

Анализ рыночной корзины

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

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

Шаги

К счастью, шаги по построению этого алгоритма просты:

  1. Установка модулей
  2. Импорт библиотек
  3. Подготовка набора данных
  4. Извлечь часто используемые наборы элементов
  5. Извлечь правила ассоциации
  6. Извлечь правила
  7. Определите порог и извлеките окончательные ассоциации

1. Установка модулей

Я буду импортировать модули с помощью pip.

! pip install mlxtend
! pip install xlrd

2. Импорт библиотек

Scikit-Learn не поддерживает априорный алгоритм. Я буду использовать расширение библиотеки Python под названием mlxtend.

import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori
from mlxtend.frequent_patterns import association_rules

3. Подготовка набора данных.

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

#Onion, Sausages, Cheese, Water, Butter, Sugar, Eggs
df = [['Onion', 'Sausages', 'Cheese', 'Butter'],
      ['Onion', 'Sausages', 'Water', 'Sugar'],
      ['Onion', 'Water', 'Sausages'],
      ['Butter', 'Sugar', 'Eggs'],
      ['Butter', 'Sugar', 'Eggs', 'Cheese'],
      ['Water', 'Cheese', 'Eggs'],
      ['Water', 'Butter'],
      ['Onion', 'Butter', 'Sugar'],
      ['Onion', 'Butter', 'Cheese'],
      ['Onion', 'Butter', 'Water'],
      ]
df = pd.DataFrame(df)
df

Преобразование DataFrame в совместимый список

На самом деле набор данных был бы готов до того, как преобразовать его в DataFrame. Однако цель этой статьи - проиллюстрировать вам, каковы строительные блоки анализа рыночной корзины. Поскольку вы, вероятно, начнете с информации, хранящейся в DataFrame pandas, это окажется полезным в будущем (вы можете пропустить, если не заинтересованы).

#1. conversione in list: il problema che ha None values
df = dataset.values.tolist()
df
[['Onion', 'Sausages', 'Cheese', 'Butter'],
 ['Onion', 'Sausages', 'Water', 'Sugar'],
 ['Onion', 'Water', 'Sausages', None],
 ['Butter', 'Sugar', 'Eggs', None],
 ['Butter', 'Sugar', 'Eggs', 'Cheese'],
 ['Water', 'Cheese', 'Eggs', None],
 ['Water', 'Butter', None, None],
 ['Onion', 'Butter', 'Sugar', None],
 ['Onion', 'Butter', 'Cheese', None],
 ['Onion', 'Butter', 'Water', None]]

Как видите, после преобразования в нашем списке все еще остаются значения None. Если мы скармливаем его модели, Apriori выдаст ошибку.

#Removing None values in list, 2 dimensions
df_ = list()
for _ in df:
  #using list comprehension 
  _ = [x for x in _ if x is not None]
  df_.append(_)
df = df_
df
[['Onion', 'Sausages', 'Cheese', 'Butter'],
 ['Onion', 'Sausages', 'Water', 'Sugar'],
 ['Onion', 'Water', 'Sausages'],
 ['Butter', 'Sugar', 'Eggs'],
 ['Butter', 'Sugar', 'Eggs', 'Cheese'],
 ['Water', 'Cheese', 'Eggs'],
 ['Water', 'Butter'],
 ['Onion', 'Butter', 'Sugar'],
 ['Onion', 'Butter', 'Cheese'],
 ['Onion', 'Butter', 'Water']]

Я воссоздал список, используя df_, но отказавшись от значений None. Поскольку DataFrame был структурирован с использованием вложенных списков в 2 измерениях, этот алгоритм не применяется, если вы хотите удалить None в многомерных списках.

#one_hot encoding (boolean output)
te = TransactionEncoder()
te_ary = te.fit(df).transform(df)
df = pd.DataFrame(te_ary, columns=te.columns_)
df

Scikit-Learn не поддерживает априорный алгоритм, для этого я установил mlxtend. Он преобразует двумерный список в DataFrame в кодировке one_hot.

Как уже упоминалось выше, это должен быть конечный результат:

Для каждого покупателя покупка одного ингредиента будет эквивалентна True, а не покупка False. Как видите, алгоритм априори не учитывает количества, а учитывает только то, был ли товар куплен или нет.

4. Извлечение часто встречающихся наборов элементов.

frequent_itemsets = apriori(df, min_support=0.4, use_colnames=True)
frequent_itemsets

5. Извлечь правила ассоциации

Среди всех элементов я выберу те, которые имеют минимальную достоверность 0,4:

association_rules(frequent_itemsets, metric="confidence", min_threshold=0.4)

6. Извлечь правила

На этом шаге я установлю минимальный порог подъемной силы 0,7:

rules = association_rules(frequent_itemsets, metric="lift", min_threshold=.7)

7. Определите порог и извлеките окончательные ассоциации.

rules["antecedent_len"] = rules["antecedents"].apply(lambda x: len(x))

Как мы видим, люди, которые покупают лук, скорее всего, купят масло, и это правило действует и наоборот.

Сделайте выбор исходя из специфики

Если вы хотите выбрать правила ассоциации на основе порогового значения, вам будет полезен этот алгоритм.

rules[ (rules['antecedent_len'] >= 1) &
       (rules['confidence'] > 0.75) &
       (rules['lift'] > 1.2) ]

Сделайте выбор по ингредиентам

#select the ones you want
rules[rules['antecedents'] == {'Onion'}]