Пошаговый пример того, как специалисты по данным подходят к кластерному анализу и выполняют его.

Возвращаясь к моему времени, когда я был студентом бакалавриата по статистике, есть день, который выделяется. Это был первый день модуля многомерного анализа. Этот класс был новым в то время, и, к нашему удивлению, профессор решил сделать что-то другое. Вместо того, чтобы пройтись по повестке дня на семестр, он закрыл свет и объявил, что сегодня мы узнаем о модуле иначе — посмотрев пилотную серию сериала «Numb3rs».

Сериал посвящен специальному агенту ФБР Дону Эппесу и его брату Чарльзу Эппесу, блестящему математику, который использует науку о данных, чтобы разыскивать самых хитрых преступников. В частности, в пилотном эпизоде ​​Чарльз использует кластерный анализ, чтобы выяснить местонахождение преступника. Излишне говорить, что мы все были на крючке.

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

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

  • Введение в кластеризацию:понимание трех основных блоков кластерного анализа
  • Пошаговое исследование кластеризации в R: визуализация данных, обработка данных, вычисление матрицы сходства (расстояний), выбор количества кластеров и описание результатов.

1. Введение в кластеризацию

1.1. Какова цель кластеризации?

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

1.2. Как работает кластеризация?

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

С другой стороны, кластеризация — это неконтролируемый метод машинного обучения. Набор данных не имеет метки (отсюда и название неконтролируемый). Вместо этого цель состоит в том, чтобы создать новую метку в форме назначения кластера. Каждый кластерный анализ будет отличаться, но в каждом случае есть три основных строительных блока или шага, если вы предпочитаете:

  1. Создайте набор данных, уникальный по строке для объекта, который вы хотите кластеризовать. Поэтому, если вы хотите сгруппировать клиентов, каждая строка должна представлять отдельного клиента. Для каждой из этих строк у вас будут атрибуты (столбцы), которые описывают определенные характеристики, такие как доход за последний год, любимый продукт, количество дней с момента последней покупки и т. д.
  2. Вычислите сходство между каждой строкой и всеми остальными в вашем наборе данных (на основе доступных атрибутов). Таким образом, у нас будет значение сходства между первой и второй строкой, первой и третьей строкой, второй и третьей строкой и так далее. Наиболее часто используемыми функциями подобия являются расстояния. Мы рассмотрим их более подробно в тематическом исследовании следующего раздела, поскольку они лучше объясняются на примере.
  3. Введите матрицу подобия в алгоритм кластеризации. В R и Python их много, например k-means, иерархический и PAM. Алгоритмы кластеризации имеют простую цель. Распределите наблюдения по кластерам так, чтобы наблюдения внутри кластера были как можно более похожими, а наблюдения между разными кластерами — как можно более непохожими. В итоге у вас будет кластерное назначение для каждой строки (наблюдение)

2. Пошаговое исследование кластеризации в R

Несмотря на то, что я не смог найти набор данных, использованный в пилотном эпизоде ​​сериала Numb3rs, я подумал, что было бы уместно использовать что-то подобное для нашего исследования, поэтому я выбрал Набор данных об арестах в США, загруженный из пакет datasets (часть базовойбиблиотеки в R).

Набор данных содержит 50 строк и 4 атрибута. Каждая строка представляет собой штат США (объект). Четыре атрибута описывают следующие характеристики каждого состояния:

  • Убийство: количество арестов за убийство на 100 000 жителей в 1975 г.
  • Нападение: количество арестов в связи с нападением на 100 000 жителей в 1975 г.
  • Изнасилование: количество арестов за изнасилование на 100 000 жителей в 1975 году.
  • UrbanPop: процент населения, проживающего в городских районах в 1975 году.
  • У нас также есть имя состояния в качестве имен строк. Это не будет использоваться в качестве входных данных для алгоритма кластеризации.
##############################
# Loading libraries
##############################
library("dplyr")        # summarizing data
library("ggplot2")      # visualization
library("cluster")      # gower distance and PAM
library("ggalluvial")   # alluvial plots


##############################
# Loading the data set
##############################
data("USArrests")

##############################
# Examine data set
##############################
head(USArrests)   # head -> header

2.1. Визуализация данных

Глядя на диаграммы ниже, все четыре атрибута кажутся примерно симметричными (UrbanPop немного смещен вправо, а Rape — немного влево). Если атрибут был сильно искажен или имелись выбросы, мы могли бы рассмотреть возможность применения других преобразований (например, логарифмического преобразования). С нашим набором данных в этом нет необходимости.

##############################
# Box plot for each attribute
##############################
USArrests %>% 
  select(c(Murder, Assault, Rape, UrbanPop)) %>%
  boxplot(.,
    boxwex = 0.7, 
    alpha = 0.2, 
    col = c("red3", "lightgreen", "lightblue", "purple"), 
    horizontal = TRUE
  )

Вы также можете видеть, что атрибут Нападение имеет гораздо более высокие значения, чем остальные три. Хорошей практикой при кластеризации является стандартизация всех атрибутов в одном масштабе перед вычислением сходства. Это делается для того, чтобы атрибуты в большем масштабе не вносили чрезмерный вклад (Нападение измеряется сотнями, тогда как остальные три атрибута исчисляются десятками). К счастью, функция подобия, которую мы будем использовать, позаботится об этом, поэтому на данном этапе нам не нужно выполнять масштабирование.

2.2. Вычисление матрицы подобия

В нашем примере мы будем использовать расстояние Гауэраиз функции daisy (кластерныйпакет) в R для вычисления матрицы подобия. Чтобы быть более конкретным, Гауэр использует несходства как функцию расстояния, но концепция остается той же (вместо того, чтобы максимизировать сходство, мы минимизируем несходство).

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

Таким образом, для нашего набора данных с n = 50 строк (состояний) у нас будет матрица 50x50 с 1225 уникальными значениями (n*(n-1)/2). Диагональ не нужна (расстояние состояния с самим собой), а верхний треугольник такой же, как и нижний (матрица симметрична).

##############################
# Get distance
##############################
gower_dist <- 
  USArrests %>% 
  select(c(Murder, Assault, Rape, UrbanPop)) %>%
  daisy(.,metric = "gower")

gower_dist

2.3. Выбор количества кластеров

В нашем примере мы будем использовать алгоритм кластеризации PAM (Partitioning Around Medoids) и, в частности, функцию pam (пакет cluster).

PAM (и все другие алгоритмы K-medoid) — надежная альтернатива k-средним, поскольку в качестве центров кластеров он использует медоиды, а не средние значения. В результате алгоритм менее чувствителен к шуму и выбросам по сравнению с k-средними (но не невосприимчив!).

Во-первых, нам нужно выбрать количество кластеров. Подход к определению количества кластеров довольно прост. Мы запустим алгоритм PAM, используя матрицу подобия Гауэра, которую мы вычислили на предыдущем шаге, и в каждом запуске мы будем выбирать разное количество кластеров (от 2 до 10). Затем мы рассчитаем среднюю ширину силуэта (ASW) для каждого прогона. Мы сделаем это, используя функцию ниже.

##############################
# Function to compute ASW 
##############################
get_asw_using_pam <- function(distance, min_clusters, max_clusters) {
  average_sil_width <- c(NA)
  for (i in min_clusters:max_clusters){
    pam_fit <- 
      pam(
        distance,
        diss = TRUE,
        k=i)
    average_sil_width[i] <- pam_fit$silinfo$avg.width
  }
  return(average_sil_width)
  }

############################
## Get ASW from each run
############################
sil_width <- get_asw_using_pam(gower_dist, 2, 10)

ASW показывает, насколько хорошо каждое наблюдение соответствует своему текущему кластеру по сравнению с ближайшим соседним кластером. Он находится в диапазоне от -1 до 1, причем более высокие значения (ближе к 1) указывают на лучшие результаты кластеризации. Мы будем использовать график силуэта (ASW на оси y и количество кластеров на оси x), чтобы визуально изучить перспективных кандидатов для нашей кластеризации.

##############################
# Visualize Silhouette Plot
##############################
silhouette_plot <- sil_width %>% as.data.frame()
names(silhouette_plot)[names(silhouette_plot) == '.'] <- 'sil_width'

silhouette_plot %>%
  mutate(number = c(1:10)) %>%
  filter(number > 1) %>%
  ggplot(aes(x = number , y = sil_width)) +
  geom_line( color="turquoise3", size=1) +
  geom_point(color="darkgrey",fill = "black", size=3) +
  scale_x_continuous(breaks = seq(2, 10, 1) ) +
  ylab("Average Silhouette Width") +
  xlab("No of Clusters") +
  theme_classic()

Решение с наибольшим значением ASW составляет 2 кластера, а после резкого снижения имеем 3 и 4 кластера, после чего ASW снова резко уменьшается. Нашими возможными кандидатами являются эти три варианта (кластеры 2, 3 и 4). Давайте сохраним назначение кластеризации из каждого прогона в виде трех новых атрибутов (cluster_2, cluster_3 и cluster_4) в наборе данных USArrests.

## Set the seed of R's random number generator
## which is useful for creating reproducible simulations
## like in cases of clustering assignment
set.seed(5)

##############################
# Saving PAM results
##############################
pam_2 <- pam(gower_dist, diss = TRUE, k= 2 )
pam_3 <- pam(gower_dist, diss = TRUE, k= 3 )
pam_4 <- pam(gower_dist, diss = TRUE, k= 4 )


##############################
# Adding assignment as columns
##############################
USArrests <-
  USArrests %>%
  mutate(cluster_2 = as.factor(pam_2$clustering)) %>%
  mutate(cluster_3 = as.factor(pam_3$clustering)) %>%  
  mutate(cluster_4 = as.factor(pam_4$clustering))

2.4. Описание кластерных решений

Поскольку кластеризация — это неконтролируемый метод, важно помнить, что, по сути, это исследовательский анализ (EDA) на стероидах. Таким образом, в отличие от контролируемых методов, мы не можем оценить точность нашего решения кластеризации (в наборе данных нет метки для сравнения). Вместо этого «качество» вашего кластерного анализа будет оцениваться на основе другого критерия:

Разделены ли получившиеся кластеры таким образом, чтобы они отражали аспекты, которые имели в виду заинтересованные стороны бизнеса?

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

Во-первых, мы хотим изучить, как связаны между собой различные решения кластеризации. Мы будем использовать аллювиальный график, чтобы визуализировать поток наблюдений (состояний) между тремя прогонами.

##############################
# Alluvial plot
##############################
aluv <- 
  USArrests %>%
  group_by(cluster_2, cluster_3, cluster_4) %>%
  summarise(Freq = n()) 

alluvial(
  aluv[,1:3],
  freq=aluv$Freq, 
  border="lightgrey", 
  gap.width=0.2,
  alpha=0.8,
  col =  
    ifelse( 
      aluv$cluster_4 == 1, "red", 
      ifelse(aluv$cluster_4 == 2, "lightskyblue", 
      ifelse(aluv$cluster_4 == 3 & aluv$cluster_3 == 2, "lightskyblue4", 
      ifelse(aluv$cluster_4 == 3 & aluv$cluster_3 == 2, "purple",              
      "orange")))),
  cex=0.65
  ) 

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

Например, красная лента представляет штаты Алабама, Джорджия, Луизиана, Миссисипи, Северная Каролина, Южная Каролина и Теннесси (см. код ниже). Эти состояния были отнесены к тому же кластеру («1»), что и состояния с синей ленты в прогоне с двумя и тремя кластерами (кластер_2 и кластер_3), но были разделены в прогоне с четырьмя кластерами (кластер_4).

##################################################
# Filter for the red ribbon (cluster_4 = 1)
##################################################
USArrests %>% filter(cluster_4 == "1")

Далее мы хотим лучше понять характеристики каждого кластера и чем они отличаются между тремя решениями.

##################################################
# Summarizing (average) attributes, 2 clusters
##################################################
USArrests %>% 
  group_by(cluster_2)  %>%
  summarise(
    count = n(),
    mean_murder = mean(Murder),
    mean_assault = mean(Assault),
    mean_rape = mean(Rape),
    mean_urbanpop = mean(UrbanPop)
    )


##################################################
# Summarizing (average) attributes, 3 clusters
##################################################
USArrests %>% 
  group_by(cluster_3)  %>%
  summarise(
    count = n(),
    mean_murder = mean(Murder),
    mean_assault = mean(Assault),
    mean_rape = mean(Rape),
    mean_urbanpop = mean(UrbanPop)
    )


##################################################
# Summarizing (average) attributes, 4 clusters
##################################################
USArrests %>% 
  group_by(cluster_4)  %>%
  summarise(
    count = n(),
    mean_murder = mean(Murder),
    mean_assault = mean(Assault),
    mean_rape = mean(Rape),
    mean_urbanpop = mean(UrbanPop)
    )

Запуск с двумя кластерами:

  • Кластер «1» имеет более высокий средний показатель арестов по всем преступлениям.
  • Нет заметной разницы в среднем городском населении %

Запуск с тремя кластерами:

  • Три кластера кажутся хорошо разделенными
  • По сравнению с высокими (кластер «1») и низкими (кластер «2») задержаниями при прогоне с двумя кластерами теперь у нас есть высокие (кластер «1»), средние (кластер «2») и низкие аресты (кластер «2»). «3»)
  • Кластер «3» также имеет значительно более низкую среднюю долю городского населения, %

Запуск с четырьмя кластерами:

  • Разделение не такое четкое
  • Средний (кластер «2») и низкий (кластер «3») кластеры из серии с тремя кластерами остались без изменений (только переименованы в «3» и «4» соответственно).
  • Максимум (кластер «1») из серии с тремя кластерами был разделен на два кластера. Кластер «1» имеет значительно более низкий средний процент городского населения, с меньшим количеством арестов за изнасилование и нападение.

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

Краткое содержание

🚀🚀 И с этим последним шагом мы достигли конца руководства. Ниже вы также можете найти краткое описание шагов:

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

✅ Визуализируйте данные, чтобы изучить асимметрию, выбросы и проблемы масштабирования.

✅ Используйте график силуэта, чтобы выбрать количество кластеров

✅ Изучите характеристики каждого кластерного решения и выберите то, которое более эффективно для бизнеса (более соответствует бизнес-целям).

По ссылке ниже вы также можете найти более подробное бесплатное пошаговое руководство в формате PDF по выполнению кластерного анализа клиентов в реальном бизнес-сценарии с использованием методов обработки данных и лучших практик. 👇



Оставайтесь на связи!

Если вам понравилось читать эту статью и вы хотите узнать больше, не забудьте подписаться, чтобы получать мои истории прямо на ваш почтовый ящик.

Рекомендации

Документация и наборы данных R были получены из проекта R и находятся под лицензией GPL. Документация OpenIntro находится под лицензией Creative Commons BY-SA 3.0.