Демонстрация предположений k-means#

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

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

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

Функция make_blobs генерирует изотропные (сферические) гауссовы сгустки. Для получения анизотропных (эллиптических) гауссовых сгустков необходимо определить линейное transformation.

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)  # Anisotropic blobs
X_varied, y_varied = make_blobs(
    n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state
)  # Unequal variance
X_filtered = np.vstack(
    (X[y == 0][:500], X[y == 1][:100], X[y == 2][:10])
)  # Unevenly sized blobs
y_filtered = [0] * 500 + [1] * 100 + [2] * 10

Мы можем визуализировать полученные данные:

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()
Ground truth clusters, Mixture of Gaussian Blobs, Anisotropically Distributed Blobs, Unequal Variance, Unevenly Sized Blobs

Обучить модели и построить результаты#

Ранее сгенерированные данные теперь используются, чтобы показать, как KMeans ведет себя в следующих сценариях:

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

  • Анизотропно распределенные сгустки: k-средние состоит в минимизации евклидовых расстояний выборок до центроида кластера, к которому они отнесены. Как следствие, k-средние более подходит для кластеров, которые изотропны и нормально распределены (т.е. сферические гауссовы).

  • Неравная дисперсия: k-means эквивалентен взятию оценщика максимального правдоподобия для "смеси" k гауссовских распределений с одинаковыми дисперсиями, но, возможно, разными средними.

  • Неравномерные размеры кластеров: нет теоретического результата о 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()
Unexpected KMeans clusters, Non-optimal Number of Clusters, Anisotropically Distributed Blobs, Unequal Variance, Unevenly Sized Blobs

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

Пример того, как найти правильное количество кластеров, см. Выбор количества кластеров с помощью анализа силуэта для кластеризации KMeans. В этом случае достаточно установить n_clusters=3.

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()
Optimal Number of Clusters

Для работы с неравномерно распределёнными сгустками можно увеличить количество случайных инициализаций. В этом случае мы устанавливаем n_init=10 чтобы избежать нахождения субоптимального локального минимума. Для получения дополнительных сведений см. Кластеризация разреженных данных с помощью k-средних.

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()
Unevenly Sized Blobs  with several initializations

Поскольку анизотропные и неравные дисперсии являются реальными ограничениями алгоритма k-средних, здесь мы предлагаем вместо этого использование 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()
Gaussian mixture clusters, Anisotropically Distributed Blobs, Unequal Variance

Заключительные замечания#

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

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

Общее время выполнения скрипта: (0 минут 0.968 секунд)

Связанные примеры

Сравнение производительности биссекционного K-средних и обычного K-средних

Сравнение производительности биссекционного K-средних и обычного K-средних

Сравнение различных методов иерархической связи на игрушечных наборах данных

Сравнение различных методов иерархической связи на игрушечных наборах данных

Построение перекрестно проверенных предсказаний

Построение перекрестно проверенных предсказаний

Демонстрация кластеризации K-Means на данных рукописных цифр

Демонстрация кластеризации K-Means на данных рукописных цифр

Галерея, созданная Sphinx-Gallery