Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

1
resposta

[Projeto] Pesquisa sobre seleção de agrupamento

Vimos na base iris que, por conhecimento do "negócio" temos 3 classes (tiposd e flor), mas digamos que estivessemos entre muitas outras classes possíveis e quissemos saber qual melhor K, pesquisie algumas formas:

Silhouette Score
Davies-Bouldin
Calinski-Harabasz
Visualização (PCA, t-SNE, UMAP)

No teste com a base iris sempre apontou k=2, o que não é a realidade.

Na prática, alguém escolhe k não apenas matemáticamente, mas com conhecimento do negócio, pode ser que se deseje k 2,3,5,10 conforme o caso. Por exemplo, mesmo que aparente 2, a seleção pode ser 3. Mesmo que um silhoute mostre 7 um cliente pode preferir 5 grupos de um problema.

from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import AgglomerativeClustering
from sklearn.metrics import (
    silhouette_score,
    davies_bouldin_score,
    calinski_harabasz_score
)
from sklearn.decomposition import PCA
import pandas as pd
import matplotlib.pyplot as plt

# ======================
# Carregar e preparar dados
# ======================
iris = load_iris()
X = iris.data

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# ======================
# Testar vários valores de K
# ======================
resultados = []

for k in range(2, 11):

    modelo = AgglomerativeClustering(
        n_clusters=k,
        linkage='ward'
    )

    labels = modelo.fit_predict(X_scaled)

    silhouette = silhouette_score(X_scaled, labels)
    davies = davies_bouldin_score(X_scaled, labels)
    calinski = calinski_harabasz_score(X_scaled, labels)

    resultados.append([
        k,
        silhouette,
        davies,
        calinski
    ])

# ======================
# Exibir métricas
# ======================
df_metricas = pd.DataFrame(
    resultados,
    columns=[
        "k",
        "Silhouette",
        "Davies-Bouldin",
        "Calinski-Harabasz"
    ]
)

print(df_metricas)

# Melhor K por cada métrica
print("\nMelhor Silhouette:")
print(df_metricas.loc[df_metricas["Silhouette"].idxmax()])

print("\nMelhor Davies-Bouldin:")
print(df_metricas.loc[df_metricas["Davies-Bouldin"].idxmin()])

print("\nMelhor Calinski-Harabasz:")
print(df_metricas.loc[df_metricas["Calinski-Harabasz"].idxmax()])

# ======================
# Escolha do K
# ======================
k_escolhido = 3  #PORQUE CONHECEMOS A BASE DE DADOS, O NEGÓCIO, O PROBLEMA, MATEMATIMENTE DEU "ERRADO" FICOU 2

modelo_final = AgglomerativeClustering(
    n_clusters=k_escolhido,
    linkage='ward'
)

labels = modelo_final.fit_predict(X_scaled)

# ======================
# PCA para visualização
# ======================
pca = PCA(n_components=2)

X_pca = pca.fit_transform(X_scaled)

plt.figure(figsize=(8, 6))

scatter = plt.scatter(
    X_pca[:, 0],
    X_pca[:, 1],
    c=labels
)

plt.title(
    f"Agglomerative Clustering (k={k_escolhido})"
)

plt.xlabel("PCA 1")
plt.ylabel("PCA 2")

plt.colorbar(scatter, label="Cluster")

plt.show()
1 resposta

Oii Marcelo, tudo bem?

Obrigada por compartilhar sua pesquisa no fórum! Você foi além do proposto e trouxe uma reflexão muito relevante na prática: as métricas matemáticas são um guia, mas a decisão final sobre k quase sempre envolve contexto de negócio.

O ponto que você destacou no comentário #PORQUE CONHECEMOS A BASE DE DADOS... resume bem essa tensão. O Silhouette, Davies-Bouldin e Calinski-Harabasz otimizam separação e coesão dos clusters, mas não sabem nada sobre o que os grupos significam para quem vai usar o modelo. No caso do Iris, k=2 separa bem setosa das outras duas, que de fato se sobrepõem bastante. Matematicamente faz sentido. Mas biologicamente (e pelo negócio) são três espécies, então k=3 é a escolha certa.

Seu uso do PCA para visualização também é uma boa prática: quando os dados têm muitas dimensões, jogar para 2D e olhar a separação visual complementa muito as métricas numéricas.

Uma observação para enriquecer ainda mais: vale considerar o dendrograma do agrupamento hierárquico antes de escolher k. Ele mostra visualmente onde as fusões mais "caras" ocorrem (saltos grandes na altura), o que pode confirmar ou questionar a escolha. Com AgglomerativeClustering você pode plotar usando scipy.cluster.hierarchy:

from scipy.cluster.hierarchy import dendrogram, linkage

Z = linkage(X_scaled, method='ward')
dendrogram(Z)
plt.title("Dendrograma")
plt.show()

Se quiser se aprofundar em PCA, que você já está usando para visualização:

Conte com a Alura para evoluir seus estudos. Em caso de dúvidas, fico à disposição.

Bons estudos!

Sucesso

Imagem da comunidade