Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Guia definitivo para clustering K-Means com Scikit-Learn

Introdução

Agrupamento K-Means é um dos algoritmos de aprendizado de máquina não supervisionados mais usados ​​que formam clusters de dados com base na semelhança entre instâncias de dados.

Neste guia, veremos primeiro um exemplo simples para entender como o algoritmo K-Means funciona antes de implementá-lo usando o Scikit-Learn. Em seguida, discutiremos como determinar o número de clusters (Ks) no K-Means e também abordaremos as métricas de distância, variância e prós e contras do K-Means.

Motivação

Imagine a seguinte situação. Um dia, ao passear pelo bairro, você notou que havia 10 lojas de conveniência e começou a se perguntar quais lojas eram semelhantes – mais próximas umas das outras na proximidade. Ao pesquisar maneiras de responder a essa pergunta, você se deparou com uma abordagem interessante que divide as lojas em grupos com base em suas coordenadas em um mapa.

Por exemplo, se uma loja estivesse localizada 5 km a oeste e 3 km ao norte - você atribuiria (5, 3) coordenadas para ele, e representá-lo em um gráfico. Vamos traçar este primeiro ponto para visualizar o que está acontecendo:

import matplotlib.pyplot as plt

plt.title("Store With Coordinates (5, 3)")
plt.scatter(x=5, y=3)

Este é apenas o primeiro ponto, para que possamos ter uma ideia de como podemos representar uma loja. Digamos que já temos 10 coordenadas para as 10 lojas coletadas. Depois de organizá-los em numpy array, também podemos traçar suas localizações:

import numpy as np

points = np.array([[5, 3], [10, 15], [15, 12], [24, 10], [30, 45], [85, 70], [71, 80], [60, 78], [55, 52],[80, 91]])

xs = points[:,0] 
ys = points[:,1]  

plt.title("10 Stores Coordinates")
plt.scatter(x=xs, y=ys)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Como implementar manualmente o algoritmo K-Means

Agora podemos olhar para as 10 lojas em um gráfico, e o principal problema é encontrar uma maneira de dividi-las em diferentes grupos com base na proximidade? Dando uma olhada rápida no gráfico, provavelmente perceberemos dois grupos de lojas – um são os pontos inferiores no canto inferior esquerdo e o outro são os pontos superiores direito. Talvez possamos até diferenciar esses dois pontos no meio como um grupo separado – criando assim três grupos diferentes.

Nesta seção, veremos o processo de agrupamento manual de pontos – dividindo-os em um determinado número de grupos. Dessa forma, vamos essencialmente passar por cima de todas as etapas do Algoritmo de agrupamento K-Means. Ao final desta seção, você obterá uma compreensão intuitiva e prática de todas as etapas realizadas durante o agrupamento K-Means. Depois disso, vamos delegá-lo ao Scikit-Learn.

Qual seria a melhor maneira de determinar se existem dois ou três grupos de pontos? Uma maneira simples seria simplesmente escolher um número de grupos – por exemplo, dois – e então tentar agrupar pontos com base nessa escolha.

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Digamos que decidimos que existem dois grupos das nossas lojas (pontos). Agora, precisamos encontrar uma maneira de entender quais pontos pertencem a qual grupo. Isso pode ser feito escolhendo um ponto para representar grupo 1 e um para representar grupo 2. Esses pontos serão usados ​​como referência ao medir a distância de todos os outros pontos para cada grupo.

Dessa forma, diga ponto (5, 3) acaba pertencendo ao grupo 1, e ponto (79, 60) ao grupo 2. Ao tentar atribuir um novo ponto (6, 3) para grupos, precisamos medir sua distância a esses dois pontos. No caso do ponto (6, 3) is mais próximo ao (5, 3), portanto pertence ao grupo representado por aquele ponto – grupo 1. Desta forma, podemos agrupar facilmente todos os pontos em grupos correspondentes.

Neste exemplo, além de determinar o número de grupos (cachos) – também estamos escolhendo alguns pontos para referência de distância para novos pontos de cada grupo.

Essa é a ideia geral para entender as semelhanças entre nossas lojas. Vamos colocá-lo em prática - podemos primeiro escolher os dois pontos de referência em acaso. O ponto de referência de grupo 1 será (5, 3) e o ponto de referência grupo 2 será (10, 15). Podemos selecionar ambos os pontos de nossa numpy matriz por [0] e [1] índices e armazená-los em g1 (grupo 1) e g2 (grupo 2) variáveis:

g1 = points[0]
g2 = points[1]

Depois de fazer isso, precisamos calcular a distância de todos os outros pontos para esses pontos de referência. Isso levanta uma questão importante – como medir essa distância. Podemos essencialmente usar qualquer medida de distância, mas, para os propósitos deste guia, vamos usar a Distância Euclidiana_.

Pode ser útil saber que a medida de distância euclidiana é baseada no teorema de Pitágoras:

$$
c^2 = a^2 + b^2
$$

Quando adaptado a pontos em um plano – (a1, b1) e (a2, b2), a fórmula anterior se torna:

$$
c^2 = (a2-a1)^2 + (b2-b1)^2
$$

A distância será a raiz quadrada de c, então também podemos escrever a fórmula como:

$$
euclidiano_{dist} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2)]
$$

Observação: Você também pode generalizar a fórmula da distância euclidiana para pontos multidimensionais. Por exemplo, em um espaço tridimensional, os pontos têm três coordenadas – nossa fórmula reflete isso da seguinte maneira:
$$
euclidiano_{dist} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2 + (c2 – c1) ^2)]
$$
O mesmo princípio é seguido independentemente do número de dimensões do espaço em que estamos operando.

Até agora, escolhemos os pontos para representar grupos e sabemos calcular distâncias. Agora, vamos juntar as distâncias e os grupos atribuindo cada um de nossos pontos de armazenamento coletados a um grupo.

Para melhor visualizar isso, vamos declarar três listas. O primeiro a armazenar pontos do primeiro grupo – points_in_g1. O segundo para armazenar pontos do grupo 2 – points_in_g2, e o último - groupà rótulo os pontos tanto 1 (pertence ao grupo 1) ou 2 (pertence ao grupo 2):

points_in_g1 = []
points_in_g2 = []
group = []

Agora podemos percorrer nossos pontos e calcular a distância euclidiana entre eles e cada uma de nossas referências de grupo. Cada ponto será mais próximo a um dos dois grupos - com base em qual grupo está mais próximo, atribuiremos cada ponto à lista correspondente, além de adicionar 1 or 2 ao group Lista:

for p in points:
    x1, y1 = p[0], p[1]
    euclidean_distance_g1 = np.sqrt((g1[0] - x1)**2 + (g1[1] - y1)**2)
    euclidean_distance_g2 = np.sqrt((g2[0] - x1)**2 + (g2[1] - y1)**2)
    if euclidean_distance_g1 < euclidean_distance_g2:
        points_in_g1.append(p)
        group.append('1')
    else:
        points_in_g2.append(p)
        group.append('2')

Vejamos os resultados desta iteração para ver o que aconteceu:

print(f'points_in_g1:{points_in_g1}n 
npoints_in_g2:{points_in_g2}n 
ngroup:{group}')

O que resulta em:

points_in_g1:[array([5, 3])]
 
points_in_g2:[array([10, 15]), array([15, 12]), 
              array([24, 10]), array([30, 45]), 
              array([85, 70]), array([71, 80]),
              array([60, 78]), array([55, 52]), 
              array([80, 91])]
 
group:[1, 2, 2, 2, 2, 2, 2, 2, 2, 2] 

Também podemos plotar o resultado do agrupamento, com cores diferentes com base nos grupos atribuídos, usando o Seaborn's scatterplot() com o group como um hue argumento:

import seaborn as sns

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

É claramente visível que apenas nosso primeiro ponto é atribuído ao grupo 1, e todos os outros pontos foram atribuídos ao grupo 2. Esse resultado difere do que imaginávamos no início. Considerando a diferença entre nossos resultados e nossas expectativas iniciais – existe uma maneira de mudar isso? Parece que existe!

Uma abordagem é repetir o processo e escolher diferentes pontos para serem as referências dos grupos. Isso mudará nossos resultados, esperamos, mais de acordo com o que imaginamos no início. Desta segunda vez, poderíamos escolhê-los não aleatoriamente como fizemos anteriormente, mas obtendo um significar de todos os nossos pontos já agrupados. Dessa forma, esses novos pontos poderiam ser posicionados no meio dos grupos correspondentes.

Por exemplo, se o segundo grupo tivesse apenas pontos (10, 15), (30, 45). O novo central ponto seria (10 + 30)/2 e (15+45)/2 – que é igual a (20, 30).

Como colocamos nossos resultados em listas, podemos convertê-los primeiro em numpy matrizes, selecione seus xs, ys e, em seguida, obtenha o significar:

g1_center = [np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()]
g2_center = [np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()]
g1_center, g2_center

Conselho: Tente usar numpy e matrizes NumPy, tanto quanto possível. Eles são otimizados para melhor desempenho e simplificam muitas operações de álgebra linear. Sempre que você estiver tentando resolver algum problema de álgebra linear, você definitivamente deve dar uma olhada no numpy documentação para verificar se há numpy método projetado para resolver seu problema. A chance é que haja!

Para ajudar a repetir o processo com nossos novos pontos centrais, vamos transformar nosso código anterior em uma função, executá-lo e ver se houve alguma alteração na forma como os pontos são agrupados:

def assigns_points_to_two_groups(g1_center, g2_center):
    points_in_g1 = []
    points_in_g2 = []
    group = []

    for p in points:
        x1, y1 = p[0], p[1]
        euclidean_distance_g1 = np.sqrt((g1_center[0] - x1)**2 + (g1_center[1] - y1)**2)
        euclidean_distance_g2 = np.sqrt((g2_center[0] - x1)**2 + (g2_center[1] - y1)**2)
        if euclidean_distance_g1 < euclidean_distance_g2:
            points_in_g1.append(p)
            group.append(1)
        else:
            points_in_g2.append(p)
            group.append(2)
    return points_in_g1, points_in_g2, group

Observação: Se você perceber que continua repetindo o mesmo código várias vezes, você deve agrupar esse código em uma função separada. É considerada uma boa prática organizar o código em funções, especialmente porque facilitam os testes. É mais fácil testar e isolar um pedaço de código do que um código completo sem nenhuma função.

Vamos chamar a função e armazenar seus resultados em points_in_g1, points_in_g2 e group variáveis:

points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
points_in_g1, points_in_g2, group

E também trace o gráfico de dispersão com os pontos coloridos para visualizar a divisão dos grupos:

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Parece que o agrupamento de nossos pontos é ficando melhor. Mas ainda assim, existem dois pontos no meio do gráfico que podem ser atribuídos a qualquer grupo ao considerar sua proximidade com ambos os grupos. O algoritmo que desenvolvemos até agora atribui esses dois pontos ao segundo grupo.

Isso significa que provavelmente podemos repetir o processo mais uma vez tomando a média dos Xs e Ys, criando dois novos pontos centrais (centroides) aos nossos grupos e reatribuindo-os com base na distância.

Vamos também criar uma função para atualizar os centroides. Todo o processo agora pode ser reduzido a várias chamadas dessa função:

def updates_centroids(points_in_g1, points_in_g2):
    g1_center = np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()
    g2_center = np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()
    return g1_center, g2_center

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Observe que após esta terceira iteração, cada um dos pontos agora pertence a diferentes clusters. Parece que os resultados estão melhorando – vamos fazer isso mais uma vez. Agora indo para o quarta iteração do nosso método:

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Esta quarta vez que temos o mesmo resultado como o anterior. Então parece que nossos pontos não vão mais mudar de grupo, nosso resultado alcançou algum tipo de estabilidade – chegou a um estado imutável, ou convergido. Além disso, temos exatamente o mesmo resultado que imaginávamos para os 2 grupos. Também podemos ver se essa divisão alcançada faz sentido.

Vamos recapitular rapidamente o que fizemos até agora. Dividimos nossas 10 lojas geograficamente em duas seções – uma na região sudoeste e outra no nordeste. Pode ser interessante coletar mais dados além do que já temos – receita, número diário de clientes e muito mais. Dessa forma podemos realizar uma análise mais rica e possivelmente gerar resultados mais interessantes.

Estudos de agrupamento como esse podem ser realizados quando uma marca já estabelecida deseja escolher uma área para abrir uma nova loja. Nesse caso, há muito mais variáveis ​​levadas em consideração além da localização.

O que tudo isso tem a ver com o algoritmo K-Means?

Ao seguir essas etapas, você deve ter se perguntado o que elas têm a ver com o algoritmo K-Means. O processo que conduzimos até agora é o Algoritmo K-Means. Resumindo, determinamos o número de grupos/clusters, escolhemos aleatoriamente os pontos iniciais e atualizamos os centroides em cada iteração até que os clusters convergissem. Basicamente, executamos todo o algoritmo manualmente – conduzindo cuidadosamente cada etapa.

A K em K-Means vem do número de clusters que precisam ser definidos antes de iniciar o processo de iteração. No nosso caso K = 2. Essa característica às vezes é vista como negativo considerando que existem outros métodos de clustering, como Hierarchical Clustering, que não precisam ter um número fixo de clusters previamente.

Devido ao uso de meios, K-means também se torna sensível a outliers e valores extremos – eles aumentam a variabilidade e tornam mais difícil para nossos centróides desempenharem seu papel. Portanto, esteja consciente da necessidade de realizar valores extremos e análise de outliers antes de realizar um agrupamento usando o algoritmo K-Means.

Além disso, observe que nossos pontos foram segmentados em partes retas, não há curvas ao criar os clusters. Isso também pode ser uma desvantagem do algoritmo K-Means.

Observação: Quando você precisar que ele seja mais flexível e adaptável a elipses e outras formas, tente usar um modelo generalizado de mistura gaussiana K-médias. Este modelo pode se adaptar a clusters de segmentação elíptica.

K-Means também tem muitos vantagens! Ele funciona bem em grandes conjuntos de dados que pode se tornar difícil de manusear se você estiver usando alguns tipos de algoritmos de agrupamento hierárquico. Isso também garante a convergência, e pode facilmente generalizar e adaptar. Além disso, é provavelmente o algoritmo de agrupamento mais utilizado.

Agora que passamos por todas as etapas realizadas no algoritmo K-Means e entendemos todos os seus prós e contras, podemos finalmente implementar o K-Means usando a biblioteca Scikit-Learn.

Como implementar o algoritmo K-Means usando scikit-learn

Para verificar nosso resultado, vamos fazer esse processo novamente, mas agora usando 3 linhas de código com sklearn:

from sklearn.cluster import KMeans


kmeans = KMeans(n_clusters=2, random_state=42) 
kmeans.fit(points)
kmeans.labels_

Aqui, os rótulos são os mesmos dos nossos grupos anteriores. Vamos plotar rapidamente o resultado:

sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

O gráfico resultante é o mesmo da seção anterior.

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!

Observação: Só de ver como executamos o algoritmo K-Means usando o Scikit-Learn pode dar a impressão de que é um acéfalo e que você não precisa se preocupar muito com isso. Apenas 3 linhas de código executam todas as etapas que discutimos na seção anterior quando analisamos o algoritmo K-Means passo a passo. Mas, O diabo está nos detalhes nesse caso! Se você não entender todas as etapas e limitações do algoritmo, provavelmente enfrentará a situação em que o algoritmo K-Means fornece resultados que você não esperava.

Com o Scikit-Learn, você também pode inicializar o K-Means para uma convergência mais rápida, definindo o init='k-means++' argumento. Em termos mais amplos, K-Means++ ainda escolhe o k centros de cluster iniciais aleatoriamente seguindo uma distribuição uniforme. Então, cada centro de cluster subsequente é escolhido a partir dos pontos de dados restantes, não calculando apenas uma medida de distância – mas usando probabilidade. Usar a probabilidade acelera o algoritmo e é útil ao lidar com conjuntos de dados muito grandes.

O Método do Cotovelo – Escolhendo o Melhor Número de Grupos

Até agora tudo bem! Agrupamos 10 lojas com base na distância euclidiana entre pontos e centroides. Mas e aqueles dois pontos no meio do gráfico que são um pouco mais difíceis de agrupar? Eles não poderiam formar um grupo separado também? Será que cometemos um erro ao escolher K = 2 grupos? Talvez nós realmente tivéssemos K = 3 grupos? Poderíamos até ter mais de três grupos e não estarmos cientes disso.

A pergunta que está sendo feita aqui é como determinar o número de grupos (K) em K-Means. Para responder a essa pergunta, precisamos entender se haveria um cluster “melhor” para um valor diferente de K.

A maneira ingênua de descobrir isso é agrupando pontos com diferentes valores de K, assim, para K=2, K=3, K=4 e assim por diante:

for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 

Mas, agrupando pontos para diferentes Ks sozinho não será suficiente para entender se escolhemos o valor ideal para K. Precisamos de uma maneira de avaliar a qualidade do agrupamento para cada K nós escolhemos.

Calculando manualmente o Dentro da soma dos quadrados do cluster (WCSS)

Aqui é o lugar ideal para introduzir uma medida de quanto nossos pontos agrupados estão próximos uns dos outros. Basicamente descreve o quanto variação temos dentro de um único cluster. Essa medida é chamada Dentro do Cluster Soma de Quadradosou WCSS como diminutivo. Quanto menor for o WCSS, mais próximos estarão nossos pontos, portanto teremos um cluster mais bem formado. A fórmula WCSS pode ser usada para qualquer número de clusters:

$$
WCSS = soma(Pi_1 – Centroid_1)^2 + cdots + soma(Pi_n – Centroid_n)^2
$$

Observação: Neste guia, estamos usando o Distância euclidiana para obter os centróides, mas outras medidas de distância, como Manhattan, também poderiam ser utilizadas.

Agora podemos assumir que optamos por ter dois clusters e tentar implementar o WCSS para entender melhor o que é o WCSS e como usá-lo. Como a fórmula indica, precisamos somar as diferenças quadradas entre todos os pontos do cluster e os centróides. Então, se nosso primeiro ponto do primeiro grupo é (5, 3) e nosso último centróide (após a convergência) do primeiro grupo é (16.8, 17.0), o WCSS será:

$$
WCSS = soma((5,3) – (16.8, 17.0))^2
$$

$$
WCSS = soma((5-16.8) + (3-17.0))^2
$$

$$
WCSS = soma((-11.8) + (-14.0))^2
$$

$$
WCSS = soma((-25.8))^2
$$

$$
WCSS = 335.24
$$

Este exemplo ilustra como calculamos o WCSS para um ponto do cluster. Mas o cluster geralmente contém mais de um ponto, e precisamos levar todos eles em consideração ao calcular o WCSS. Faremos isso definindo uma função que recebe um cluster de pontos e centróides e retorna a soma dos quadrados:

def sum_of_squares(cluster, centroid):
    squares = []
    for p in cluster:
        squares.append((p - centroid)**2)
        ss = np.array(squares).sum()
    return ss

Agora podemos obter a soma dos quadrados para cada cluster:

g1 = sum_of_squares(points_in_g1, g1_center)
g2 = sum_of_squares(points_in_g2, g2_center)

E some os resultados para obter o total WCSS:

g1 + g2

Isto resulta em:

2964.3999999999996

Então, no nosso caso, quando K é igual a 2, o WCSS total é 2964.39. Agora, podemos alternar Ks e calcular o WCSS para todos eles. Dessa forma, podemos ter uma ideia do que K devemos escolher fazer com que nosso cluster tenha o melhor desempenho.

Calculando WCSS utilização scikit-learn

Felizmente, não precisamos calcular manualmente o WCSS para cada K. Depois de realizar o agrupamento K-Means para um determinado número de clusters, podemos obter seu WCSS usando o inertia_ atributo. Agora, podemos voltar ao nosso K-Means for loop, use-o para alternar o número de clusters e liste os valores WCSS correspondentes:

wcss = [] 
for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 
    wcss.append(kmeans.inertia_)
wcss

Observe que o segundo valor na lista é exatamente o mesmo que calculamos antes para K = 2:

[18272.9, # For k=1 
 2964.3999999999996, # For k=2
 1198.75, # For k=3
 861.75,
 570.5,
 337.5,
 175.83333333333334,
 79.5,
 17.0,
 0.0]

Para visualizar esses resultados, vamos plotar nossa Ks juntamente com os valores WCSS:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Há uma interrupção em uma trama quando x = 2, um ponto baixo na linha, e um ainda mais baixo quando x = 3. Perceba que isso nos lembra do forma de cotovelo. Ao plotar os Ks junto com o WCSS, estamos usando o Método do cotovelo para escolher o número de Ks. E a K escolhido é exatamente o ponto mais baixo do cotovelo, então seria 3 em vez de 2, no nosso caso:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss);
plt.axvline(3, linestyle='--', color='r')

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Podemos executar o algoritmo de cluster K-Means novamente, para ver como nossos dados ficariam com três grupos:

kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(points)
sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Já estávamos satisfeitos com dois clusters, mas de acordo com o método do cotovelo, três clusters seriam mais adequados para nossos dados. Nesse caso, teríamos três tipos de lojas em vez de duas. Antes de usar o método do cotovelo, pensávamos nos clusters de lojas do sudoeste e nordeste, agora também temos lojas no centro. Talvez esse possa ser um bom local para abrir outra loja, pois teria menos concorrência nas proximidades.

Medidas alternativas de qualidade do cluster

Há também outras medidas que podem ser usadas ao avaliar a qualidade do cluster:

  • Pontuação da Silhueta – analisa não apenas a distância entre os pontos intra-cluster, mas também entre os próprios clusters
  • Entre Clusters Soma de Quadrados (BCSS) – métrica complementar ao WCSS
  • Erro de soma de quadrados (SSE)
  • Raio Máximo – mede a maior distância de um ponto ao seu centróide
  • Raio médio – a soma da maior distância de um ponto ao seu centroide dividido pelo número de clusters.

Recomenda-se experimentar e conhecer cada um deles, pois dependendo do problema, algumas das alternativas podem ser mais aplicáveis ​​do que as métricas mais utilizadas (Pontuação WCSS e Silhouette).

No final, como acontece com muitos algoritmos de ciência de dados, queremos reduzir a variação dentro de cada cluster e maximizar a variação entre diferentes clusters. Portanto, temos clusters mais definidos e separáveis.

Aplicando K-Means em outro conjunto de dados

Vamos usar o que aprendemos em outro conjunto de dados. Desta vez, tentaremos encontrar grupos de vinhos semelhantes.

Observação: Você pode baixar o conjunto de dados SUA PARTICIPAÇÃO FAZ A DIFERENÇA.

Começamos importando pandas para ler o wine-clustering CSV (Valores Separados Por Virgula) arquivo em um Dataframe estrutura:

import pandas as pd

df = pd.read_csv('wine-clustering.csv')

Depois de carregá-lo, vamos dar uma olhada nos primeiros cinco registros de dados com o head() método:

df.head()

Isto resulta em:

	Alcohol 	Malic_Acid 	Ash 	Ash_Alcanity 	Magnesium 	Total_Phenols 	Flavanoids 	Nonflavanoid_Phenols 	Proanthocyanins 	Color_Intensity 	Hue 	OD280 	Proline
0 	14.23 		1.71 		2.43 	15.6 			127 		2.80 			3.06 		0.28 					2.29 				5.64 				1.04 	3.92 	1065
1 	13.20 		1.78 		2.14 	11.2 			100 		2.65 			2.76 		0.26 					1.28 				4.38 				1.05 	3.40 	1050
2 	13.16 		2.36 		2.67 	18.6 			101 		2.80 			3.24 		0.30 					2.81 				5.68 				1.03 	3.17 	1185
3 	14.37 		1.95 		2.50 	16.8 			113 		3.85 			3.49 		0.24 					2.18 				7.80 				0.86 	3.45 	1480
4 	13.24 		2.59 		2.87 	21.0 			118 		2.80 			2.69 		0.39 					1.82 				4.32 				1.04 	2.93 	735

Temos muitas medições de substâncias presentes nos vinhos. Aqui, também não precisaremos transformar colunas categóricas porque todas elas são numéricas. Agora, vamos dar uma olhada nas estatísticas descritivas com o describe() método:

df.describe().T 

A tabela de descrição:

 						count 	mean 		std 		min 	25% 	50% 	75% 		max
Alcohol 				178.0 	13.000618 	0.811827 	11.03 	12.3625 13.050 	13.6775 	14.83
Malic_Acid 				178.0 	2.336348 	1.117146 	0.74 	1.6025 	1.865 	3.0825 		5.80
Ash 					178.0 	2.366517 	0.274344 	1.36 	2.2100 	2.360 	2.5575 		3.23
Ash_Alcanity 			178.0 	19.494944 	3.339564 	10.60 	17.2000 19.500 	21.5000 	30.00
Magnesium 				178.0 	99.741573 	14.282484 	70.00 	88.0000 98.000 	107.0000 	162.00
Total_Phenols 			178.0 	2.295112 	0.625851 	0.98 	1.7425 	2.355 	2.8000 		3.88
Flavanoids 				178.0 	2.029270 	0.998859 	0.34 	1.2050 	2.135 	2.8750 		5.08
Nonflavanoid_Phenols 	178.0 	0.361854 	0.124453 	0.13 	0.2700 	0.340 	0.4375 		0.66
Proanthocyanins 		178.0 	1.590899 	0.572359 	0.41 	1.2500 	1.555 	1.9500 		3.58
Color_Intensity 		178.0 	5.058090 	2.318286 	1.28 	3.2200 	4.690 	6.2000 		13.00
Hue 					178.0 	0.957449 	0.228572 	0.48 	0.7825 	0.965 	1.1200 		1.71
OD280 					178.0 	2.611685 	0.709990 	1.27 	1.9375 	2.780 	3.1700 		4.00
Proline 				178.0 	746.893258 	314.907474 	278.00 	500.500 673.500 985.0000 	1680.00

Ao olhar para a tabela, fica claro que há alguns variabilidade nos dados – para algumas colunas, como Alchool há mais, e para outros, como Malic_Acid, menos. Agora podemos verificar se existem nullou NaN valores em nosso conjunto de dados:

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 13 columns):
 #   Column                Non-Null Count  Dtype  
---  ------                --------------  -----  
 0   Alcohol               178 non-null    float64
 1   Malic_Acid            178 non-null    float64
 2   Ash                   178 non-null    float64
 3   Ash_Alcanity          178 non-null    float64
 4   Magnesium             178 non-null    int64  
 5   Total_Phenols         178 non-null    float64
 6   Flavanoids            178 non-null    float64
 7   Nonflavanoid_Phenols  178 non-null    float64
 8   Proanthocyanins       178 non-null    float64
 9   Color_Intensity       178 non-null    float64
 10  Hue                   178 non-null    float64
 11  OD280                 178 non-null    float64
 12  Proline               178 non-null    int64  
dtypes: float64(11), int64(2)
memory usage: 18.2 KB

Não há necessidade de descartar ou inserir dados, considerando que não há valores vazios no conjunto de dados. Podemos usar um Seaborn pairplot() para ver a distribuição dos dados e verificar se o dataset forma pares de colunas que podem ser interessantes para clustering:

sns.pairplot(df)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Ao olhar para o pairplot, duas colunas parecem promissoras para fins de agrupamento – Alcohol e OD280 (que é um método para determinar a concentração de proteínas nos vinhos). Parece que existem 3 clusters distintos em parcelas combinando dois deles.

Existem outras colunas que parecem estar em correlação também. Mais notavelmente Alcohol e Total_Phenols e Alcohol e Flavanoids. Eles têm ótimas relações lineares que podem ser observadas no gráfico de pares.

Como nosso foco é agrupar com K-Means, vamos escolher um par de colunas, digamos Alcohol e OD280e teste o método de cotovelo para este conjunto de dados.

Observação: Ao usar mais colunas do conjunto de dados, será necessário plotar em 3 dimensões ou reduzir os dados para componentes principais (uso de PCA). Esta é uma abordagem válida e mais comum, apenas certifique-se de escolher os componentes principais com base no quanto eles explicam e lembre-se de que ao reduzir as dimensões dos dados, há alguma perda de informação – então o gráfico é um aproximação dos dados reais, não como eles realmente são.

Vamos plotar o gráfico de dispersão com essas duas colunas definidas como seu eixo para dar uma olhada nos pontos que queremos dividir em grupos:

sns.scatterplot(data=df, x='OD280', y='Alcohol')

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Agora podemos definir nossas colunas e usar o método do cotovelo para determinar o número de clusters. Também iniciaremos o algoritmo com kmeans++ apenas para ter certeza de que converge mais rapidamente:

values = df[['OD280', 'Alcohol']]

wcss_wine = [] 
for i in range(1, 11): 
    kmeans = KMeans(n_clusters = i, init = 'k-means++', random_state = 42)
    kmeans.fit(values) 
    wcss_wine.append(kmeans.inertia_)

Calculamos o WCSS, para que possamos plotar os resultados:

clusters_wine = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
plt.plot(clusters_wine, wcss_wine)
plt.axvline(3, linestyle='--', color='r')

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

De acordo com o método do cotovelo, devemos ter 3 clusters aqui. Para a etapa final, vamos agrupar nossos pontos em 3 clusters e plotar esses clusters identificados por cores:

kmeans_wine = KMeans(n_clusters=3, random_state=42)
kmeans_wine.fit(values)
sns.scatterplot(x = values['OD280'], y = values['Alcohol'], hue=kmeans_wine.labels_)

Guia definitivo para clustering K-Means com Scikit-Learn PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Podemos ver aglomerados 0, 1 e 2 no gráfico. Com base em nossa análise, grupo 0 tem vinhos com maior teor de proteína e menor teor alcoólico, grupo 1 tem vinhos com maior teor alcoólico e baixo teor de proteínas, e grupo 2 tem alta proteína e alto teor alcoólico em seus vinhos.

Este é um conjunto de dados muito interessante e eu encorajo você a ir mais longe na análise agrupando os dados após a normalização e PCA – também interpretando os resultados e encontrando novas conexões.

Conclusão

K-médias clustering é um algoritmo de aprendizado de máquina não supervisionado simples, mas muito eficaz, para clustering de dados. Ele agrupa os dados com base na distância euclidiana entre os pontos de dados. O algoritmo de agrupamento K-Means tem muitos usos para agrupar documentos de texto, imagens, vídeos e muito mais.

Carimbo de hora:

Mais de Abuso de pilha