Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Васильев Ю. - Python для data science (Библиотека программиста) - 2023.pdf
Скачиваний:
7
Добавлен:
07.04.2024
Размер:
7.21 Mб
Скачать

228      Глава 11. Получение инсайтов из данных

Как и поддержка, доверие находится в диапазоне от 0 до 1, но, в отличие от поддержки, оно не симметрично. Это означает, что метрика доверия для правила творог -> сметанаможет отличаться от доверия для правила сметана -> творог:

доверие(сметана -> творог) = (творог & сметана) / сметана = 20 / 30 = 0.66

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

Лифт

Лифт (lift) оценивает значимость ассоциативного правила для случая, когда элементы правила оказываются в одной транзакции случайно. Лифт ассоциативного правила творог -> сметана — это отношение наблюдаемой поддержки для творог -> сметанак ожидаемой, если бы покупка творога и покупка сметаны были независимы друг от друга. Рассчитать лифт можно следующим образом:

лифт(сметана -> творог) = поддержка(творог & сметана) / (поддержка (творог) *

поддержка(сметана)) = 0.2 / (0.25 * 0.3) = 2.66

Метрика лифта симметрична — если поменять местами антецедент и консеквент, значение метрики не изменится. Коэффициент лифта варьируется от 0 до бесконечности, и чем больше этот коэффициент, тем сильнее связь. В частности, коэффициент лифта, больший 1, указывает на то, что связь между антецедентом и консеквентом сильнее, чем можно было бы ожидать, если бы они были независимыми, то есть эти два товара часто покупают вместе. Коэффициент лифта, равный 1, указывает на отсутствие корреляции между антецедентом и консеквентом. Коэффициент лифта, меньший 1, говорит о наличии отрицательной корреляции между антецедентом и консеквентом. Это означает, что их вряд ли купят вместе. В данном случае коэффициент лифта 2.66 можно интерпретировать так: когда клиент покупает творог, ожидаемая вероятность того, что он также купит сметану, увеличивается на 166%.

Алгоритм Apriori

Теперь вы знаете, что собой представляют ассоциативные правила и некоторые метрики оценки их значимости, но как создавать ассоциативные правила для

Алгоритм Apriori      229

анализа потребительской корзины? Один из способов — использовать алгоритм Apriori (Apriori algorithm), автоматизированный процесс анализа данных о транз­ акциях. В общих чертах этот алгоритм состоит из двух шагов:

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

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

После создания ассоциативных правил их значимость можно оценить с помощью метрик из предыдущего раздела.

Несколько сторонних библиотек Python поставляются с реализацией алгоритма Apriori. Одна из них — библиотека mlxtend (сокращение от machine learning extensions). Библиотека mlxtend включает инструменты для решения ряда общих задач в области data science. В этом разделе мы рассмотрим пример анализа потребительской корзины с помощью реализации алгоритма Apriori. Но сначала установим mlxtend с помощью pip:

$ pip install mlxtend

ПРИМЕЧАНИЕ

Чтобы узнать больше о mlxtend, обратитесь к документации библиотеки1.

Создание датасета с транзакциями

Для проведения анализа потребительской корзины понадобятся данные о нескольких транзакциях. Для простоты можно использовать всего несколько транзакций, реализованных в виде списка списков, как показано ниже:

transactions = [

['curd', 'sour cream'], ['curd', 'orange', 'sour cream'],

['bread', 'cheese', 'butter'], ['bread', 'butter'], ['bread', 'milk'], ['apple', 'orange', 'pear'], ['bread', 'milk', 'eggs'], ['tea', 'lemon'],

1 http://rasbt.github.io/mlxtend

230      Глава 11. Получение инсайтов из данных

['curd', 'sour cream', 'apple'], ['eggs', 'wheat flour', 'milk'], ['pasta', 'cheese'], ['bread', 'cheese'], ['pasta', 'olive oil', 'cheese'], ['curd', 'jam'], ['bread', 'cheese', 'butter'],

['bread', 'sour cream', 'butter'], ['strawberry', 'sour cream'], ['curd', 'sour cream'], ['bread', 'coffee'], ['onion', 'garlic']

] 1

Каждый внутренний список содержит набор товаров одной транзакции. Внешний список transactions содержит в общей сложности 20 транзакций. Для сохранения количественных пропорций, определенных в исходном примере творог/ сметана, датасет содержит пять операций с творогом (curd), шесть операций со сметаной (sour cream) и четыре операции, содержащие и творог, и сметану.

Чтобы пропустить данные транзакций через алгоритм Apriori библиотеки mlxtend, необходимо преобразовать их в булев массив, созданный с помощью быстрого кодирования (OHE, one-hot encoding), то есть структуру, где каждый столбец представляет доступный товар, а строка — транзакцию. Значения массива могут быть равны либо True, либо False (True, если транзакция включала данный конкретный товар, и False — если нет). Во фрагменте кода ниже мы выполняем необходимое преобразование, используя объект mlxtend TransactionEncoder:

import pandas as pd

from mlxtend.preprocessing import TransactionEncoder

encoder = TransactionEncoder()

encoded_array = encoder.fit(transactions).transform(transactions)df_itemsets = pd.DataFrame(encoded_array, columns=encoder.columns_)

Мы создаем объект TransactionEncoder и используем его для преобразования списка списков transactions в булев OHE-массив с названием encoded_array . Затем преобразуем массив в pandas DataFrame df_itemsets , фрагмент которого приведен ниже:

 

apple

bread

butter

cheese

coffee

curd

eggs

...

0

False

False

False

False

False

True

False

...

1

False

False

False

False

False

True

False

...

2

False

True

True

True

False

False

False

...

3

False

True

True

False

False

False

False

...

4

False

True

False

False

False

False

False

...

1curd — творог, sour cream — сметана, orange — апельсин, bread — хлеб, cheese — сыр, butter — масло, milk — молоко, apple — яблоко, pear — груша, eggs — яйца, tea — чай, lemon — лимон, wheat flour — пшеничная мука, pasta — макароны, olive oil — оливковое масло, jam — джем, strawberry — клубника, coffee — кофе, onion — лук, garlic — чеснок. — Примеч. пер.

Алгоритм Apriori      231

5

True

False

False

False

False

False

False

...

6

False

True

False

False

False

False

True

...

--фрагмент

 

 

 

 

 

 

 

[20

rows x 20 columns]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Датафрейм состоит из 20 строк и 20 столбцов. Строки представляют собой транзакции, а столбцы — товары. Чтобы проверить, что в исходном списке списков действительно было 20 транзакций, основанных на 20 доступных товарах, используйте следующий код:

print('Number of transactions: ', len(transactions)) print('Number of unique items: ', len(set(sum(transactions, []))))

В обоих случаях должно получиться 20.

Определение часто встречающихся наборов

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

from mlxtend.frequent_patterns import apriori

frequent_itemsets = apriori(df_itemsets, min_support=0.1, use_colnames=True)

Из модуля mlxtend.frequent_patternsимпортируем функцию apriori(). Затем вызываем ее, передавая датафрейм с данными о транзакциях в качестве первого параметра. Также устанавливаем для параметра min_support значение 0.1, чтобы возвращать наборы с поддержкой не менее 10% (помните, что метрика поддержки показывает, в каком проценте транзакций встречается товар или группа товаров). Для use_colnames мы устанавливаем значение True, чтобы определить столбцы, включаемые в каждый набор товаров, по их названию (например, curd или sour cream), а не по индексу. В результате apriori() возвращает следующий датафрейм:

 

support

itemsets

0

0.10

(apple)

1

0.40

(bread)

2

0.20

(butter)

3

0.25

(cheese)

4

0.25

(curd)

5

0.10

(eggs)

232 

   

Глава 11. Получение инсайтов из данных

6

0.15

(milk)

7

0.10

(orange)

8

0.10

(pasta)

9

0.30

(sour cream)

10

0.20

(bread, butter)

11

0.15

(bread, cheese)

12

0.10

(bread, milk)

13

0.10

(cheese, butter)

14

0.10

(pasta, cheese)

15

0.20

(sour cream, curd)

16

0.10

(milk, eggs)

17

0.10

(bread, cheese, butter)

 

 

 

Как уже отмечалось, набор товаров может состоять из одного или нескольких позиций, и действительно, apriori()вернул несколько наборов с одним товаром. В конечном итоге mlxtend не будет учитывать наборы с одним товаром при составлении ассоциативных правил; тем не менее ему понадобятся данные обо всех часто встречающихся наборах (включая те, которые содержат один товар). Ради интереса можете выбрать только те наборы товаров, которые содержат несколько позиций. Для этого добавьте колонку length к датафрейму frequent_itemsets:

frequent_itemsets['length'] = frequent_itemsets['itemsets'].apply(lambda itemset: len(itemset))

Затем, используя синтаксис pandas, отфильтруйте датафрейм так, чтобы остались только те строки, значение поля length которых равно или больше 2:

print(frequent_itemsets[frequent_itemsets['length'] >= 2])

Вы получите датафрейм, который не содержит наборов с одним товаром:

10

0.20

(bread,

butter)

2

11

0.15

(bread,

cheese)

2

12

0.10

(bread, milk)

2

13

0.10

(cheese, butter)

2

14

0.10

(pasta, cheese)

2

15

0.20

(sour cream, curd)

2

16

0.10

(milk, eggs)

2

17

0.10

(bread, cheese, butter)

3

 

 

 

 

 

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