O agrupamento K-means é um algoritmo de aprendizado não supervisionado que agrupa dados com base na distância euclidiana de cada ponto a um ponto central chamado centróide. Os centroides são definidos pela média de todos os pontos que estão no mesmo cluster. O algoritmo primeiro escolhe pontos aleatórios como centroides e então itera ajustando-os até a convergência total.
Uma coisa importante a ser lembrada ao usar o K-means, é que o número de clusters é um hiperparâmetro, ele será definido antes de executar o modelo.
K-means pode ser implementado usando Scikit-Learn com apenas 3 linhas de código. O Scikit-learn também já possui um método de otimização de centroides disponível, kmeans++, que ajuda o modelo a convergir mais rapidamente.
Para aplicar o algoritmo de agrupamento K-means, vamos carregar o Pinguins Palmer conjunto de dados, escolha as colunas que serão agrupadas e use o Seaborn para traçar um gráfico de dispersão com agrupamentos codificados por cores.
Note: Você pode baixar o conjunto de dados deste link.
Vamos importar as bibliotecas e carregar o conjunto de dados do Penguins, aparando-o nas colunas escolhidas e descartando as linhas com dados ausentes (havia apenas 2):
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
df = pd.read_csv('penguins.csv')
print(df.shape)
df = df[['bill_length_mm', 'flipper_length_mm']]
df = df.dropna(axis=0)
Podemos usar o método Elbow para ter uma indicação de clusters para nossos dados. Consiste na interpretação de um gráfico de linhas em forma de cotovelo. O número de clusters é onde as curvas do cotovelo. O eixo x do gráfico é o número de clusters e o eixo y é a soma dos quadrados dentro dos clusters (WCSS) para cada número de clusters:
wcss = []
for i in range(1, 11):
clustering = KMeans(n_clusters=i, init='k-means++', random_state=42)
clustering.fit(df)
wcss.append(clustering.inertia_)
ks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sns.lineplot(x = ks, y = wcss);
O método do cotovelo indica que nossos dados têm 2 clusters. Vamos plotar os dados antes e depois do agrupamento:
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(15,5))
sns.scatterplot(ax=axes[0], data=df, x='bill_length_mm', y='flipper_length_mm').set_title('Without clustering')
sns.scatterplot(ax=axes[1], data=df, x='bill_length_mm', y='flipper_length_mm', hue=clustering.labels_).set_title('Using the elbow method');
Este exemplo mostra como o método Elbow é apenas uma referência quando usado para escolher o número de clusters. Já sabemos que temos 3 tipos de pinguins no conjunto de dados, mas se determinássemos seu número usando o método Elbow, 2 clusters seriam nosso resultado.
Como o K-means é sensível à variação de dados, vejamos as estatísticas descritivas das colunas que estamos agrupando:
df.describe().T
Isto resulta em:
count mean std min 25% 50% 75% max
bill_length_mm 342.0 43.921930 5.459584 32.1 39.225 44.45 48.5 59.6
flipper_length_mm 342.0 200.915205 14.061714 172.0 190.000 197.00 213.0 231.0
Observe que a média está longe do desvio padrão (std), isso indica alta variância. Vamos tentar reduzi-lo dimensionando os dados com o Standard Scaler:
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
scaled = ss.fit_transform(df)
Agora, vamos repetir o processo do método Elbow para os dados dimensionados:
wcss_sc = []
for i in range(1, 11):
clustering_sc = KMeans(n_clusters=i, init='k-means++', random_state=42)
clustering_sc.fit(scaled)
wcss_sc.append(clustering_sc.inertia_)
ks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sns.lineplot(x = ks, y = wcss_sc);
Confira nosso guia prático e prático para aprender Git, com práticas recomendadas, padrões aceitos pelo setor e folha de dicas incluída. Pare de pesquisar comandos Git no Google e realmente aprender -lo!
Desta vez, o número sugerido de clusters é 3. Podemos plotar os dados com os rótulos dos clusters novamente junto com os dois gráficos anteriores para comparação:
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15,5))
sns.scatterplot(ax=axes[0], data=df, x='bill_length_mm', y='flipper_length_mm').set_title('Without cliustering')
sns.scatterplot(ax=axes[1], data=df, x='bill_length_mm', y='flipper_length_mm', hue=clustering.labels_).set_title('With the Elbow method')
sns.scatterplot(ax=axes[2], data=df, x='bill_length_mm', y='flipper_length_mm', hue=clustering_sc.labels_).set_title('With the Elbow method and scaled data');
Ao usar o K-means Clustering, você precisa pré-determinar o número de clusters. Como vimos ao usar um método para escolher nosso k número de clusters, o resultado é apenas uma sugestão e pode ser afetado pela quantidade de variação nos dados. É importante realizar uma análise aprofundada e gerar mais de um modelo com diferentes _k_s ao agrupar.
Se não houver indicação prévia de quantos clusters estão nos dados, visualize-os, teste-os e interprete-os para ver se os resultados do clustering fazem sentido. Se não, agrupar novamente. Além disso, observe mais de uma métrica e instancie diferentes modelos de agrupamento – para K-means, observe a pontuação da silhueta e talvez o agrupamento hierárquico para ver se os resultados permanecem os mesmos.