Algoritmo K-means
O algoritmo K-means é uma técnica de aprendizado de máquina não supervisionado, amplamente utilizada para a tarefa de agrupamento (ou “clustering”). O objetivo do K-means é dividir um conjunto de dados (N) em (K) grupos distintos (ou “clusters”), de forma que cada ponto pertença ao grupo cuja média (ou “centroide”) é a mais próxima possível. Este algoritmo é particularmente útil para identificar padrões subjacentes nos dados e para organizar grandes volumes de dados em categorias significativas, facilitando a análise e a interpretação.
Funcionamento do Algoritmo K-means:
- Inicialização: Primeiro, escolhem-se (K) pontos aleatórios dos dados como os centroides iniciais.
- Atribuição: Cada ponto do conjunto de dados é atribuído ao cluster cujo centroide é o mais próximo. A proximidade é geralmente medida usando a distância Euclidiana, embora outras métricas também possam ser utilizadas.
- Atualização do Centroide: Os centroides dos clusters são recalculados como a média de todos os pontos atribuídos ao cluster.
- Iteração: Os passos 2 e 3 são repetidos até que os centroides não se movam significativamente entre as iterações, o que indica que o algoritmo convergiu.
Exemplo de Aplicação em Python:
Vamos considerar um exemplo simples usando a biblioteca scikit-learn, que é uma das bibliotecas de aprendizado de máquina mais populares em Python. Suponha que temos um conjunto de dados bidimensional e queremos agrupá-los em (K=3) clusters.
Dados fixos:
#Carregar Bibliotecas import numpy as np import plotly.express as px import plotly.graph_objects as go from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans #Transformando dados em uma matriz base_salario = np.array([[20,1000],[27,1200],[21,2900],[35,1850],[46,900], [53,950],[55,2000],[47,2100],[52,3000],[32,5900], [39,4100],[41,5100],[39,7000],[48,5000],[48,6500]]) #Plotando os pontos grafico = px.scatter(x = base_salario[:,0], y = base_salario[:,1]) grafico.show() #Deixar os valores na mesma escala (escalonados), Existe uma grande diferença entre a idade e o salario scaler_salario = StandardScaler() base_salario_escalonado = scaler_salario.fit_transform(base_salario) base_salario_escalonado #Enviar os dados para o algoritmo Kmeans kmeans_salario = KMeans(n_clusters=3) kmeans_salario.fit(base_salario_escalonado) #Mostrar os centroides. Será exibido de forma escalonada centroides_escalonados = kmeans_salario.cluster_centers_ centroides_escalonados #Centroides convertidos não escalonada centroides = scaler_salario.inverse_transform(centroides_escalonados) centroides #Mostrar os rótulos rotulos = kmeans_salario.labels_ rotulos #Gerar o gráfico grafico1 = px.scatter(x = base_salario[:,0], y = base_salario[:,1], color=rotulos) grafico2 = px.scatter(x = centroides[:,0], y = centroides[:,1], size=[1,1,1]) grafico3 = go.Figure(data = grafico1.data + grafico2.data) grafico3.show()
Dados Aleatórios:
#Carregar Bibliotecas import numpy as np import plotly.express as px import plotly.graph_objects as go from sklearn.preprocessing import StandardScaler from sklearn.datasets import make_blobs from sklearn.cluster import KMeans #Dados Aleatórios X_random, k_random = make_blobs(n_samples=200, centers=5, random_state=1) #Valores de x,y X_random #Valores de k k_random #Plotando os pontos grafico = px.scatter(x = X_random[:,0], y = X_random[:,1]) grafico.show() #Enviar os dados para o algoritmo Kmeans kmeans_salario = KMeans(n_clusters=5) kmeans_salario.fit(X_random) #Mostrar os centroides. Será exibido de forma escalonada centroides = kmeans_salario.cluster_centers_ centroides #Mostrar os rótulos rotulos = kmeans_salario.labels_ rotulos #Gerar o gráfico grafico1 = px.scatter(x = base_salario[:,0], y = base_salario[:,1], color=rotulos) grafico2 = px.scatter(x = centroides[:,0], y = centroides[:,1], size=[1,1,1,1,1]) grafico3 = go.Figure(data = grafico1.data + grafico2.data) grafico3.show()
Aplicações do K-means:
O K-means pode ser aplicado a uma ampla gama de problemas, como:
Segmentação de Mercado: Agrupar clientes com características semelhantes para campanhas de marketing direcionadas.
Organização de Inventário: Agrupar produtos em categorias baseadas em características ou comportamento de compra.
Detecção de Anomalias: Identificar padrões incomuns ou outliers.
Agrupamento de Documentos: Agrupar documentos com temas ou palavras-chave semelhantes para facilitar a organização ou a busca.
O algoritmo K-means é apreciado por sua simplicidade e eficácia, mas é importante notar que ele tem algumas limitações, como a sensibilidade à escolha dos centroides iniciais e a dificuldade em lidar com clusters de formas não esféricas ou tamanhos variados
Dataset Iris:
#Carregar Pandas import pandas as pd data = pd.read_csv('iris.csv') data.head() #Mostra os primeiros registros do dataframe data list(data.columns) #Mostra os nomes das colunas do dataframe data.info() features = data.iloc[:,:-1] #todas as linhas (:) e todas as colunas exceto a última (:-1) target = data.iloc[:,-1] #todas as linhas (:) e apenas a última coluna (-1) print(features) print(target) X = data.iloc[:,0:4].values #Separa somente as colunas das características X from sklearn.manifold import TSNE # Classe para redução da dimensionalidade #Reduz de 4 para 2 características X_reduzido = TSNE(n_components = 2).fit_transform(X) X_reduzido #Transforma as amostras obtidas pelo TSNE em dataframe data_reduzido = pd.DataFrame(X_reduzido) data_reduzido #Extrai a coluna dos rótulos das classes classes = data.iloc[:,4] classes #Reúne as amostras e os rótulos das classes data_reduzido.insert(2, 'classe', classes) data_reduzido #Altera os nomes das colunas data_reduzido = data_reduzido.rename(columns = {0: "carac_0", 1: "carac_1"}) data_reduzido import seaborn as sns #Plota as amostras reduzidas em 2D sns.scatterplot(x = data_reduzido['carac_0'], y = data_reduzido['carac_1'],hue = data_reduzido.classe, style = data_reduzido.classe) from sklearn.cluster import KMeans #Importação do algoritmo k-means kmeans = KMeans(n_clusters = 3, init = 'random', n_init = 10, max_iter = 300, tol = 1e-04, random_state = 0) # Parametrização do modelo kmeans.fit(X_reduzido) # Computa os centroides do clusters predicao = kmeans.predict(X_reduzido) # Associa os objetos aos índices da classe from sklearn.metrics import silhouette_score score = silhouette_score(X_reduzido, predicao) print('Silhouette Score: %.3f' % score) from matplotlib import pyplot as plt sns.scatterplot(x=X_reduzido[:,0], y=X_reduzido[:,1], hue=predicao, style=predicao) plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=250, marker='*', c='red', edgecolor='black', label='centroids') plt.legend(scatterpoints=1) plt.grid() plt.show()
O Silhouette Score é uma métrica usada para calcular a eficácia da clusterização, ou seja, o quão bem cada objeto foi classificado em seu cluster em comparação com outros clusters. Essa métrica fornece uma perspectiva sobre a separação de distância entre os clusters resultantes. O valor do Silhouette Score varia de -1 a 1, onde um valor alto indica que o objeto está bem combinado com seu próprio cluster e mal combinado com os clusters vizinhos.
Interpretação do Silhouette Score
Próximo de +1: Um valor próximo de +1 indica que o ponto está longe dos clusters vizinhos, ou seja, está bem posicionado dentro de seu próprio cluster e longe dos outros clusters. Isso sugere uma clusterização apropriada e clara.
Próximo de 0: Um valor próximo de 0 indica que o ponto está próximo à fronteira de decisão entre dois clusters vizinhos. Isso pode sugerir que a atribuição de clusters pode ser arbitrária, pois o ponto está igualmente distante de ambos os clusters.
Próximo de -1: Um valor próximo de -1 indica que o ponto foi atribuído ao cluster errado, estando mais próximo dos pontos de outro cluster
O que significa um Silhouette Score de 0.68?
Um Silhouette Score de 0.68 é considerado bom e indica que, em média, os pontos estão bem atribuídos aos seus clusters, com uma boa separação entre os clusters. Isso significa que a maioria dos pontos está mais próxima dos pontos dentro de seu próprio cluster do que dos pontos em clusters diferentes, sugerindo que a clusterização foi, em grande parte, bem-sucedida.
No entanto, é importante notar que esse valor é uma média, e pode haver variações individuais dentro dos clusters. Alguns pontos ainda podem estar mal posicionados ou mais próximos de outros clusters.
Dataset Wine:
Para aplicar o algoritmo K-means no dataset wine do sklearn, primeiro precisamos carregar esse dataset. O dataset wine é um conjunto de dados clássico que contém os resultados de uma análise química de vinhos cultivados em uma mesma região da Itália, mas derivados de três diferentes cultivares. O conjunto de dados consiste em 13 características diferentes medidas para cada amostra de vinho, com 178 amostras:
- alcohol (álcool)
- malic_acid (ácido málico)
- ash (cinzas)
- alcalinity_of_ash (alcalinidade das cinzas)
- magnesium (magnésio)
- total_phenols (fenóis totais)
- flavonoids (flavonóides)
- nonflavanoid_phenols (fenóis não flavonóides)
- proanthocyanins (proantocinidinas)
- color_intensity (intensidade de cor)
- hue (matiz)
- od280/od315_of_diluted_wines (od280/od315 de vinhos diluídos)
- proline (proline)
Vamos seguir os passos para aplicar o K-means a este dataset:
- Carregar o dataset wine.
- Pré-processar os dados, se necessário (por exemplo, escalonamento dos dados).
- Aplicar o algoritmo K-means.
- Visualizar os resultados
import pandas as pd data = pd.read_csv('wine.csv') data.head() #Mostra os primeiros registros do dataframe data list(data.columns) #Mostra os nomes das colunas do dataframe data.info() features = data.iloc[:,1:] #todas as colunas começando da segunda coluna até a última target = data.iloc[:,0] #todas as linhas (:) e apenas a primiera coluna print(features) print(target) X = data.iloc[:,1:14].values #Separa somente as colunas das características X from sklearn.manifold import TSNE # Classe para redução da dimensionalidade #Reduz de 4 para 2 características X_reduzido = TSNE(n_components = 2).fit_transform(X) X_reduzido #Transforma as amostras obtidas pelo TSNE em dataframe data_reduzido = pd.DataFrame(X_reduzido) data_reduzido #Extrai a coluna dos rótulos das classes classes = data.iloc[:,0] classes #Reúne as amostras e os rótulos das classes data_reduzido.insert(2, 'wine', classes) data_reduzido #Altera os nomes das colunas data_reduzido = data_reduzido.rename(columns = {0: "carac_0", 1: "carac_1"}) data_reduzido import seaborn as sns #Plota as amostras reduzidas em 2D sns.scatterplot(x = data_reduzido['carac_0'], y = data_reduzido['carac_1'],hue = data_reduzido.wine, style = data_reduzido.wine) from sklearn.cluster import KMeans #Importação do algoritmo k-means kmeans = KMeans(n_clusters = 3, init = 'random', n_init = 10, max_iter = 300, tol = 1e-04, random_state = 0) # Parametrização do modelo kmeans.fit(X_reduzido) # Computa os centroides do clusters predicao = kmeans.predict(X_reduzido) # Associa os objetos aos índices da classe from sklearn.metrics import silhouette_score score = silhouette_score(X_reduzido, predicao) print('Silhouette Score: %.3f' % score) from matplotlib import pyplot as plt sns.scatterplot(x=X_reduzido[:,0], y=X_reduzido[:,1], hue=predicao, style=predicao) plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=250, marker='*', c='red', edgecolor='black', label='centroids') plt.legend(scatterpoints=1) plt.grid() plt.show()
Interpretando um Silhouette Score de 0.62:
Um Silhouette Score de 0.62 é geralmente considerado um bom valor, indicando que, em média, os clusters estão bem definidos e separados. Pontos dentro de um cluster estão relativamente próximos uns dos outros, e há uma boa distância entre os clusters. Isso significa que a clusterização conseguiu agrupar os dados de uma maneira que os membros de cada cluster são mais semelhantes entre si do que com membros de outros clusters, o que é um indicativo de uma clusterização eficaz.
No entanto, é importante notar que o Silhouette Score fornece uma visão geral da qualidade da clusterização, mas não deve ser o único critério para avaliar a eficácia de um modelo de clusterização. Outros fatores, como conhecimento do domínio e objetivos específicos do projeto, também devem ser considerados na avaliação de um modelo de clusterização.