Полное руководство по иерархической кластеризации с помощью Python и Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Полное руководство по иерархической кластеризации с помощью Python и Scikit-Learn

Введение

В этом руководстве мы сосредоточимся на реализации Алгоритм иерархической кластеризации с помощью Scikit-Learn решить маркетинговую задачу.

Прочитав руководство, вы поймете:

  • Когда применять иерархическую кластеризацию
  • Как визуализировать набор данных, чтобы понять, подходит ли он для кластеризации
  • Как предварительно обрабатывать функции и создавать новые функции на основе набора данных
  • Как уменьшить размерность набора данных с помощью PCA
  • Как использовать и читать дендрограмму для разделения на группы
  • Какие различные методы связывания и метрики расстояния применяются к дендрограммам и алгоритмам кластеризации
  • Что такое агломеративные и разделительные стратегии кластеризации и как они работают
  • Как реализовать агломеративную иерархическую кластеризацию с помощью Scikit-Learn
  • Какие наиболее частые проблемы при работе с алгоритмами кластеризации и как их решить

Примечание: Вы можете скачать блокнот, содержащий весь код в этом руководстве. здесь.

мотивация

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

Есть ли способ, которым вы могли бы помочь определить, какие клиенты похожи? Сколько из них принадлежат к одной группе? А сколько разных групп?

Один из способов ответить на эти вопросы — использовать кластеризации алгоритмы, такие как K-Means, DBSCAN, иерархическая кластеризация и т. д. В общих чертах, алгоритмы кластеризации находят сходство между точками данных и группируют их.

В этом случае наши маркетинговые данные довольно малы. У нас есть информация только о 200 клиентах. Что касается маркетинговой команды, важно, чтобы мы могли четко объяснить им, как были приняты решения на основе количества кластеров, таким образом, объяснив им, как на самом деле работает алгоритм.

Поскольку наши данные малы, а объяснимость является основным фактором, мы можем использовать Иерархическая кластеризация Для решения этой проблемы. Этот процесс также известен как Иерархический кластерный анализ (HCA).

Одним из преимуществ HCA является его интерпретируемость и хорошая работа с небольшими наборами данных.

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

Теперь, когда мы поняли проблему, которую пытаемся решить, и то, как ее решить, мы можем начать смотреть на наши данные!

Краткий исследовательский анализ данных

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

После загрузки набора данных обратите внимание, что это CSV (значения, разделенные запятыми) файл называется shopping-data.csv. Чтобы упростить исследование и обработку данных, мы загрузим их в DataFrame с помощью панд:

import pandas as pd


path_to_file = 'home/projects/datasets/shopping-data.csv'
customer_data = pd.read_csv(path_to_file)

Маркетинг заявил, что собрал 200 записей о клиентах. Мы можем проверить, заполнены ли загруженные данные 200 строками, используя shape атрибут. Он сообщит нам, сколько у нас строк и столбцов соответственно:

customer_data.shape

Это приводит к:

(200, 5)

Большой! Наши данные заполнены 200 строками (клиентские записи) и у нас тоже 5 столбцов (Особенности). Чтобы увидеть, какие характеристики собрал отдел маркетинга от клиентов, мы можем увидеть имена столбцов с columns атрибут. Для этого выполните:

customer_data.columns

Приведенный выше сценарий возвращает:

Index(['CustomerID', 'Genre', 'Age', 'Annual Income (k$)',
       'Spending Score (1-100)'],
      dtype='object')

Здесь мы видим, что маркетинг породил CustomerID, собрал Genre, Age, Annual Income (в тысячах долларов) и Spending Score от 1 до 100 для каждого из 200 клиентов. Когда их попросили уточнить, они сказали, что значения в Spending Score колонка показывает, как часто человек тратит деньги в торговом центре по шкале от 1 до 100. Другими словами, если у покупателя 0 баллов, этот человек никогда не тратит деньги, а если 100 баллов, мы только что заметили самый большой транжира.

Давайте кратко рассмотрим распределение этой оценки, чтобы изучить покупательские привычки пользователей в нашем наборе данных. Вот где панды hist() на помощь приходит метод:

customer_data['Spending Score (1-100)'].hist()

IMG

Глядя на гистограмму, мы видим, что более 35 клиентов имеют оценки между 40 и 60, то менее 25 имеют баллы между 70 и 80. Поэтому большинство наших клиентов сбалансированные траты, за которыми следуют люди с умеренными и высокими расходами. Мы также можем видеть, что есть строка после 0, слева от раздачи, и еще одна строка перед 100, справа от раздачи. Эти пустые места, вероятно, означают, что в распределении нет нетранжирящих людей, которые получили бы оценку 0, а также что нет людей с высокими расходами с оценкой 100.

Чтобы проверить, так ли это, мы можем посмотреть на минимальное и максимальное значения распределения. Эти значения можно легко найти как часть описательной статистики, поэтому мы можем использовать describe() метод, чтобы получить представление о других распределениях числовых значений:


customer_data.describe().transpose()

Это даст нам таблицу, из которой мы можем прочитать распределения других значений нашего набора данных:

 						count 	mean 	std 		min 	25% 	50% 	75% 	max
CustomerID 				200.0 	100.50 	57.879185 	1.0 	50.75 	100.5 	150.25 	200.0
Age 					200.0 	38.85 	13.969007 	18.0 	28.75 	36.0 	49.00 	70.0
Annual Income (k$) 		200.0 	60.56 	26.264721 	15.0 	41.50 	61.5 	78.00 	137.0
Spending Score (1-100) 	200.0 	50.20 	25.823522 	1.0 	34.75 	50.0 	73.00 	99.0

Наша гипотеза подтверждается. min значение Spending Score is 1 и максимум 99. Так что у нас нет 0 or 100 тратящие очки. Давайте тогда взглянем на другие столбцы транспонированного describe стол. Глядя на mean и std столбцы, мы можем видеть, что для Age домен mean is 38.85 и std примерно 13.97. То же самое происходит для Annual Income, С mean of 60.56 и std 26.26, А для Spending Score с mean of 50 и std of 25.82. Для всех функций, mean далеко от стандартного отклонения, что указывает на наши данные имеют высокую изменчивость.

Чтобы лучше понять, как меняются наши данные, построим график Annual Income распределение:

customer_data['Annual Income (k$)'].hist()

Что даст нам:

IMG

Обратите внимание на гистограмму, что большая часть наших данных, более 35 клиентов, сконцентрирована возле числа 60, на нашей mean, по горизонтальной оси. Но что происходит, когда мы приближаемся к концам распределения? Двигаясь влево, от среднего значения 60.560 34.300 долларов США следующее значение, с которым мы столкнемся, составляет 60.560 26.260 долларов США — среднее значение (26.260 34.300 долларов США) минус стандартная вариация (8.040 60 долларов США). Если мы пойдем еще дальше влево от нашего распределения данных, применяется аналогичное правило: мы вычитаем стандартную вариацию (8 26.260 долларов США) из текущего значения (XNUMX XNUMX долларов США). Таким образом, мы столкнемся со значением $XNUMX. Обратите внимание, как быстро наши данные выросли с XNUMX XNUMX до XNUMX XNUMX долларов. Каждый раз он «прыгает» на $XNUMX — сильно варьируется, поэтому у нас такая высокая вариативность.

IMG

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

До сих пор мы видели форму наших данных, некоторые их распределения и описательную статистику. С Pandas мы также можем перечислить наши типы данных и посмотреть, все ли наши 200 строк заполнены или имеют некоторые null ценности:

customer_data.info()

Это приводит к:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 200 entries, 0 to 199
Data columns (total 5 columns):
 #   Column                  Non-Null Count  Dtype 
---  ------                  --------------  ----- 
 0   CustomerID              200 non-null    int64 
 1   Genre                   200 non-null    object
 2   Age                     200 non-null    int64 
 3   Annual Income (k$)      200 non-null    int64 
 4   Spending Score (1-100)  200 non-null    int64 
dtypes: int64(4), object(1)
memory usage: 7.9+ KB

Здесь мы видим, что нет null значения в данных и что у нас есть только один категориальный столбец — Genre. На этом этапе важно иметь в виду, какие функции кажутся интересными для добавления в модель кластеризации. Если мы хотим добавить столбец «Жанр» в нашу модель, нам нужно будет преобразовать его значения из категорический в численный.

Давайте посмотрим, как Genre заполняется путем быстрого просмотра первых 5 значений наших данных:

customer_data.head() 

Это приводит к:

    CustomerID 	Genre 	Age 	Annual Income (k$) 	Spending Score (1-100)
0 	1 			Male 	19 		15 					39
1 	2 			Male 	21 		15 					81
2 	3 			Female 	20 		16 					6
3 	4 			Female 	23 		16 					77
4 	5 			Female 	31 		17 					40

Кажется, что у него есть только Female и Male категории. Мы можем убедиться в этом, взглянув на его уникальные значения с unique:

customer_data['Genre'].unique()

Это подтверждает наше предположение:

array(['Male', 'Female'], dtype=object)

Пока что мы знаем, что у нас есть только два жанра, если мы планируем использовать эту функцию на нашей модели, Male может быть преобразован в 0 и Female в 1. Также важно проверить пропорции между жанрами, чтобы увидеть, сбалансированы ли они. Мы можем сделать это с помощью value_counts() метод и его аргумент normalize=True показать процентное соотношение между Male и Female:

customer_data['Genre'].value_counts(normalize=True)

Это выводит:

Female    0.56
Male      0.44
Name: Genre, dtype: float64

У нас есть 56% женщин в наборе данных и 44% мужчин. Разница между ними всего 16%, а наши данные не 50/50, а достаточно сбалансированный чтобы не доставлять неприятностей. Если бы результаты были 70/30, 60/40, то, возможно, потребовалось либо собрать больше данных, либо применить какой-либо метод увеличения данных, чтобы сделать это соотношение более сбалансированным.

До сих пор все функции, кроме Age, были кратко исследованы. Что касается Age, обычно бывает интересно разделить его на корзины, чтобы можно было сегментировать клиентов по возрастным группам. Если мы это сделаем, нам нужно будет преобразовать возрастные категории в одно число, прежде чем добавлять их в нашу модель. Таким образом, вместо категории 15–20 лет мы будем подсчитывать количество клиентов в 15-20 категории, и это будет число в новом столбце под названием 15-20.

Совет: В этом руководстве мы представляем только краткий исследовательский анализ данных. Но вы можете пойти дальше, и вы должны идти дальше. Вы можете увидеть, есть ли разница в доходах и оценках в зависимости от жанра и возраста. Это не только обогащает анализ, но и приводит к лучшим результатам моделирования. Чтобы углубиться в исследовательский анализ данных, ознакомьтесь с глава ЭДА в «Практическое прогнозирование цен на жилье — машинное обучение в Python Управляемый проект.

После предположений о том, что можно было бы сделать с обоими категоричными – или категоричными быть – Genre и Age колонки, давайте применим то, что было обсуждено.

Переменные кодирования и разработка функций

Начнем с деления Age на группы, которые варьируются в 10, так что у нас есть 20-30, 30-40, 40-50, и так далее. Поскольку нашему самому молодому клиенту 15 лет, мы можем начать с 15 и закончить с 70, что является возрастом самого старшего клиента в данных. Начиная с 15 и заканчивая 70, у нас будут интервалы 15-20, 20-30, 30-40, 40-50, 50-60 и 60-70.

Чтобы сгруппировать или бункер Age значения в эти интервалы, мы можем использовать Pandas cut() метод, чтобы разрезать их на ячейки, а затем назначить ячейки новому Age Groups колонка:

intervals = [15, 20, 30, 40, 50, 60, 70]
col = customer_data['Age']
customer_data['Age Groups'] = pd.cut(x=col, bins=intervals)


customer_data['Age Groups'] 

Это приводит к:

0      (15, 20]
1      (20, 30]
2      (15, 20]
3      (20, 30]
4      (30, 40]
         ...   
195    (30, 40]
196    (40, 50]
197    (30, 40]
198    (30, 40]
199    (20, 30]
Name: Age Groups, Length: 200, dtype: category
Categories (6, interval[int64, right]): [(15, 20] < (20, 30] < (30, 40] < (40, 50] < (50, 60] < (60, 70]]

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

И сколько у нас клиентов в каждой категории? Мы можем быстро узнать это, сгруппировав столбец и подсчитав значения с помощью groupby() и count():

customer_data.groupby('Age Groups')['Age Groups'].count()

Это приводит к:

Age Groups
(15, 20]    17
(20, 30]    45
(30, 40]    60
(40, 50]    38
(50, 60]    23
(60, 70]    17
Name: Age Groups, dtype: int64

Легко заметить, что большинство клиентов в возрасте от 30 до 40 лет, за ними следуют клиенты в возрасте от 20 до 30 лет, а затем клиенты в возрасте от 40 до 50 лет. Это также полезная информация для отдела маркетинга.

На данный момент у нас есть две категориальные переменные, Age и Genre, которые нам нужно преобразовать в числа, чтобы иметь возможность использовать их в нашей модели. Есть много разных способов сделать это преобразование — мы будем использовать Pandas get_dummies() метод, который создает новый столбец для каждого интервала и жанра, а затем заполняет его значения нулями и единицами — такая операция называется одноразовое кодирование. Давайте посмотрим, как это выглядит:


customer_data_oh = pd.get_dummies(customer_data)

customer_data_oh 

Это даст нам предварительный просмотр результирующей таблицы:

IMG

С выводом легко увидеть, что столбец Genre был разделен на столбцы - Genre_Female и Genre_Male. Когда клиент женщина, Genre_Female равно 1, а когда клиент мужчина, он равен 0.

Так же Age Groups столбец был разделен на 6 столбцов, по одному для каждого интервала, например Age Groups_(15, 20], Age Groups_(20, 30], и так далее. Точно так же, как Genre, когда клиенту исполнилось 18 лет, Age Groups_(15, 20] Значение 1 а значение всех остальных столбцов равно 0.

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

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

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

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

Базовое построение графиков и уменьшение размерности

В нашем наборе данных 11 столбцов, и есть несколько способов визуализировать эти данные. Первый — построить его в 10-мерном пространстве (удачи в этом). Десять, потому что Customer_ID столбец не рассматривается. Второй — это построение наших первоначальных числовых признаков, а третий — преобразование наших 10 признаков в 2, то есть выполнение уменьшения размерности.

График каждой пары данных

Поскольку построить 10 измерений немного невозможно, мы выберем второй подход — мы нанесем наши первоначальные функции. Мы можем выбрать два из них для нашего кластерного анализа. Один из способов, которым мы можем увидеть все наши пары данных в сочетании, — это Seaborn. pairplot():

import seaborn as sns


customer_data = customer_data.drop('CustomerID', axis=1)

sns.pairplot(customer_data)

Что отображает:

IMG

С первого взгляда мы можем заметить диаграммы рассеяния, которые, кажется, имеют группы данных. Один из них кажется интересным — это диаграмма рассеяния, которая объединяет Annual Income и Spending Score. Обратите внимание, что между диаграммами рассеивания других переменных нет четкого разделения. В лучшем случае мы можем сказать, что есть две различные концентрации точек в Spending Score vs Age диаграмма рассеяния.

Обе диаграммы рассеяния, состоящие из Annual Income и Spending Score по сути одинаковы. Мы можем видеть это дважды, потому что оси x и y поменялись местами. Взглянув на любую из них, мы можем увидеть пять разных групп. Давайте нарисуем только эти две функции с помощью Seaborn. scatterplot() чтобы рассмотреть поближе:

sns.scatterplot(x=customer_data['Annual Income (k$)'],
                y=customer_data['Spending Score (1-100)'])

IMG

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

IMG

Замечательно! На данный момент у нас уже есть две переменные для построения нашей модели. Помимо того, что это представляет, это также делает модель более простой, экономичной и более объяснимой.

Ознакомьтесь с нашим практическим руководством по изучению Git с рекомендациями, принятыми в отрасли стандартами и прилагаемой памяткой. Перестаньте гуглить команды Git и на самом деле изучить это!

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

Построение данных после использования PCA

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

Примечание: Большинство людей используют PCA для уменьшения размерности перед визуализацией. Существуют и другие методы, которые помогают визуализировать данные перед кластеризацией, например Пространственная кластеризация приложений с шумом на основе плотности (DBSCAN) и Самоорганизующиеся карты (SOM) кластеризация. Оба являются алгоритмами кластеризации, но также могут использоваться для визуализации данных. Поскольку у кластерного анализа нет золотого стандарта, важно сравнивать разные визуализации и разные алгоритмы.

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

Для каждой пары признаков PCA проверяет, соответствуют ли большие значения одной переменной большим значениям другой переменной, и делает то же самое для меньших значений. Таким образом, он, по сути, вычисляет, насколько значения признаков различаются по отношению друг к другу — мы называем это их ковариационная. Эти результаты затем организуются в матрицу, получая ковариационная матрица.

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

Внимание: PCA — это линейное преобразование, а линейность зависит от масштаба данных. Таким образом, PCA работает лучше всего, когда все значения данных находятся в одном масштабе. Это можно сделать, вычитая столбец значить от его значений и деления результата на его стандартное отклонение. Это называется стандартизация данных. Перед использованием PCA убедитесь, что данные масштабированы! Если вы не знаете, как, прочитайте нашу «Масштабирование данных с помощью Scikit-Learn для машинного обучения в Python»!

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

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

Примечание: Одна важная деталь, которую следует принять во внимание, заключается в том, что из-за своей линейной природы PCA будет концентрировать большую часть объясненной дисперсии в первых главных компонентах. Таким образом, при рассмотрении объясненной дисперсии обычно достаточно первых двух компонентов. Но в некоторых случаях это может ввести в заблуждение, поэтому старайтесь постоянно сравнивать различные графики и алгоритмы при кластеризации, чтобы увидеть, дают ли они похожие результаты.

Прежде чем применять PCA, нам нужно выбрать между Age столбец или Age Groups столбцы в наших ранее закодированных данных. Поскольку оба столбца представляют одну и ту же информацию, ее двойное введение влияет на дисперсию наших данных. Если Age Groups столбец выбран, просто удалите Age столбец с помощью Pandas drop() метод и переназначить его на customer_data_oh переменная:

customer_data_oh = customer_data_oh.drop(['Age'], axis=1)
customer_data_oh.shape 

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

Давайте сделаем это с помощью Scikit-Learn PCA. Мы рассчитаем объясненную дисперсию каждого измерения, заданную выражением explained_variance_ratio_ , а затем посмотрите на их совокупную сумму с помощью cumsum() :

from sklearn.decomposition import PCA

pca = PCA(n_components=10)
pca.fit_transform(customer_data_oh)
pca.explained_variance_ratio_.cumsum()

Наши совокупные объясненные отклонения составляют:

array([0.509337  , 0.99909504, 0.99946364, 0.99965506, 0.99977937,
       0.99986848, 0.99993716, 1.        , 1.        , 1.        ])

Мы видим, что первое измерение объясняет 50% данных, а в сочетании со вторым измерением они объясняют 99% процентов. Это означает, что первые 2 измерения уже объясняют 99% наших данных. Таким образом, мы можем применить PCA с двумя компонентами, получить наши основные компоненты и построить их:

from sklearn.decomposition import PCA

pca = PCA(n_components=2)
pcs = pca.fit_transform(customer_data_oh)

pc1_values = pcs[:,0]
pc2_values = pcs[:,1]
sns.scatterplot(x=pc1_values, y=pc2_values)

IMG

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

IMG

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

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

Ассоциация дендрограммы является результатом связывания точек в наборе данных. Это визуальное представление процесса иерархической кластеризации. И как работает процесс иерархической кластеризации? Ну… это зависит от обстоятельств — возможно, этот ответ вы уже много раз слышали в науке о данных.

Понимание иерархической кластеризации

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

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

Шаги для выполнения агломеративной иерархической кластеризации

Чтобы сделать агломеративный подход еще более понятным, есть шаги Агломеративная иерархическая кластеризация (AHC) алгоритм:

  1. Вначале рассматривайте каждую точку данных как один кластер. Следовательно, количество кластеров в начале будет равно K, а K — целое число, представляющее количество точек данных.
  2. Сформируйте кластер, объединив две ближайшие точки данных, что приведет к кластерам K-1.
  3. Сформируйте больше кластеров, объединив два ближайших кластера, в результате чего получится кластер K-2.
  4. Повторяйте описанные выше три шага, пока не сформируется один большой кластер.

Внимание: Для упрощения мы говорим «две ближайшие» точки данных на шагах 2 и 3. Но есть и другие способы связать точки, как мы вскоре увидим.

Если вы инвертируете шаги алгоритма ACH, переходя от 4 к 1, это будут шаги к *Разделительная иерархическая кластеризация (DHC)*.

Обратите внимание, что HCA могут быть либо разделяющими и нисходящими, либо агломеративными и восходящими. Подход DHC «сверху вниз» лучше всего работает, когда у вас меньше кластеров, но они крупнее, поэтому он требует больших вычислительных ресурсов. С другой стороны, восходящий подход AHC подходит для случаев, когда у вас много небольших кластеров. Он проще в вычислительном отношении, более широко используется и более доступен.

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

Давайте построим дендрограмму данных наших клиентов, чтобы визуализировать иерархические отношения данных. На этот раз мы будем использовать scipy библиотека для создания дендрограммы для нашего набора данных:

import scipy.cluster.hierarchy as shc
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 7))
plt.title("Customers Dendrogram")


selected_data = customer_data_oh.iloc[:, 1:3]
clusters = shc.linkage(selected_data, 
            method='ward', 
            metric="euclidean")
shc.dendrogram(Z=clusters)
plt.show()

Вывод скрипта выглядит так:

IMG

В приведенном выше скрипте мы сгенерировали кластеры и подкластеры с нашими точками, определили, как наши точки будут связаны (применив ward метод), и как измерить расстояние между точками (используя euclidean метрика).

С помощью графика дендрограммы можно визуализировать описанные процессы DHC и AHC. Чтобы визуализировать подход «сверху вниз», начните с верхней части дендрограммы и двигайтесь вниз, и сделайте наоборот, начиная вниз и двигаясь вверх, чтобы визуализировать подход снизу вверх.

Методы связи

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

Некоторые из методов связывания:

  • Одинарная связь: также упоминается как Ближайший сосед (NN). Расстояние между кластерами определяется расстоянием между их ближайшими членами.

IMG

  • Полная связь: также упоминается как Самый дальний сосед (FN), Алгоритм самой дальней точкиили Алгоритм Вур Хиса. Расстояние между кластерами определяется расстоянием между их самыми дальними членами. Этот метод является дорогостоящим в вычислительном отношении.

IMG

  • Средняя связь: также известен как УПГМА (метод невзвешенной парной группы со средним арифметическим). Процент количества точек каждого кластера рассчитывается по отношению к количеству точек двух кластеров, если они были объединены.

IMG

  • Взвешенная связь: также известен как ВПГМА (метод взвешенных парных групп со средним арифметическим). Отдельные точки двух кластеров вносят вклад в совокупное расстояние между меньшим и большим кластерами.
  • Центральная связь: также упоминается как УПГМК (Метод невзвешенной парной группы с использованием центроидов). Точка, определяемая средним значением всех точек (центроид), рассчитывается для каждого кластера, а расстояние между кластерами — это расстояние между их соответствующими центроидами.

IMG

  • Связь с приходом: Также известен как МИСК (Минимальное увеличение суммы квадратов). Он определяет расстояние между двумя кластерами, вычисляет ошибку суммы квадратов (ESS) и последовательно выбирает следующие кластеры на основе меньшего ESS. Метод Уорда стремится свести к минимуму увеличение ESS на каждом этапе. Таким образом, минимизируя ошибку.

IMG

Метрики расстояния

Помимо связи, мы также можем указать некоторые из наиболее часто используемых показателей расстояния:

  • евклиды: также упоминается как Пифагорейская или прямолинейная расстояние. Он вычисляет расстояние между двумя точками в пространстве, измеряя длину отрезка, проходящего между ними. Он использует теорему Пифагора, и значение расстояния является результатом (c) уравнения:

$$
с ^ 2 = а ^ 2 + Ь ^ 2
$$

  • Манхеттен: также называемый Городской квартал, Такси расстояние. Это сумма абсолютных разностей между измерениями всех измерений двух точек. Если этих измерений два, это аналогично повороту вправо, а затем влево при прохождении одного квартала.

IMG

  • Минковский: это обобщение как евклидовых, так и манхэттенских расстояний. Это способ расчета расстояний на основе абсолютных разностей порядка метрики Минковского. p. Хотя он определен для любого р> 0, он редко используется для значений, отличных от 1, 2 и ∞ (бесконечно). Расстояние Минковского равно манхэттенскому расстоянию, когда р = 1, и то же, что и евклидово расстояние, когда р = 2.

$$
Dleft(X,Yright) = left(sum_{i=1}^n |x_i-y_i|^pright)^{frac{1}{p}}
$$

IMG

  • Чебышева: также известен как шахматная доска расстояние. Это крайний случай расстояния Минковского. Когда мы используем бесконечность в качестве значения параметра р (р = ∞), мы получаем метрику, определяющую расстояние как максимальную абсолютную разницу между координатами.
  • Косинус: это угловое косинусное расстояние между двумя последовательностями точек или векторов. Косинусное сходство — это скалярное произведение векторов, деленное на произведение их длин.
  • Жаккар: измеряет сходство между конечными наборами точек. Он определяется как общее количество точек (мощность) в общих точках в каждом наборе (пересечение), деленное на общее количество точек (мощность) суммы точек обоих наборов (объединения).
  • Дженсен-Шеннон: на основе расхождения Кульбака-Лейблера. Он рассматривает распределения вероятностей точек и измеряет сходство между этими распределениями. Это популярный метод теории вероятностей и статистики.

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

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

Когда количество признаков (F) больше, чем количество наблюдений (N) - в основном пишется как ф >> Н, значит, у нас есть многомерное пространство.

Если бы мы включили больше атрибутов, то есть у нас есть более 200 признаков, евклидово расстояние могло бы работать не очень хорошо, так как было бы трудно измерить все малые расстояния в очень большом пространстве, которое только увеличивается. Другими словами, метод евклидова расстояния имеет трудности при работе с данными. разреженность. Это проблема, которая называется проклятие размерности. Значения расстояния станут такими маленькими, как если бы они «разбавлялись» в большем пространстве, искажались до тех пор, пока не стали бы равными 0.

Примечание: Если вы когда-нибудь встретите набор данных с ж >> п, вы, вероятно, будете использовать другие показатели расстояния, такие как Махаланобис расстояние. Кроме того, вы также можете уменьшить размеры набора данных, используя Анализ главных компонентов (PCA). Эта проблема часто возникает, особенно при кластеризации данных биологического секвенирования.

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

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

Мы можем провести горизонтальную линию, проходящую через это самое длинное расстояние:

plt.figure(figsize=(10, 7))
plt.title("Customers Dendogram with line")
clusters = shc.linkage(selected_data, 
            method='ward', 
            metric="euclidean")
shc.dendrogram(clusters)
plt.axhline(y = 125, color = 'r', linestyle = '-')

IMG

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

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

Реализация агломеративной иерархической кластеризации

Использование исходных данных

На данный момент мы подсчитали предполагаемое количество кластеров для нашего набора данных, которые подтверждают наш первоначальный анализ и наш анализ PCA. Теперь мы можем создать нашу агломеративную иерархическую модель кластеризации с помощью Scikit-Learn. AgglomerativeClustering и узнайте этикетки маркетинговых точек с labels_:

from sklearn.cluster import AgglomerativeClustering

clustering_model = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
clustering_model.fit(selected_data)
clustering_model.labels_

Это приводит к:

array([4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3,
       4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 1,
       4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 0, 2, 0, 2,
       1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2,
       0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
       0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
       0, 2])

Мы многое исследовали, чтобы добраться до этой точки. И что означают эти ярлыки? Здесь у нас есть каждая точка наших данных, помеченная как группа от 0 до 4:

data_labels = clustering_model.labels_
sns.scatterplot(x='Annual Income (k$)', 
                y='Spending Score (1-100)', 
                data=selected_data, 
                hue=data_labels,
                pallete="rainbow").set_title('Labeled Customer Data')

IMG

Это наши окончательные кластеризованные данные. Вы можете увидеть точки данных с цветовой кодировкой в ​​виде пяти кластеров.

Точки данных в правом нижнем углу (метка: 0, фиолетовые точки данных) принадлежат клиентам с высокими зарплатами, но низкими расходами. Это клиенты, которые бережно тратят свои деньги.

Точно так же клиенты в правом верхнем углу (метка: 2, зеленые точки данных), — это клиенты с высокими зарплатами и высокими расходами. Это тип клиентов, на которых ориентируются компании.

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

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

И, наконец, клиенты в левом верхнем углу (метка: 3, оранжевые точки данных) — это компании с высоким доходом и низкими расходами, на которые идеально ориентируется маркетинг.

Использование результатов PCA

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

clustering_model_pca = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
clustering_model_pca.fit(pcs)

data_labels_pca = clustering_model_pca.labels_

sns.scatterplot(x=pc1_values, 
                y=pc2_values,
                hue=data_labels_pca,
                palette="rainbow").set_title('Labeled Customer Data Reduced with PCA')

IMG

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

Чем меньше нам нужно преобразовать наши данные, тем лучше.

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

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

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

Заключение

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

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

Удачной кластеризации!

Отметка времени:

Больше от Стекабьюс