Quantos grupos?
K é a quantidade de clusters que desejamos formar. O algoritmo não “descobre K sozinho” na versão clássica: esse valor precisa ser escolhido ou avaliado externamente.
Aprendizagem não supervisionada · laboratório visual
Entenda o que o algoritmo procura, como ele mede distância, por que os centróides se movem, o que significa convergir e como avaliar se os grupos encontrados realmente fazem sentido.
Antes do algoritmo
Ele recebe apenas os atributos X. Não existem classes corretas previamente informadas. O objetivo é criar K grupos compactos em que os pontos fiquem, tanto quanto possível, próximos do centro do próprio grupo.
K é a quantidade de clusters que desejamos formar. O algoritmo não “descobre K sozinho” na versão clássica: esse valor precisa ser escolhido ou avaliado externamente.
É o vetor médio dos pontos de um cluster. Ele representa o “centro matemático” do grupo e não precisa coincidir com um ponto real do conjunto de dados.
O K-Means procura reduzir a soma das distâncias quadráticas de cada ponto ao centróide do seu cluster. Essa quantidade é chamada de inércia, SSE ou WCSS.
A dúvida mais importante
Porque o primeiro cluster não é definitivo. Ele foi criado usando centróides que ainda eram apenas palpites iniciais. O K-Means alterna entre duas perguntas diferentes.
Primeiro, os centróides ficam parados. Cada ponto escolhe o centróide mais próximo. Isso produz clusters provisórios.
Enquanto os centróides estão fixos, essa escolha é a melhor atribuição possível para cada ponto.
Agora seguramos temporariamente os membros de cada cluster e calculamos a média deles. A média é a posição que minimiza a soma das distâncias quadráticas para aquele grupo atual.
Ao mover μⱼ, porém, mudamos as distâncias. Por isso, a atribuição feita no passo anterior pode deixar de ser a melhor.
Considere os pontos 0, 4, 5, 6 e 20 em uma linha, com dois centróides iniciais em 0 e 6. Veja que um ponto realmente troca de grupo depois que o centróide se move.
μ₁=0 recebe {0}
μ₂=6 recebe {4,5,6,20}
Esses grupos surgiram apenas porque 0 e 6 eram os centros atuais.
novo μ₁=0
novo μ₂=(4+5+6+20)/4=8,75
Os centros agora representam melhor os grupos provisórios.
As distâncias são calculadas de novo usando 0 e 8,75.
O ponto 4 troca de cluster: antes estava a apenas 2 unidades de μ₂=6 e a 4 de μ₁=0; agora está a 4 de μ₁=0 e a 4,75 de μ₂=8,75. Depois disso, as médias serão recalculadas outra vez.
Se você quiser guardar o algoritmo em uma única ideia, pense exatamente desta forma:
No desenho, parece que o centróide anda suavemente, mas matematicamente o que acontece é apenas uma substituição.
Se o centróide estava em (8, 7) e a nova média calculada deu (5, 4), o algoritmo simplesmente passa a usar (5, 4) na próxima iteração.
Depois disso, todos os pontos medem novamente sua distância aos novos centróides. É por isso que um ponto pode trocar de grupo.
Experimente antes de decorar
Avance uma fase por vez. A lateral mostra a conta que acabou de ser executada; a inércia permite observar se a solução está melhorando.
A matemática por trás da animação
As fórmulas abaixo correspondem diretamente às fases do laboratório. O objetivo é associar cada símbolo a uma ação visual.
Cada observação xᵢ é um vetor com d atributos. Em um gráfico 2D, por exemplo, xᵢ = (x, y).
nnúmero de observações.dnúmero de atributos (dimensões).xᵢi-ésima observação do conjunto.A distância Euclidiana mede o comprimento da linha reta entre o ponto xᵢ e o centróide μⱼ. O cluster escolhido será o do menor valor.
μⱼcentróide do cluster j.míndice do atributo comparado.d(·)distância entre dois vetores.arg min significa: “qual índice j produz o menor valor?”. Portanto, cᵢ guarda o número do centróide mais próximo de xᵢ.
cᵢcluster atribuído ao ponto xᵢ.arg minposição/índice que minimiza a expressão.O novo centróide é simplesmente a média de cada atributo dos pontos atualmente pertencentes ao cluster Cⱼ.
Cⱼconjunto de pontos do cluster j.|Cⱼ|quantidade de pontos no cluster j.Considere o ponto x = (2, 3) e dois centróides: μ₁ = (1, 1) e μ₂ = (5, 4).
Conclusão: como 2,24 < 3,16, esse ponto é atribuído ao cluster 1. A próxima fase recalculará μ₁ usando a média de todos os pontos que também foram enviados para esse cluster.
Função objetivo
A forma clássica do K-Means minimiza a soma das distâncias Euclidianas quadráticas entre cada ponto e o centróide do seu próprio cluster.
Quanto menor J, mais compactos são os grupos para aquele valor de K. Durante as iterações de Lloyd, a função objetivo não aumenta: cada fase de atribuição e atualização procura manter ou reduzir esse custo.
Mas cuidado: menor inércia não significa automaticamente “melhor explicação do mundo”. A inércia sempre tende a cair quando aumentamos K.
Para um conjunto de pontos fixo, o valor que minimiza a soma dos erros quadráticos é a média. Por isso, depois que os membros de um cluster estão definidos, mover μ para a média é a melhor atualização possível para esse cluster dentro desse critério.
Essa ligação entre erro quadrático e média é a razão matemática do nome K-Means.
Escolha do K
Não existe um único teste universal. Duas ferramentas didáticas comuns são o método do cotovelo e o coeficiente de silhouette. Use-os junto com conhecimento do problema.
Execute o K-Means para vários valores de K e observe a queda da inércia. Procura-se um ponto a partir do qual aumentar K traz ganhos proporcionalmente menores.
O gráfico acima é recalculado para o conjunto de dados do laboratório.
a(i) mede a distância média do ponto aos membros do próprio cluster; b(i) mede a menor distância média desse ponto a outro cluster. O resultado fica entre −1 e 1.
Próximo de +1: ponto bem separado.
Próximo de 0: fronteira ambígua.
Negativo: possível atribuição ruim.
Pré-processamento
Como K-Means depende de distância, um atributo numericamente muito maior pode dominar os demais. Por isso, escalonamento e escolha de atributos fazem parte do problema.
Imagine idade = 20–70 e renda = 1.500–30.000. A diferença de renda pode ser centenas de vezes maior e dominar a distância Euclidiana, mesmo quando isso não deveria representar a importância real do atributo.
A padronização transforma os atributos para escalas comparáveis. Após isso, “um desvio padrão de diferença” em idade e em renda passa a ter magnitude numérica semelhante.
Inicialização e convergência
O algoritmo clássico converge para um mínimo local. Por isso, inicializações diferentes podem levar a soluções finais diferentes.
Seleciona posições/pontos iniciais sem uma estratégia de espalhamento. Se dois centróides começam muito próximos, o algoritmo pode gastar mais iterações ou terminar em uma solução ruim.
Escolhe novos centros favorecendo pontos distantes dos centros já escolhidos. A ideia é começar com sementes mais bem distribuídas e reduzir a chance de uma inicialização ruim.
Na prática, é comum executar o algoritmo com sementes diferentes e manter a solução de menor inércia. Bibliotecas modernas automatizam esse procedimento por meio de parâmetros como n_init.
Quando ele falha
Troque o conjunto do laboratório para grupos alongados ou luas. Você verá que proximidade a um centróide favorece regiões aproximadamente convexas e isotrópicas.
Do conceito para o código
A implementação abaixo usa apenas listas, laços, soma e divisão. Os centróides iniciais são passados explicitamente para que fique visível que eles são apenas o ponto de partida do algoritmo.
Leitura correta do laço: primeiro o algoritmo classifica os pontos com os centróides atuais; depois recalcula os centróides como médias; em seguida volta e classifica tudo novamente com os novos centros. Esse ciclo é o coração do K-Means.
# Nenhuma biblioteca é necessária.
def distancia_quadrada(ponto, centroide):
soma = 0.0
for i in range(len(ponto)):
diferenca = ponto[i] - centroide[i]
soma = soma + diferenca * diferenca
return soma
def centroide_do_cluster(pontos_do_cluster):
quantidade = len(pontos_do_cluster)
dimensoes = len(pontos_do_cluster[0])
novo_centroide = []
for dimensao in range(dimensoes):
soma = 0.0
for ponto in pontos_do_cluster:
soma = soma + ponto[dimensao]
media = soma / quantidade
novo_centroide.append(media)
return novo_centroide
def atribuir_pontos(dados, centroides):
# Guarda o índice do centróide escolhido para cada ponto.
rotulos = []
for ponto in dados:
melhor_cluster = 0
menor_distancia = distancia_quadrada(ponto, centroides[0])
for j in range(1, len(centroides)):
distancia = distancia_quadrada(ponto, centroides[j])
if distancia < menor_distancia:
menor_distancia = distancia
melhor_cluster = j
rotulos.append(melhor_cluster)
return rotulos
def atualizar_centroides(dados, rotulos, centroides_atuais):
k = len(centroides_atuais)
novos_centroides = []
for j in range(k):
pontos_do_cluster = []
# Separa os pontos que atualmente pertencem ao cluster j.
for i in range(len(dados)):
if rotulos[i] == j:
pontos_do_cluster.append(dados[i])
# Se o cluster ficou vazio, mantém o centróide anterior.
if len(pontos_do_cluster) == 0:
novos_centroides.append(centroides_atuais[j][:])
else:
novos_centroides.append(
centroide_do_cluster(pontos_do_cluster)
)
return novos_centroides
def centroides_iguais(a, b, tolerancia=0.000001):
for j in range(len(a)):
for d in range(len(a[j])):
if abs(a[j][d] - b[j][d]) > tolerancia:
return False
return True
def calcular_inercia(dados, rotulos, centroides):
total = 0.0
for i in range(len(dados)):
cluster = rotulos[i]
total = total + distancia_quadrada(
dados[i],
centroides[cluster]
)
return total
def kmeans(dados, centroides_iniciais, max_iteracoes=100):
# Fazemos uma cópia para não alterar a lista recebida.
centroides = []
for centroide in centroides_iniciais:
centroides.append(centroide[:])
for iteracao in range(max_iteracoes):
print("\nITERACAO", iteracao + 1)
print("Centroides no inicio:", centroides)
# PASSO A ---------------------------------------------
# Com os centroides PARADOS, cada ponto escolhe
# o centroide mais proximo.
rotulos = atribuir_pontos(dados, centroides)
print("Rotulos:", rotulos)
# PASSO B ---------------------------------------------
# Com os membros dos clusters PARADOS, calculamos
# a media de cada grupo e movemos seus centroides.
novos_centroides = atualizar_centroides(
dados,
rotulos,
centroides
)
print("Novos centroides:", novos_centroides)
# Se a media nao mudou mais, chegamos a um ponto fixo.
if centroides_iguais(centroides, novos_centroides):
centroides = novos_centroides
print("Convergiu.")
break
# IMPORTANTE:
# ao mover os centroides, as distancias mudaram.
# Portanto, na proxima volta precisamos atribuir
# TODOS OS PONTOS NOVAMENTE.
centroides = novos_centroides
# Recalcula os rotulos uma ultima vez usando os centros finais.
rotulos = atribuir_pontos(dados, centroides)
inercia = calcular_inercia(dados, rotulos, centroides)
return rotulos, centroides, inercia
# -----------------------------------------------------------
# EXEMPLO 1D — o mesmo da explicação acima
# Cada ponto continua sendo um vetor; aqui ele tem 1 dimensão.
# -----------------------------------------------------------
dados = [
[0.0],
[4.0],
[5.0],
[6.0],
[20.0]
]
# Não são os centros "corretos".
# São somente dois palpites iniciais.
centroides_iniciais = [
[0.0],
[6.0]
]
rotulos, centroides, inercia = kmeans(
dados,
centroides_iniciais
)
print("\nRESULTADO FINAL")
print("Rotulos:", rotulos)
print("Centroides:", centroides)
print("Inercia:", inercia)
Na função atualizar_centroides(). Ela seleciona os membros que naquela iteração receberam o mesmo rótulo e chama centroide_do_cluster(), que calcula manualmente a média de cada dimensão.
Na próxima chamada de atribuir_pontos(). Como os centróides acabaram de mudar de posição, todas as distâncias são calculadas novamente. Um ponto pode permanecer no grupo ou trocar para outro.
Resumo para revisão
Defina quantos grupos serão procurados.
Posicione K centróides, preferencialmente com uma estratégia como k-means++.
Cada ponto vai para o centróide mais próximo.
Substitua cada centróide pela média do seu cluster.
Alterne atribuição e atualização enquanto houver mudança relevante.
Analise inércia, silhouette, estabilidade e, principalmente, significado para o domínio.
Fontes e aprofundamento
A página combina a formulação histórica do K-Means, a interpretação do algoritmo de Lloyd, a inicialização k-means++ e documentação contemporânea de bibliotecas e cursos de Machine Learning.
INTERPRETANDO OS CLUSTERS
Depois que o K-Means termina, ele não devolve nomes como “VIP”, “econômico” ou “caçador de ofertas”. Ele devolve grupos e seus respectivos centróides. A interpretação desses grupos é feita analisando os valores médios de cada variável.
Geometricamente, o K-Means posiciona um centróide no centro matemático de cada cluster. Se sua base possui 10 variáveis, cada centróide também terá 10 valores.
Imagine que cada cliente seja representado por um vetor com 10 características:
Depois da convergência, um centróide poderia ter a seguinte forma:
Esses números representam a média de cada característica dos clientes que pertencem ao Cluster 1.
Portanto, se existirem 3 clusters, teremos 3 vetores de centróides. Comparar esses vetores é uma das maneiras mais importantes de descobrir o que diferencia cada grupo.
Um valor isolado normalmente diz pouco. Saber que um cluster possui frequência média de compra igual a 15, por exemplo, só é realmente útil quando comparamos esse valor com os demais clusters ou com a média geral da base.
Considere a variável Frequência de Compra:
O valor do Cluster 2 é muito maior que o dos outros grupos.
Isso significa que comprar com muita frequência é uma característica marcante daquele cluster.
Outra estratégia é comparar o centróide de cada cluster com a média de toda a base.
Quanto maior essa diferença, positiva ou negativa, mais aquela variável ajuda a definir a identidade do grupo.
Em dados padronizados, essa comparação também pode ser interpretada de maneira semelhante a um Z-Score.
Imagine uma base de clientes com 10 variáveis relacionadas ao comportamento de compra. Depois de executar o K-Means, analisamos os valores dos centróides.
| Variável | Média global | Cluster 1 | Cluster 2 | Cluster 3 |
|---|---|---|---|---|
| Gasto mensal | R$ 150 |
R$ 450 Muito alto |
R$ 50 Baixo |
R$ 120 Próximo da média |
| Idade | 35 anos |
48 anos Acima da média |
22 anos Abaixo da média |
36 anos Próximo da média |
| Uso de cupom | 20% |
5% Muito baixo |
80% Muito alto |
15% Próximo da média |
| Outras 7 variáveis | ... | ... | ... | ... |
DA MATEMÁTICA PARA A INTERPRETAÇÃO
Os nomes dos grupos não são produzidos pelo K-Means. Eles são uma interpretação humana construída a partir das características que mais diferenciam cada centróide.
O Cluster 1 possui gasto muito acima da média, idade mais elevada e uso muito baixo de cupons.
Uma interpretação possível é a de clientes de maior valor, menos dependentes de promoções.
O Cluster 2 apresenta clientes mais jovens, gasto relativamente baixo e uso extremamente alto de cupons.
O desconto aparece como uma das características mais marcantes desse grupo.
O Cluster 3 permanece próximo da média global em grande parte das variáveis analisadas.
Portanto, ele representa um comportamento mais próximo do perfil médio da base.
Com 2 atributos, conseguimos visualizar os clusters diretamente em um gráfico. Com 10, 20 ou 100 atributos, essa visualização deixa de ser possível.
Uma estratégia comum é utilizar técnicas de redução de dimensionalidade, como o PCA — Principal Component Analysis, para representar parte dessa estrutura em duas ou três dimensões.
O PCA não substitui a análise dos centróides, mas pode ajudar a visualizar a separação entre os grupos e entender quais combinações de variáveis explicam grande parte da variação dos dados.