Исследование предположений алгоритма кластеризации k-средних

Beginner

This tutorial is from open-source community. Access the source code

Введение

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

Советы по работе с ВМ

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

Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.

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

Генерация данных

Мы будем использовать функцию make_blobs из scikit - learn для генерации различных наборов данных с различными распределениями. В следующем блоке кода мы генерируем четыре набора данных:

  • Смесь гауссовых кластеров
  • Анизотропно распределенные кластеры
  • Кластеры с различной дисперсией
  • Кластеры с различными размерами
import numpy as np
from sklearn.datasets import make_blobs

n_samples = 1500
random_state = 170
transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]

X, y = make_blobs(n_samples=n_samples, random_state=random_state)
X_aniso = np.dot(X, transformation)  ## Анизотропные кластеры
X_varied, y_varied = make_blobs(
    n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state
)  ## Различная дисперсия
X_filtered = np.vstack(
    (X[y == 0][:500], X[y == 1][:100], X[y == 2][:10])
)  ## Кластеры с различными размерами
y_filtered = [0] * 500 + [1] * 100 + [2] * 10

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

Мы будем использовать Matplotlib для визуализации сгенерированных наборов данных. В следующем блоке кода мы создаем 2x2 график, показывающий истинные кластеры для каждого набора данных.

import matplotlib.pyplot as plt

fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(12, 12))

axs[0, 0].scatter(X[:, 0], X[:, 1], c=y)
axs[0, 0].set_title("Mixture of Gaussian Blobs")

axs[0, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y)
axs[0, 1].set_title("Anisotropically Distributed Blobs")

axs[1, 0].scatter(X_varied[:, 0], X_varied[:, 1], c=y_varied)
axs[1, 0].set_title("Unequal Variance")

axs[1, 1].scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_filtered)
axs[1, 1].set_title("Unevenly Sized Blobs")

plt.suptitle("Ground truth clusters").set_y(0.95)
plt.show()

Кластеризация k-средних

Мы будем использовать класс KMeans из scikit - learn для кластеризации данных. В следующем блоке кода мы создаем 2x2 график, показывающий кластеры, полученные с использованием k-средних для каждого набора данных.

from sklearn.cluster import KMeans

common_params = {
    "n_init": "auto",
    "random_state": random_state,
}

fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(12, 12))

y_pred = KMeans(n_clusters=2, **common_params).fit_predict(X)
axs[0, 0].scatter(X[:, 0], X[:, 1], c=y_pred)
axs[0, 0].set_title("Non-optimal Number of Clusters")

y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_aniso)
axs[0, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred)
axs[0, 1].set_title("Anisotropically Distributed Blobs")

y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_varied)
axs[1, 0].scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)
axs[1, 0].set_title("Unequal Variance")

y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_filtered)
axs[1, 1].scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
axs[1, 1].set_title("Unevenly Sized Blobs")

plt.suptitle("Unexpected KMeans clusters").set_y(0.95)
plt.show()

Возможные решения

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

y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.title("Optimal Number of Clusters")
plt.show()

y_pred = KMeans(n_clusters=3, n_init=10, random_state=random_state).fit_predict(
    X_filtered
)
plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
plt.title("Unevenly Sized Blobs \nwith several initializations")
plt.show()

Гауссовская смесь

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

from sklearn.mixture import GaussianMixture

fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(12, 6))

y_pred = GaussianMixture(n_components=3).fit_predict(X_aniso)
ax1.scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred)
ax1.set_title("Anisotropically Distributed Blobs")

y_pred = GaussianMixture(n_components=3).fit_predict(X_varied)
ax2.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)
ax2.set_title("Unequal Variance")

plt.suptitle("Gaussian mixture clusters").set_y(0.95)
plt.show()

Обзор

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