Использование кластеризации K-средних для понимания реакции маркетинга
Обзор
Цель этой статьи - показать, что вам не всегда нужны сверхсложные и изощренные модели машинного обучения, чтобы получать осмысленную информацию из ваших данных.
В этом мини-проекте я использую популярный алгоритм Кластеризация K-средних для сегментации клиентов на основе их реакции на серию маркетинговых кампаний. Этот метод относительно легко реализовать, и тем не менее он позволил мне собрать тонны информации из моих данных и выявить интересные модели поведения в моей клиентской базе.
Что такое сегментация рынка?
Сегментация рынка относится к процессу разделения потребительского рынка существующих и / или потенциальных клиентов на группы (или сегменты) на основе общих атрибутов, интересов и поведения.
Основная идея заключается в том, что потребители, которые разделяют общие черты, с большей вероятностью будут реагировать на маркетинговую коммуникацию аналогичным образом, чтобы компании могли обратиться к каждой группе более актуальным и эффективным способом.
Что такое кластеризация K-средних?
Кластеризация K-средних является частью семейства моделирования Неконтролируемое обучение, набора методов, используемых для поиска закономерностей в данных, которые не были помечены, классифицированы или категоризированы. Поскольку этот метод не требует наличия цели для кластеризации, он может оказаться большим подспорьем на исследовательской фазе сегментации клиентов.
Основная идея состоит в том, что клиенты, отнесенные к группе, максимально похожи, тогда как клиенты, принадлежащие к разным группам, максимально различны. Каждый кластер представлен своим centre
, соответствующим среднему значению элементов, назначенных кластеру.
Чтобы проиллюстрировать принцип, предположим, что у вас есть набор элементов, подобных показанным на рисунке ниже, и вы хотите классифицировать их на 3 кластера.
K-Means могут сгруппировать их вокруг середины или centre
каждого кластера, представленного здесь «X», таким образом, чтобы минимизировать расстояние между каждым элементом до это centre
Итак, как это поможет вам лучше понять своих клиентов? Что ж, в этом случае вы можете использовать их поведение (в частности, какое предложение они сделали или не использовали) как способ сгруппировать их с единомышленниками. Теперь вы можете изучить каждую из этих групп, чтобы выявить тенденции и закономерности и использовать их для формирования будущих предложений.
В более техническом отношении, важно отметить, что существует множество доступных алгоритмов K-средних (Хартиган-Вонг, Ллойд, MacQueen, и это лишь некоторые из них), но все они разделяют одну и ту же базовую концепцию: каждый элемент назначается кластеру, так что он сводит к минимуму сумму евклидова расстояния в квадратах до centre
- a процесс также называется минимизацией общей суммы квадратов внутри кластера (tot.withinss
).
Загрузка пакетов
library(tidyverse)
library(lubridate)
library(knitr)
library(readxl)
library(broom)
library(umap)
library(ggrepel)
Данные
Набор данных взят из книги Джона Формана Data Smart. Он содержит данные рекламных акций для вымышленного розничного продавца вин и включает подробную информацию о 32 рекламных акциях (включая ассортимент вин, минимальное количество покупок, процентную скидку и страна происхождения), а также список из 100 клиентов и рекламных акций, на которые они откликнулись.
offers_tbl <- read_excel('../00_data/WineKMC.xlsx', sheet = 'OfferInformation')
offers_tbl <- offers_tbl %>% set_names(c('offer', 'campaign', 'varietal', 'min_qty_kg', 'disc_pct','origin','past_peak') )
head(offers_tbl)
## # A tibble: 6 x 7 ## offer campaign varietal min_qty_kg disc_pct origin past_peak ## <dbl> <chr> <chr> <dbl> <dbl> <chr> <chr> ## 1 1 January Malbec 72 56 France FALSE ## 2 2 January Pinot Noir 72 17 France FALSE ## 3 3 February Espumante 144 32 Oregon TRUE ## 4 4 February Champagne 72 48 France TRUE ## 5 5 February Cabernet~ 144 44 New Zeala~ TRUE ## 6 6 March Prosecco 144 86 Chile FALSE
transac_tbl <- read_excel('../00_data/WineKMC.xlsx', sheet = 'Transactions')
transac_tbl <- transac_tbl %>% set_names(c('customer', 'offer') )
head(transac_tbl)
## # A tibble: 6 x 2 ## customer offer ## <chr> <dbl> ## 1 Smith 2 ## 2 Smith 24 ## 3 Johnson 17 ## 4 Johnson 24 ## 5 Johnson 26 ## 6 Williams 18
Данные необходимо преобразовать в User-Item format
(также известную как матрица "клиент-продукт"), в которой клиенты вверху, а предложения внизу. Ячейки заполнены значениями 0 и 1, где 1 указывает, ответил ли клиент на конкретное предложение.
Этот тип матрицы также известен как двоичная рейтинговая матрица и НЕ требует нормализации.
wine_tbl <- transac_tbl %>% left_join(offers_tbl) %>% mutate(value = 1) %>% spread(customer,value, fill = 0)
head(wine_tbl)
## # A tibble: 6 x 107 ## offer campaign varietal min_qty_kg disc_pct origin past_peak ## <dbl> <chr> <chr> <dbl> <dbl> <chr> <chr> ## 1 1 January Malbec 72 56 France FALSE ## 2 2 January Pinot Noir 72 17 France FALSE ## 3 3 February Espumante 144 32 Oregon TRUE ## 4 4 February Champagne 72 48 France TRUE ## 5 5 February Cabernern~ 144 44 New Zea~ TRUE ## 6 6 March Prosecco 144 86 Chile FALSE ## # ... with 100 more variables: Adams <dbl>, Allen <dbl>, Anderson <dbl>, Bailey <dbl>, Baker <dbl>, Barnes <dbl>, ...
Кластеризация клиентов
Алгоритм K-средних поставляется с пакетом stats, одной из основных системных библиотек в R, и довольно прост в использовании. Мне просто нужно передать несколько параметров функции kmeans ().
user_item_tbl <- wine_tbl[,8:107]
set.seed(196) kmeans_obj <- user_item_tbl %>% kmeans(centers = 5, # number of clusters nstart = 100, # number of random sets to be chosen iter.max = 50) # max number of iterations allowed
Я могу быстро проверить модель с помощьюglance()
из broom
пакета, который предоставляет сводную статистику на уровне модели.
glance(kmeans_obj) %>% glimpse()
## Observations: 1 ## Variables: 4 ## $ totss <dbl> 283.1875 ## $ tot.withinss <dbl> 189.7255 ## $ betweenss <dbl> 93.46201 ## $ iter <int> 3
Единственная метрика, за которой действительно следует следить, - это общая сумма квадратов внутри кластера (или tot.withinss
), поскольку оптимальное количество кластеров - это то, которое минимизирует tot.withinss
.
Итак, я хочу подогнать модель k-средних для разного количества кластеров и посмотреть, где tot.withinss
достигает своего минимума.
Сначала я создаю функцию для заданного числа centers
(в данном случае 4) и проверяю, что она работает на glance()
.
kmeans_map <- function(centers = 4) { user_item_tbl %>% kmeans(centers = centers, nstart = 100, iter.max = 50) }
4 %>% kmeans_map() %>% glance()
## # A tibble: 1 x 4 ## totss tot.withinss betweenss iter ## <dbl> <dbl> <dbl> <int> ## 1 283. 203. 80.0 2
Затем я создаю вложенный тиббл, который представляет собой способ «вложения» столбцов во фрейм данных.
Во вложенных фреймах данных замечательно то, что вы можете поместить в них практически все, что захотите: списки, модели, фреймы данных, графики и т. Д.!
kmeans_map_tbl <- tibble(centers = 1:15) %>% # create column with centres
mutate(k_means = centers %>% map(kmeans_map)) %>% # iterate `kmeans_map` row-wise to # gather kmeans models for each centre
mutate(glance = k_means %>% map(glance)) # apply `glance()` row-wise to gather # each model’s summary metrics
kmeans_map_tbl %>% glimpse()
## Observations: 15 ## Variables: 3 ## $ centers <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ... ## $ k_means <list> [<1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... ## $ glance <list> [<tbl_df[1 x 4]>, <tbl_df[1 x 4]>, ...
Наконец, я могу построить scree plot
и искать «изгиб» на графике, точку, где количество дополнительных кластеров, кажется, выравнивается. В этом случае 5 представляется оптимальным числом, так как падение tot.withinss
для 6 не так ярко выражено, как предыдущее.
kmeans_map_tbl %>%
unnest(glance) %>% # unnest the glance column
select(centers,
tot.withinss) %>% # select centers and tot.withinss
ggplot(aes(x = centers, y = tot.withinss)) +
geom_line(colour = 'grey30', size = .8) +
geom_point(colour = 'green4', size = 3) +
geom_label_repel(aes(label = centers),
colour = 'grey30') +
theme_light() +
labs(title = 'Scree Plot')
Визуализация сегментов
Теперь, когда я определил оптимальное количество кластеров, я хочу их визуализировать. Для этого я использую UMAP (Uniform Manifold Approximation and Projection), метод уменьшения размерности, который можно использовать для визуализации кластеров аналогично Анализ главных компонентов и t-SNE .
Сначала я создаю объект umap и извлекаю аргумент layout
(содержащий координаты, которые можно использовать для визуализации набора данных), меняю его формат на тиббл и присоединяю столбец offer
из wine_tbl
.
umap_obj <- user_item_tbl %>% umap()
umap_tbl <- umap_obj$layout %>%
as_tibble() %>% # change to a tibble
set_names(c('x', 'y')) %>% # remane columns
bind_cols(wine_tbl %>% select(offer)) # attach offer reference
Затем я pluck
5-ю модель kmeans из вложенного тибла, присоединяю аргумент cluster из функции kmeans
к выходным данным и присоединяю предложение и кластер к umap_tbl.
umap_kmeans_5_tbl <- kmeans_map_tbl %>%
pull(k_means) %>%
pluck(5) %>% # pluck element 5
broom::augment(wine_tbl) %>% # attach .cluster to the tibble
select(offer, .cluster) %>%
left_join(umap_tbl,
by = 'offer') # join umap_tbl by offer
Наконец-то я могу визуализировать проекции кластеров по UMAP. plotly
добавляет приятную интерактивность, которая оживляет график!
umap_kmeans_5_tbl %>%
mutate(label_text = str_glue('Offer: {offer}
Cluster: {.cluster}')) %>%
ggplot(aes(x,y, colour = .cluster)) +
geom_point() +
geom_label_repel(aes(label = label_text), size = 3) +
theme_light() +
labs(title = 'UMAP 2D Projections of K-Means Clusters',
caption = "") +
theme(legend.position = 'none')
Оценка кластеров
Теперь мы можем, наконец, более внимательно посмотреть на отдельные кластеры, чтобы увидеть, что идентифицировал K-Means.
Но давайте сначала соберем всю информацию в одном фрейме данных.
cluster_trends_tbl <- wine_tbl %>%
left_join(umap_kmeans_5_tbl) %>%
arrange(.cluster) %>%
select(.cluster, offer:past_peak)
Кластер 1 и 2
Клиенты в кластере 1 покупают большие объемы игристых вин (шампанское и просекко), тогда как клиенты из второго сегмента предпочитают небольшие объемы закупок разных сортов.
cluster_trends_tbl %>% filter(.cluster ==1 | .cluster ==2) %>% count(.cluster, varietal, origin, min_qty_kg, disc_pct) %>% select(-n)
## # A tibble: 9 x 5 ## .cluster varietal origin min_qty_kg disc_pct ## <fct> <chr> <chr> <dbl> <dbl> ## 1 1 Champagne France 72 48 ## 2 1 Champagne New Zealand 72 88 ## 3 1 Prosecco Chile 144 86 ## 4 2 Espumante Oregon 6 50 ## 5 2 Espumante South Africa 6 45 ## 6 2 Malbec France 6 54 ## 7 2 Merlot Chile 6 43 ## 8 2 Pinot Grigio France 6 87 ## 9 2 Prosecco Australia 6 40
Кластер 3 и 4
Когда речь идет о вине, покупатели из этих групп имеют очень специфические вкусы: те, кто находится в третьем сегменте, предпочитают Пино Нуар, тогда как группа 4 покупает только французское шампанское в больших объемах.
cluster_trends_tbl %>% filter(.cluster ==3 | .cluster ==4 ) %>% group_by() %>% count(.cluster, varietal, origin, min_qty_kg, disc_pct) %>% select(-n)
## # A tibble: 6 x 5 ## .cluster varietal origin min_qty_kg disc_pct ## <fct> <chr> <chr> <dbl> <dbl> ## 1 3 Pinot Noir Australia 144 83 ## 2 3 Pinot Noir France 72 17 ## 3 3 Pinot Noir Germany 12 47 ## 4 3 Pinot Noir Italy 6 34 ## 5 4 Champagne France 72 63 ## 6 4 Champagne France 72 89
Кластер 5
Пятый сегмент немного сложнее отнести к категории, поскольку он включает в себя множество различных атрибутов. Единственная явная тенденция заключается в том, что покупатели в этом сегменте воспользовались всеми доступными предложениями Каберне Совиньон.
cluster_trends_tbl %>% filter(.cluster ==5 ) %>% count(.cluster, varietal, origin, min_qty_kg, disc_pct) %>% select(-n)
## # A tibble: 17 x 5 ## .cluster varietal origin min_qty_kg disc_pct ## <fct> <chr> <chr> <dbl> <dbl> ## 1 5 Cabernet Sauvignon France 12 56 ## 2 5 Cabernet Sauvignon Germany 72 45 ## 3 5 Cabernet Sauvignon Italy 72 82 ## 4 5 Cabernet Sauvignon Italy 144 19 ## 5 5 Cabernet Sauvignon New Zealand 144 44 ## 6 5 Cabernet Sauvignon Oregon 72 59 ## 7 5 Champagne California 12 50 ## 8 5 Champagne France 72 85 ## 9 5 Champagne Germany 12 66 ## 10 5 Chardonnay Chile 144 57 ## 11 5 Chardonnay South Africa 144 39 ## 12 5 Espumante Oregon 144 32 ## 13 5 Malbec France 72 56 ## 14 5 Merlot California 72 88 ## 15 5 Merlot Chile 72 64 ## 16 5 Prosecco Australia 72 83 ## 17 5 Prosecco California 72 52
Последние мысли
кластеризация - это мощное исследовательское упражнение, которое, хотя и не даст вам всех ответов, может помочь вам выявить закономерности в вашей потребительской базе, особенно когда у вас есть совершенно новый рынок, который нужно изучить, и у вас нет ни одного предварительное знание этого.
Его очень легко реализовать, и даже на небольшом наборе данных, подобном тому, который я использовал здесь, вы можете выявить интересные модели поведения в своей клиентской базе.
С небольшими усилиями мы пришли к выводу, что некоторые из наших клиентов предпочитают определенные сорта вина, тогда как другие предпочитают покупать большие или маленькие количества. Такую информацию можно использовать, чтобы адаптировать ваши стратегии ценообразования и маркетинговые кампании к тем клиентам, которые более склонны отвечать. Более того, сегментация клиентов позволяет более эффективно распределять маркетинговые ресурсы и максимально использовать возможности перекрестных и дополнительных продаж.
Сегментацию также можно дополнить наложением такой информации, как демографические данные клиентов (возраст, раса, религия, пол, размер семьи, этническая принадлежность, доход, уровень образования), география ( где они живут и работают) и психографические (социальный класс, образ жизни и личностные характеристики), но они выходят за рамки этого мини-проекта.
Репозиторий кода
Полный код R можно найти в моем профиле GitHub
использованная литература
- Для более широкого взгляда на потенциал сегментации клиентов
- За критику некоторых недостатков k-средних
- Сегментация клиентов в Bain & Company
Первоначально опубликовано на https://diegousai.io 25 мая 2019 г.