Повний посібник із кластеризації K-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Повний посібник із кластеризації K-Means за допомогою Scikit-Learn

Вступ

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

У цьому посібнику ми спочатку розглянемо простий приклад, щоб зрозуміти, як працює алгоритм K-Means, перш ніж реалізувати його за допомогою Scikit-Learn. Потім ми обговоримо, як визначити кількість кластерів (Ks) у K-Means, а також охопимо показники відстані, дисперсію, а також переваги та мінуси K-Means.

мотивація

Уявіть собі наступну ситуацію. Одного разу, прогулюючись околицями, ви помітили 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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Як вручну реалізувати алгоритм K-Means

Тепер ми можемо поглянути на 10 магазинів на графіку, і головна проблема полягає в тому, щоб знайти спосіб, яким їх можна розділити на різні групи на основі близькості? Просто швидко поглянувши на графік, ми, ймовірно, помітимо дві групи магазинів – одна – це нижня точка зліва, а інша – верхня права точка. Можливо, ми навіть можемо виділити ці дві точки посередині в окрему групу – отже, творити три різні групи.

У цьому розділі ми розглянемо процес кластеризації точок вручну – поділу їх на задану кількість груп. Таким чином ми, по суті, уважно розглянемо всі кроки Алгоритм кластеризації K-Means. До кінця цього розділу ви отримаєте як інтуїтивне, так і практичне розуміння всіх кроків, які виконуються під час кластеризації K-Means. Після цього ми передамо його Scikit-Learn.

Який найкращий спосіб визначити наявність двох чи трьох груп точок? Одним із простих способів було б просто вибрати одну кількість груп (наприклад, дві), а потім спробувати згрупувати точки на основі цього вибору.

Повний посібник із кластеризації K-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Скажімо, ми вирішили, що є дві групи наших магазинів (точок). Тепер нам потрібно знайти спосіб зрозуміти, які точки до якої групи належать. Це можна зробити, вибравши одну точку для представлення група 1 і один представляти група 2. Ці точки будуть використовуватися як еталонні під час вимірювання відстані від усіх інших точок до кожної групи.

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

У цьому прикладі, окрім визначення кількості груп (кластерів) – ми також вибираємо деякі моменти для a посилання відстані для нових точок кожної групи.

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

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

Після цього нам потрібно обчислити відстань від усіх інших точок до цих контрольних точок. Це викликає важливе питання – як виміряти цю відстань. По суті, ми можемо використовувати будь-яку міру відстані, але для цілей цього посібника давайте використаємо Евклідову відстань_.

Може бути корисно знати, що евклідова міра відстані базується на теоремі Піфагора:

$$
c^2 = a^2 + b^2
$$

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

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

Відстань буде квадратним коренем з c, тому ми також можемо записати формулу так:

$$
euclidean_{dist} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2)]
$$

Примітка: Ви також можете узагальнити формулу евклідової відстані для багатовимірних точок. Наприклад, у тривимірному просторі точки мають три координати – наша формула відображає це таким чином:
$$
euclidean_{dist} = 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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Чітко видно, що лише наша перша точка віднесена до групи 1, а всі інші точки були віднесені до групи 2. Цей результат відрізняється від того, що ми передбачали на початку. Враховуючи різницю між нашими результатами та нашими початковими очікуваннями, чи є спосіб змінити це? Здається є!

Один із підходів полягає в тому, щоб повторити процес і вибрати різні точки, які будуть посиланнями для груп. Це змінить наші результати, сподіваємося, більше відповідатимуть тим, що ми передбачали на початку. Цього разу вдруге ми могли вибрати їх не навмання, як робили раніше, а отримавши a значити усіх наших уже згрупованих точок. Таким чином, ці нові точки можуть бути розташовані в середині відповідних груп.

Наприклад, якщо в другій групі були лише бали (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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Здається, кластеризація наших точок є стає краще. Але все ж у середині графіка є дві точки, які можна віднести до будь-якої групи, враховуючи їхню близькість до обох груп. Розроблений нами алгоритм призначає обидві ці точки до другої групи.

Це означає, що ми, ймовірно, можемо повторити процес ще раз, взявши середні Xs і Ys, створивши дві нові центральні точки (центроїди) до наших груп і перепризначаючи їх залежно від відстані.

Давайте також створимо функцію для оновлення центроїдів. Весь процес тепер можна звести до кількох викликів цієї функції:

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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Зверніть увагу, що після цієї третьої ітерації кожна з точок тепер належить до різних кластерів. Здається, результати стають кращими – давайте повторимо це ще раз. Тепер іду до четверта ітерація нашого методу:

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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Це четвертий раз ми отримали той самий результат як і попередній. Отже, здається, що наші бали більше не змінюватимуться у групах, наш результат досяг певної стабільності – він перейшов у незмінний стан, або збіглися. Крім того, ми маємо точно такий самий результат, як ми передбачали для 2 груп. Ми також можемо побачити, чи має сенс цей досягнутий поділ.

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

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

Що все це має робити з алгоритмом K-Means?

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

Команда K в K-Means походить від кількість кластерів які потрібно встановити до початку процесу ітерації. У нашому випадку К = 2. Ця характеристика іноді розглядається як негативний враховуючи, що існують інші методи кластеризації, такі як ієрархічна кластеризація, для яких не потрібно заздалегідь мати фіксовану кількість кластерів.

Завдяки його використанню засобів, K-засобів також стає чутливий до викидів і екстремальних значень – вони підвищують мінливість і ускладнюють виконання наших центроїдів своєї ролі. Отже, усвідомлюйте необхідність виконання екстремальні значення та аналіз викидів перед проведенням кластеризації за допомогою алгоритму K-Means.

Крім того, зверніть увагу, що наші точки були сегментовані на прямі частини, немає кривих при створенні кластерів. Це також може бути недоліком алгоритму K-Means.

Примітка: Якщо вам потрібно, щоб він був більш гнучким і адаптованим до еліпсів та інших форм, спробуйте використати a узагальнена K-середня модель суміші Гауса. Ця модель може адаптуватися до кластерів еліптичної сегментації.

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

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

Як реалізувати алгоритм K-Means за допомогою scikit-learn

Щоб подвійно перевірити наш результат, давайте повторимо цей процес, але тепер з використанням 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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Отриманий графік такий самий, як і в попередньому розділі.

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

Примітка: Лише подивившись на те, як ми виконали алгоритм K-Means за допомогою Scikit-Learn, ви можете скласти враження, що це безпроблемно, і вам не потрібно про це надто турбуватися. Лише 3 рядки коду виконують усі кроки, які ми обговорювали в попередньому розділі, коли ми крок за кроком розглядали алгоритм K-Means. але, диявол криється в деталях в цьому випадку! Якщо ви не розумієте всіх етапів і обмежень алгоритму, ви, швидше за все, зіткнетеся з ситуацією, коли алгоритм K-Means дає вам результати, яких ви не очікували.

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

Метод ліктя – вибір найкращої кількості груп

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

Тут ставиться питання як визначити кількість груп (K) у K-Means. Щоб відповісти на це запитання, нам потрібно зрозуміти, чи існував би «кращий» кластер для іншого значення K.

Наївний спосіб знайти це шляхом кластеризації точок з різними значеннями K, отже, для K=2, K=3, K=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 можна використовувати для будь-якої кількості кластерів:

$$
WCSS = sum(Pi_1 – Centroid_1)^2 + cdots + sum(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
$$

$$
WCSS = 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)

І підсумуйте результати, щоб отримати підсумок WCSS:

g1 + g2

Це призводить до:

2964.3999999999996

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

Розрахунок WCSS використання scikit-learn

На щастя, нам не потрібно вручну обчислювати WCSS для кожного K. Після виконання кластеризації K-Means для заданої кількості кластерів ми можемо отримати його 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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Існує перерва на сюжеті, коли x = 2, нижня точка лінії, і ще нижча, коли x = 3. Зверніть увагу, що це нагадує нам про форма ліктя. Зображуючи Ks разом із WCSS, ми використовуємо Метод ліктя вибрати кількість Кс. І вибране 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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Ми можемо знову запустити кластерний алгоритм 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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Ми вже були задоволені двома кластерами, але згідно з методом ліктя, три кластери краще підходили б для наших даних. У цьому випадку ми мали б три види магазинів замість двох. До використання ліктьового методу ми думали про південно-західний і північно-східний кластери магазинів, тепер у нас також є магазини в центрі. Можливо, це було б гарним місцем для відкриття іншого магазину, оскільки поблизу було б менше конкуренції.

Альтернативні кластерні показники якості

Існують також інші показники, які можна використовувати при оцінці якості кластера:

  • Силуетна оцінка – аналізує не тільки відстань між внутрішньокластерними точками, а й між самими кластерами
  • Сума квадратів між кластерами (BCSS) – метрика, яка доповнює WCSS
  • Помилка суми квадратів (ESS)
  • Максимальний радіус – вимірює найбільшу відстань від точки до її центроїда
  • Середній радіус – сума найбільшої відстані від точки до її центроїда, поділена на кількість кластерів.

Рекомендується поекспериментувати та ознайомитися з кожним із них, оскільки залежно від проблеми деякі з альтернатив можуть бути більш застосовними, ніж найбільш широко використовувані показники (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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Дивлячись на парний графік, два стовпці здаються перспективними для цілей кластеризації – Alcohol та OD280 (це метод визначення концентрації білка у винах). Здається, що на ділянках є 3 окремі кластери, які поєднують два з них.

Є й інші стовпці, які, здається, також корелюються. Дуже помітно Alcohol та Total_Phenols та Alcohol та Flavanoids. Вони мають чудові лінійні зв’язки, які можна спостерігати на парному графіку.

Оскільки ми зосереджені на кластеризації за допомогою K-Means, давайте, скажімо, виберемо одну пару стовпців Alcohol та OD280і протестуйте метод ліктя для цього набору даних.

Примітка: При використанні більшої кількості стовпців набору даних виникне необхідність або побудувати тривимірний графік, або зменшити дані до основні компоненти (використання PCA). Це дійсний і більш поширений підхід, просто переконайтеся, що ви вибрали основні компоненти на основі того, наскільки вони пояснюють, і майте на увазі, що при зменшенні розмірів даних відбувається деяка втрата інформації, тому графік є наближення реальних даних, а не того, як вони є насправді.

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

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

Повний посібник із кластеризації K-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Тепер ми можемо визначити наші стовпці та використовувати метод ліктя для визначення кількості кластерів. Ми також запустимо алгоритм з 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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Відповідно до ліктьового методу тут має бути 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-Means за допомогою Scikit-Learn PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Ми можемо бачити кластери 0, 1 та 2 на графіку. На основі нашого аналізу, група 0 містить вина з більшим вмістом білка та меншим вмістом алкоголю, група 1 містить вина з високим вмістом алкоголю та низьким вмістом білка, а також група 2 має високий вміст білка та алкоголю у своїх винах.

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

Висновок

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

Часова мітка:

Більше від Stackabuse