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

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

Введение

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

В этом руководстве мы сначала рассмотрим простой пример, чтобы понять, как работает алгоритм K-средних, прежде чем реализовать его с помощью Scikit-Learn. Затем мы обсудим, как определить количество кластеров (K) в K-средних, а также рассмотрим метрики расстояния, дисперсию и плюсы и минусы K-средних.

мотивация

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

Например, если один магазин находится в 5 км к западу и в 3 км к северу, вы бы присвоили (5, 3) координаты к нему и представить его на графике. Давайте построим эту первую точку, чтобы визуализировать то, что происходит:

import matplotlib.pyplot as plt

plt.title("Store With Coordinates (5, 3)")
plt.scatter(x=5, y=3)

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

import numpy as np

points = np.array([[5, 3], [10, 15], [15, 12], [24, 10], [30, 45], [85, 70], [71, 80], [60, 78], [55, 52],[80, 91]])

xs = points[:,0] 
ys = points[:,1]  

plt.title("10 Stores Coordinates")
plt.scatter(x=xs, y=ys)

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

Как вручную реализовать алгоритм K-средних

Теперь мы можем посмотреть на 10 магазинов на графике, и основная проблема заключается в том, чтобы найти способ разделить их на разные группы на основе близости? Просто взглянув на график, мы, вероятно, заметим две группы магазинов – одна нижняя указывает на нижнюю левую, а другая – верхняя правая точка. Возможно, мы даже сможем выделить эти две точки посередине в отдельную группу, создав тем самым три разные группы.

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

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

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

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

Таким образом, скажем, точка (5, 3) оказывается принадлежащим группе 1, а точка (79, 60) к группе 2. При попытке назначить новую точку (6, 3) к группам, нам нужно измерить его расстояние до этих двух точек. В случае точки (6, 3) is ближе до (5, 3), поэтому он принадлежит к группе, представленной этой точкой – группа 1. Таким образом, мы можем легко сгруппировать все точки в соответствующие группы.

В этом примере, помимо определения количества групп (кластеры) – мы также выбираем некоторые точки, которые будут ссылка расстояния для новых точек каждой группы.

Это общая идея, чтобы понять сходство между нашими магазинами. Давайте применим это на практике – мы можем сначала выбрать две контрольные точки в случайный. Ориентир группа 1 будет (5, 3) и точка отсчета группа 2 будет (10, 15). Мы можем выбрать обе точки нашего numpy массив по [0] и [1] индексы и хранить их в g1 (группа 1) и g2 (группа 2) переменные:

g1 = points[0]
g2 = points[1]

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

Может быть полезно знать, что евклидова мера расстояния основана на теореме Пифагора:

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

При адаптации к точкам на плоскости – (a1, b1) и (a2, b2), предыдущая формула принимает вид:

$$
c^2 = (a2-a1)^2 + (b2-b1)^2
$$

Расстояние будет квадратным корнем из c, поэтому мы также можем записать формулу как:

$$
евклидов_{расстояние} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2)]
$$

Примечание: Вы также можете обобщить формулу евклидова расстояния для многомерных точек. Например, в трехмерном пространстве точки имеют три координаты — наша формула отражает это следующим образом:
$$
евклидов_{расстояние} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2 + (c2 – c1) ^2)]
$$
Тот же принцип соблюдается независимо от количества измерений пространства, в котором мы работаем.

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

Чтобы лучше это представить, мы объявим три списка. Первый, кто хранит баллы первой группы – points_in_g1. Второй для хранения очков из группы 2 – points_in_g2, и последний - groupдо этикетка точки как либо 1 (относится к группе 1) или 2 (относится ко 2 группе):

points_in_g1 = []
points_in_g2 = []
group = []

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

for p in points:
    x1, y1 = p[0], p[1]
    euclidean_distance_g1 = np.sqrt((g1[0] - x1)**2 + (g1[1] - y1)**2)
    euclidean_distance_g2 = np.sqrt((g2[0] - x1)**2 + (g2[1] - y1)**2)
    if euclidean_distance_g1 < euclidean_distance_g2:
        points_in_g1.append(p)
        group.append('1')
    else:
        points_in_g2.append(p)
        group.append('2')

Давайте посмотрим на результаты этой итерации, чтобы увидеть, что произошло:

print(f'points_in_g1:{points_in_g1}n 
npoints_in_g2:{points_in_g2}n 
ngroup:{group}')

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

points_in_g1:[array([5, 3])]
 
points_in_g2:[array([10, 15]), array([15, 12]), 
              array([24, 10]), array([30, 45]), 
              array([85, 70]), array([71, 80]),
              array([60, 78]), array([55, 52]), 
              array([80, 91])]
 
group:[1, 2, 2, 2, 2, 2, 2, 2, 2, 2] 

Мы также можем построить результат кластеризации с разными цветами в зависимости от назначенных групп, используя Seaborn. scatterplot() с group как hue Аргумент:

import seaborn as sns

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

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

Хорошо видно, что только наша первая точка отнесена к группе 1, а все остальные точки отнесены к группе 2. Этот результат отличается от того, что мы предполагали в начале. Учитывая разницу между нашими результатами и нашими первоначальными ожиданиями — можем ли мы это изменить? Кажется есть!

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

Например, если бы во второй группе были только точки (10, 15), (30, 45). Новые центральный точка была бы (10 + 30)/2 и (15+45)/2 – что равно (20, 30).

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

g1_center = [np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()]
g2_center = [np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()]
g1_center, g2_center

Совет: Попробуй использовать numpy и массивы NumPy, насколько это возможно. Они оптимизированы для повышения производительности и упрощают многие операции линейной алгебры. Всякий раз, когда вы пытаетесь решить какую-либо задачу линейной алгебры, вам обязательно следует взглянуть на numpy документацию, чтобы проверить, есть ли numpy метод, предназначенный для решения вашей проблемы. Шанс есть!

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

def assigns_points_to_two_groups(g1_center, g2_center):
    points_in_g1 = []
    points_in_g2 = []
    group = []

    for p in points:
        x1, y1 = p[0], p[1]
        euclidean_distance_g1 = np.sqrt((g1_center[0] - x1)**2 + (g1_center[1] - y1)**2)
        euclidean_distance_g2 = np.sqrt((g2_center[0] - x1)**2 + (g2_center[1] - y1)**2)
        if euclidean_distance_g1 < euclidean_distance_g2:
            points_in_g1.append(p)
            group.append(1)
        else:
            points_in_g2.append(p)
            group.append(2)
    return points_in_g1, points_in_g2, group

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

Давайте вызовем функцию и сохраним ее результаты в points_in_g1, points_in_g2и group переменные:

points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
points_in_g1, points_in_g2, group

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

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

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

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

Это означает, что мы, вероятно, можем повторить процесс еще раз, взяв за основу X и Y, создав две новые центральные точки. (центроиды) к нашим группам и переназначая их в зависимости от расстояния.

Давайте также создадим функцию для обновления центроидов. Теперь весь процесс можно свести к нескольким вызовам этой функции:

def updates_centroids(points_in_g1, points_in_g2):
    g1_center = np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()
    g2_center = np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()
    return g1_center, g2_center

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

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

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

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

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

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

Давайте просто быстро подведем итог тому, что мы сделали до сих пор. Мы разделили наши 10 магазинов географически на две секции: одни в нижних юго-западных регионах, а другие на северо-востоке. Может быть интересно собрать больше данных помимо того, что у нас уже есть — доход, ежедневное количество клиентов и многое другое. Таким образом, мы можем провести более подробный анализ и, возможно, получить более интересные результаты.

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

Какое отношение все это имеет к алгоритму K-средних?

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

Ассоциация K в K-Means происходит от количество кластеров которые необходимо установить до начала процесса итерации. В нашем случае K = 2. Эта характеристика иногда рассматривается как отрицательный учитывая, что существуют другие методы кластеризации, такие как иерархическая кластеризация, для которых не требуется предварительное фиксированное количество кластеров.

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

Также обратите внимание, что наши точки были сегментированы прямыми частями, кривых при создании кластеров не было. Это также может быть недостатком алгоритма K-Means.

Примечание: Если вам нужно, чтобы он был более гибким и адаптируемым к эллипсам и другим формам, попробуйте использовать обобщенная модель гауссовой смеси K-средних. Эта модель может адаптироваться к кластерам эллиптической сегментации.

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

Теперь, когда мы прошли все шаги, выполняемые в алгоритме K-Means, и поняли все его плюсы и минусы, мы, наконец, можем реализовать K-Means с помощью библиотеки Scikit-Learn.

Как реализовать алгоритм K-средних с помощью научное обучение

Чтобы еще раз проверить наш результат, давайте повторим этот процесс, но теперь используя 3 строки кода с sklearn:

from sklearn.cluster import KMeans


kmeans = KMeans(n_clusters=2, random_state=42) 
kmeans.fit(points)
kmeans.labels_

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

sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

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

Полученный график такой же, как и в предыдущем разделе.

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

Примечание: Просто взглянув на то, как мы выполнили алгоритм K-Means с помощью Scikit-Learn, может создаться впечатление, что это не проблема и вам не нужно слишком беспокоиться об этом. Всего 3 строки кода выполняют все шаги, которые мы обсуждали в предыдущем разделе, когда мы шаг за шагом рассмотрели алгоритм K-Means. Но, Дьявол кроется в деталях в таком случае! Если вы не понимаете всех шагов и ограничений алгоритма, вы, скорее всего, столкнетесь с ситуацией, когда алгоритм K-Means дает результаты, которых вы не ожидали.

С помощью Scikit-Learn вы также можете инициализировать K-Means для более быстрой сходимости, установив параметр init='k-means++' аргумент. В более широком смысле, К-средние ++ по-прежнему выбирает k начальный кластер центрируется случайным образом, следуя равномерному распределению. Затем каждый последующий центр кластера выбирается из оставшихся точек данных не путем вычисления только меры расстояния, а с использованием вероятности. Использование вероятности ускоряет алгоритм и полезно при работе с очень большими наборами данных.

Метод локтя — выбор наилучшего количества групп

Все идет нормально! Мы сгруппировали 10 магазинов на основе евклидова расстояния между точками и центроидами. Но как насчет тех двух точек в середине графика, которые немного сложнее сгруппировать? А нельзя ли было создать отдельную группу? Действительно ли мы ошиблись, выбрав K = 2 группы? Может быть, у нас действительно было K = 3 группы? Мы могли даже иметь более трех групп и не знать об этом.

Здесь задается вопрос как определить количество групп (K) в K-Means. Чтобы ответить на этот вопрос, нам нужно понять, будет ли «лучший» кластер для другого значения K.

Наивный способ выяснить это — сгруппировать точки с разными значениями K, Таким образом, для К=2, К=3, К=4 и т. д.:

for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 

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

Ручной расчет Внутри кластерной суммы квадратов (WCSS)

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

$$
WCSS = сумма (Pi_1 - Centroid_1) ^ 2 + cdots + сумма (Pi_n - Centroid_n) ^ 2
$$

Примечание: В этом руководстве мы используем Евклидово расстояние для получения центроидов, но также можно использовать и другие меры расстояния, такие как Манхэттен.

Теперь мы можем предположить, что мы выбрали два кластера, и попытаться реализовать WCSS, чтобы лучше понять, что такое WCSS и как его использовать. Как указано в формуле, нам нужно суммировать квадраты разностей между всеми точками кластера и центроидами. Итак, если наша первая точка из первой группы (5, 3) и наш последний центроид (после сходимости) первой группы (16.8, 17.0), WCSS будет:

$$
WCSS = сумма ((5,3) – (16.8, 17.0))^2
$$

$$
WCSS = сумма ((5-16.8) + (3-17.0)) ^ 2
$$

$$
WCSS = сумма ((-11.8) + (-14.0)) ^ 2
$$

$$
WCSS = сумма ((-25.8)) ^ 2
$$

$$
ВЧСС = 335.24
$$

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

def sum_of_squares(cluster, centroid):
    squares = []
    for p in cluster:
        squares.append((p - centroid)**2)
        ss = np.array(squares).sum()
    return ss

Теперь мы можем получить сумму квадратов для каждого кластера:

g1 = sum_of_squares(points_in_g1, g1_center)
g2 = sum_of_squares(points_in_g2, g2_center)

И просуммируйте результаты, чтобы получить общее ВКСС:

g1 + g2

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

2964.3999999999996

Итак, в нашем случае, когда K равен 2, общая WCSS равна 2964.39. Теперь мы можем переключить Ks и рассчитать WCSS для всех из них. Таким образом, мы можем получить представление о том, что K мы должны сделать так, чтобы наша кластеризация работала наилучшим образом.

Расчет ВКСС . научное обучение

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

wcss = [] 
for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 
    wcss.append(kmeans.inertia_)
wcss

Обратите внимание, что второе значение в списке точно такое же, как мы вычислили ранее для K = 2:

[18272.9, # For k=1 
 2964.3999999999996, # For k=2
 1198.75, # For k=3
 861.75,
 570.5,
 337.5,
 175.83333333333334,
 79.5,
 17.0,
 0.0]

Чтобы визуализировать эти результаты, давайте построим наш Ks вместе со значениями WCSS:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss)

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

Сюжет прерывается, когда x = 2, нижняя точка в линии и еще более низкая, когда x = 3. Обратите внимание, что это напоминает нам о форма локтя. Нанося Ks вместе с WCSS, мы используем Метод локтя выбрать количество Ks. И выбранная K - это точно самая нижняя точка локтя, значит, было бы 3 вместо 2, в нашем случае:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss);
plt.axvline(3, linestyle='--', color='r')

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

Мы можем снова запустить кластерный алгоритм K-Means, чтобы увидеть, как наши данные будут выглядеть с три кластера:

kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(points)
sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

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

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

Альтернативные показатели качества кластера

Есть и другие меры, которые можно использовать при оценке качества кластера:

  • Оценка силуэта – анализирует не только расстояние между внутрикластерными точками, но и между самими кластерами
  • Между кластерами Сумма квадратов (БКСС) – метрика, дополняющая WCSS
  • Ошибка суммы квадратов (ССЭ)
  • Максимальный радиус - измеряет наибольшее расстояние от точки до ее центра тяжести
  • Средний радиус – сумма наибольшего расстояния от точки до ее центроида, деленная на количество кластеров.

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

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

Применение K-средних к другому набору данных

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

Примечание: Вы можете скачать набор данных здесь.

Начнем с импорта pandas читать wine-clustering CSV (значения, разделенные запятыми) файл в Dataframe состав:

import pandas as pd

df = pd.read_csv('wine-clustering.csv')

После загрузки давайте взглянем на первые пять записей данных с head() Метод:

df.head()

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

	Alcohol 	Malic_Acid 	Ash 	Ash_Alcanity 	Magnesium 	Total_Phenols 	Flavanoids 	Nonflavanoid_Phenols 	Proanthocyanins 	Color_Intensity 	Hue 	OD280 	Proline
0 	14.23 		1.71 		2.43 	15.6 			127 		2.80 			3.06 		0.28 					2.29 				5.64 				1.04 	3.92 	1065
1 	13.20 		1.78 		2.14 	11.2 			100 		2.65 			2.76 		0.26 					1.28 				4.38 				1.05 	3.40 	1050
2 	13.16 		2.36 		2.67 	18.6 			101 		2.80 			3.24 		0.30 					2.81 				5.68 				1.03 	3.17 	1185
3 	14.37 		1.95 		2.50 	16.8 			113 		3.85 			3.49 		0.24 					2.18 				7.80 				0.86 	3.45 	1480
4 	13.24 		2.59 		2.87 	21.0 			118 		2.80 			2.69 		0.39 					1.82 				4.32 				1.04 	2.93 	735

У нас есть много измерений веществ, присутствующих в винах. Здесь нам также не нужно будет преобразовывать категориальные столбцы, потому что все они числовые. Теперь давайте посмотрим на описательную статистику с describe() Метод:

df.describe().T 

Таблица описания:

 						count 	mean 		std 		min 	25% 	50% 	75% 		max
Alcohol 				178.0 	13.000618 	0.811827 	11.03 	12.3625 13.050 	13.6775 	14.83
Malic_Acid 				178.0 	2.336348 	1.117146 	0.74 	1.6025 	1.865 	3.0825 		5.80
Ash 					178.0 	2.366517 	0.274344 	1.36 	2.2100 	2.360 	2.5575 		3.23
Ash_Alcanity 			178.0 	19.494944 	3.339564 	10.60 	17.2000 19.500 	21.5000 	30.00
Magnesium 				178.0 	99.741573 	14.282484 	70.00 	88.0000 98.000 	107.0000 	162.00
Total_Phenols 			178.0 	2.295112 	0.625851 	0.98 	1.7425 	2.355 	2.8000 		3.88
Flavanoids 				178.0 	2.029270 	0.998859 	0.34 	1.2050 	2.135 	2.8750 		5.08
Nonflavanoid_Phenols 	178.0 	0.361854 	0.124453 	0.13 	0.2700 	0.340 	0.4375 		0.66
Proanthocyanins 		178.0 	1.590899 	0.572359 	0.41 	1.2500 	1.555 	1.9500 		3.58
Color_Intensity 		178.0 	5.058090 	2.318286 	1.28 	3.2200 	4.690 	6.2000 		13.00
Hue 					178.0 	0.957449 	0.228572 	0.48 	0.7825 	0.965 	1.1200 		1.71
OD280 					178.0 	2.611685 	0.709990 	1.27 	1.9375 	2.780 	3.1700 		4.00
Proline 				178.0 	746.893258 	314.907474 	278.00 	500.500 673.500 985.0000 	1680.00

Глядя на таблицу, становится ясно, что есть некоторые изменчивость данных – для некоторых столбцов, таких как Alchool есть больше, и для других, таких как Malic_Acid, меньше. Теперь мы можем проверить, есть ли nullили NaN значения в нашем наборе данных:

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 13 columns):
 #   Column                Non-Null Count  Dtype  
---  ------                --------------  -----  
 0   Alcohol               178 non-null    float64
 1   Malic_Acid            178 non-null    float64
 2   Ash                   178 non-null    float64
 3   Ash_Alcanity          178 non-null    float64
 4   Magnesium             178 non-null    int64  
 5   Total_Phenols         178 non-null    float64
 6   Flavanoids            178 non-null    float64
 7   Nonflavanoid_Phenols  178 non-null    float64
 8   Proanthocyanins       178 non-null    float64
 9   Color_Intensity       178 non-null    float64
 10  Hue                   178 non-null    float64
 11  OD280                 178 non-null    float64
 12  Proline               178 non-null    int64  
dtypes: float64(11), int64(2)
memory usage: 18.2 KB

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

sns.pairplot(df)

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

Глядя на парный график, два столбца кажутся многообещающими для целей кластеризации: Alcohol и OD280 (это метод определения концентрации белка в вине). Кажется, что на участках есть 3 отдельных кластера, объединяющих два из них.

Есть и другие столбцы, которые, похоже, также находятся в корреляции. В частности Alcohol и Total_Phenolsи Alcohol и Flavanoids. У них отличные линейные отношения, которые можно наблюдать на парном графике.

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

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

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

sns.scatterplot(data=df, x='OD280', y='Alcohol')

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

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

values = df[['OD280', 'Alcohol']]

wcss_wine = [] 
for i in range(1, 11): 
    kmeans = KMeans(n_clusters = i, init = 'k-means++', random_state = 42)
    kmeans.fit(values) 
    wcss_wine.append(kmeans.inertia_)

Мы рассчитали WCSS, поэтому можем нанести результаты на график:

clusters_wine = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
plt.plot(clusters_wine, wcss_wine)
plt.axvline(3, linestyle='--', color='r')

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

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

kmeans_wine = KMeans(n_clusters=3, random_state=42)
kmeans_wine.fit(values)
sns.scatterplot(x = values['OD280'], y = values['Alcohol'], hue=kmeans_wine.labels_)

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

Мы видим кластеры 0, 1и 2 на графике. На основании нашего анализа, группа 0 есть вина с более высоким содержанием белка и меньшим содержанием алкоголя, группа 1 имеет вина с более высоким содержанием алкоголя и низким содержанием белка, и группа 2 имеет как высокое содержание белка, так и высокое содержание алкоголя в своих винах.

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

Заключение

K-средних кластеризация — это простой, но очень эффективный неконтролируемый алгоритм машинного обучения для кластеризации данных. Он группирует данные на основе евклидова расстояния между точками данных. Алгоритм кластеризации K-средних широко используется для группировки текстовых документов, изображений, видео и многого другого.

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

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