Шаг 49.
Однострочники Python. Наука о данных. Простейший анализ ассоциаций: купившие товар X покупают и товар Y

    На этом шаге мы проведем небольшое введение в анализ ассоциаций.

    Случалось ли вам покупать товары по рекомендациям Amazon? В основе алгоритмов рекомендации часто лежит методика так называемого анализа ассоциаций (association analysis). На этом шаге вы узнаете основные идеи такого анализа и окунетесь в бездну рекомендательных систем.

Общее описание

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

    Рассмотрим практический пример на рисунке 1.


Рис.1. Матрица "Товар - Покупатель": какой покупатель купил какие товары?

    Четыре покупателя - Алиса, Боб, Луи и Лариса - купили различные сочетания товаров: книгу, игру, футбольный мяч, ноутбук и наушники. Пусть вам известны все продукты, купленные каждым из них, за исключением того, что Луи купил ноутбук. Как вы думаете, насколько вероятно, что Луи его купит?

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

    Следующий фрагмент кода упрощает решение этой задачи.

Код

    Попробуем ответить на вопрос: какая доля покупателей купит две книги сразу? На основе этих данных рекомендательная система может предложить покупателям купить "набор" книг, если изначально похоже, что они собираются купить только одну (пример 3.29).


Пример 3.29. Однострочное решение, использующее срезы, аргумент axis, свойство shape и простейшие арифметические операции над массивами с транслированием
## Зависимости
import numpy as np

## Данные: каждая строка соответствует корзине для покупок конкретного покупателя
## строка = [курс 1, курс 2, эл. книга 1, эл. книга 2]
## значение 1 означает, что товар был куплен
basket = np.array([[0, 1, 1, 0],
                   [0, 0, 0, 1],
                   [1, 1, 0, 0],
                   [0, 1, 1, 1],
                   [1, 1, 1, 0],
                   [0, 1, 1, 0],
                   [1, 1, 0, 1],
                   [1, 1, 1, 1]])

## Однострочник
copurchases = np.sum(np.all(basket[:, 2:], axis=1)) / basket.shape[0]

## Результат
print(copurchases)
Архив с файлом можно взять здесь.

    Какими же будут результаты выполнения этого фрагмента кода?

Принцип работы

    Массив данных basket содержит по одной строке для каждого покупателя и по столбцу для каждого товара. Первые два товара с индексами столбцов 0 и 1 - онлайн-курсы, а последние два с индексами столбцов 2 и 3 - электронные книги. Значение 1 в ячейке (i, j) означает, что покупатель i купил товар j.

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

print(basket[:,2:])
# [[1 0]
#  [0 1]
#  [0 0]
#  [1 1]
#  [1 0]
#  [1 0]
#  [0 1]
#  [1 1]]

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

    Функция all() библиотеки NumPy проверяет, все ли значения в заданном массиве NumPy равны True. В этом случае она возвращает True. В противном случае она возвращает False. При указании аргумента axis функция all() делает то же самое, но по заданной оси.


Вы наверняка обратите внимание, что аргумент axis снова и снова встречается во многих функциях NumPy, поэтому имеет смысл потратить немного времени и разобраться с ним как следует. Указанная ось координат схлопывается в одно значение в зависимости от соответствующей агрегирующей функции (в данном случае all()).

    Следовательно, в результате применения функции all() к подмассиву получится следующее:

print(np.all(basket[:,2:], axis=1))
# [False False False True False False False True]

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

    А поскольку нас интересует доля покупателей, мы суммируем этот булев массив, получая в результате 2, и делим полученное на количество покупателей, 8. В результате мы получаем 0.25 - долю покупателей, купивших обе электронные книги.

    Резюмируя: вы укрепили свое знание основ библиотеки NumPy, таких как атрибут shape и аргумент axis, а также научились использовать их вместе для анализа совместных покупок различных товаров. Далее мы продолжим работу над этим примером и изучим более продвинутые методики агрегирования массивов с помощью сочетания нескольких особых возможностей NumPy и Python, а именно транслирования и спискового включения.

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




Предыдущий шаг Содержание Следующий шаг