Explorando as Suposições do Agrupamento K-Means

Beginner

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

Introdução

Neste laboratório, exploraremos o algoritmo de agrupamento k-means e suas premissas. Geraremos dados com diferentes distribuições e visualizaremos como o k-means particiona esses dados em clusters. Também discutiremos algumas das limitações do algoritmo e possíveis soluções para superá-las.

Dicas da Máquina Virtual

Após o término da inicialização da VM, clique no canto superior esquerdo para mudar para a aba Notebook para acessar o Jupyter Notebook para praticar.

Às vezes, pode ser necessário aguardar alguns segundos para que o Jupyter Notebook termine de carregar. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.

Se você enfrentar problemas durante o aprendizado, sinta-se à vontade para perguntar ao Labby. Forneça feedback após a sessão e resolveremos prontamente o problema para você.

Geração de Dados

Usaremos a função make_blobs do scikit-learn para gerar diferentes conjuntos de dados com distribuições variadas. No bloco de código a seguir, geramos quatro conjuntos de dados:

  • Uma mistura de blobs gaussianos
  • Blobs distribuídos anisotrópica
  • Blobs com variância desigual
  • Blobs com tamanhos desiguais
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)  ## Blobs anisotrópicos
X_varied, y_varied = make_blobs(
    n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state
)  ## Variância desigual
X_filtered = np.vstack(
    (X[y == 0][:500], X[y == 1][:100], X[y == 2][:10])
)  ## Blobs com tamanhos desiguais
y_filtered = [0] * 500 + [1] * 100 + [2] * 10

Visualizar Dados

Usaremos o Matplotlib para visualizar os conjuntos de dados gerados. No bloco de código a seguir, criamos um gráfico 2x2 mostrando os clusters verdadeiros para cada conjunto de dados.

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("Mistura de Blobs Gaussianos")

axs[0, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y)
axs[0, 1].set_title("Blobs Distribuídos Anisotropicamente")

axs[1, 0].scatter(X_varied[:, 0], X_varied[:, 1], c=y_varied)
axs[1, 0].set_title("Variância Desigual")

axs[1, 1].scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_filtered)
axs[1, 1].set_title("Blobs com Tamanhos Desiguais")

plt.suptitle("Clusters verdadeiros").set_y(0.95)
plt.show()

Agrupamento K-Means

Usaremos a classe KMeans do scikit-learn para agrupar os dados. No bloco de código a seguir, criamos um gráfico 2x2 mostrando os clusters obtidos pelo k-means para cada conjunto de dados.

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("Número de Clusters Não Ótimo")

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("Blobs Distribuídos Anisotropicamente")

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("Variância Desigual")

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("Blobs com Tamanhos Desiguais")

plt.suptitle("Clusters KMeans Inesperados").set_y(0.95)
plt.show()

Soluções Possíveis

Vamos discutir algumas soluções possíveis para as limitações do agrupamento k-means. No bloco de código a seguir, mostramos como encontrar o número correto de clusters para o primeiro conjunto de dados e como lidar com blobs de tamanhos irregulares aumentando o número de inicializações aleatórias.

y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.title("Número Ótimo de 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("Blobs de Tamanhos Irregulares \ncom várias inicializações")
plt.show()

Modelo de Mistura Gaussiana

Vamos explorar o uso do Modelo de Mistura Gaussiana, que pode lidar com distribuições anisótropas e de variância desigual. No bloco de código a seguir, usamos GaussianMixture para agrupar os segundo e terceiro conjuntos de dados.

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("Blobs Distribuídos Anisotropicamente")

y_pred = GaussianMixture(n_components=3).fit_predict(X_varied)
ax2.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)
ax2.set_title("Variância Desigual")

plt.suptitle("Clusters do modelo de mistura gaussiana").set_y(0.95)
plt.show()

Resumo

Neste laboratório, exploramos o algoritmo de agrupamento k-means e suas suposições. Geramos diferentes conjuntos de dados com distribuições variadas e visualizamos como o k-means particiona esses dados em clusters. Também discutimos algumas das limitações do algoritmo e possíveis soluções para superá-las, incluindo a descoberta do número correto de clusters, o aumento do número de inicializações aleatórias e o uso do Modelo de Mistura Gaussiana.