Eu estudei sobre o agrupamento k-means , e uma coisa que não está clara é como você escolhe o valor de k. É apenas uma questão de tentativa e erro, ou há mais?
R
) aqui: stackoverflow.com/a/15376462/1036500
Eu estudei sobre o agrupamento k-means , e uma coisa que não está clara é como você escolhe o valor de k. É apenas uma questão de tentativa e erro, ou há mais?
R
) aqui: stackoverflow.com/a/15376462/1036500
Respostas:
Você pode maximizar o Critério de Informação Bayesiano (BIC):
BIC(C | X) = L(X | C) - (p / 2) * log n
onde L(X | C)
é a probabilidade de log do conjunto de dados de X
acordo com o modelo C
, p
é o número de parâmetros no modelo C
e n
o número de pontos no conjunto de dados. Veja "meios X: estendendo os meios K com estimativa eficiente do número de clusters" por Dan Pelleg e Andrew Moore no ICML 2000.
Outra abordagem é começar com um grande valor k
e continuar removendo os centróides (reduzindo k) até que não reduz mais o tamanho da descrição. Ver "Princípio MDL para quantização robusta de vetores" de Horst Bischof, Ales Leonardis e Alexander Selb em Pattern Analysis and Applications vol. 2, p. 59-72, 1999.
Finalmente, você pode começar com um cluster e continuar dividindo os clusters até que os pontos atribuídos a cada cluster tenham uma distribuição gaussiana. Em "Aprender a k em k -means" (PIN 2003), Greg Hamerly e Charles Elkan mostrar alguma evidência de que isso funciona melhor do que BIC, e que BIC não penalize a complexidade do modelo fortemente o suficiente.
Basicamente, você deseja encontrar um equilíbrio entre duas variáveis: o número de clusters ( k ) e a variação média dos clusters. Você deseja minimizar o primeiro enquanto também minimiza o último. Obviamente, à medida que o número de clusters aumenta, a variação média diminui (até o caso trivial de k = n e variação = 0).
Como sempre na análise de dados, não existe uma abordagem verdadeira que funcione melhor do que todas as outras em todos os casos. No final, você deve usar seu próprio julgamento. Para isso, ajuda a plotar o número de clusters em relação à variação média (que pressupõe que você já executou o algoritmo para vários valores de k ). Então você pode usar o número de clusters no joelho da curva.
Sim, você pode encontrar o melhor número de clusters usando o método Elbow, mas achei difícil encontrar o valor de clusters no gráfico do cotovelo usando o script. Você pode observar o gráfico do cotovelo e descobrir o ponto do cotovelo, mas foi muito trabalho encontrá-lo a partir do script.
Portanto, outra opção é usar o Silhouette Method para encontrá-lo. O resultado do Silhouette é totalmente compatível com o resultado do método Elbow em R.
Aqui está o que eu fiz.
#Dataset for Clustering
n = 150
g = 6
set.seed(g)
d <- data.frame(x = unlist(lapply(1:g, function(i) rnorm(n/g, runif(1)*i^2))),
y = unlist(lapply(1:g, function(i) rnorm(n/g, runif(1)*i^2))))
mydata<-d
#Plot 3X2 plots
attach(mtcars)
par(mfrow=c(3,2))
#Plot the original dataset
plot(mydata$x,mydata$y,main="Original Dataset")
#Scree plot to deterine the number of clusters
wss <- (nrow(mydata)-1)*sum(apply(mydata,2,var))
for (i in 2:15) {
wss[i] <- sum(kmeans(mydata,centers=i)$withinss)
}
plot(1:15, wss, type="b", xlab="Number of Clusters",ylab="Within groups sum of squares")
# Ward Hierarchical Clustering
d <- dist(mydata, method = "euclidean") # distance matrix
fit <- hclust(d, method="ward")
plot(fit) # display dendogram
groups <- cutree(fit, k=5) # cut tree into 5 clusters
# draw dendogram with red borders around the 5 clusters
rect.hclust(fit, k=5, border="red")
#Silhouette analysis for determining the number of clusters
library(fpc)
asw <- numeric(20)
for (k in 2:20)
asw[[k]] <- pam(mydata, k) $ silinfo $ avg.width
k.best <- which.max(asw)
cat("silhouette-optimal number of clusters:", k.best, "\n")
plot(pam(d, k.best))
# K-Means Cluster Analysis
fit <- kmeans(mydata,k.best)
mydata
# get cluster means
aggregate(mydata,by=list(fit$cluster),FUN=mean)
# append cluster assignment
mydata <- data.frame(mydata, clusterid=fit$cluster)
plot(mydata$x,mydata$y, col = fit$cluster, main="K-means Clustering results")
Espero que ajude!!
Pode ser alguém iniciante como eu procurando um exemplo de código. informações para silhouette_score estão disponíveis aqui.
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
range_n_clusters = [2, 3, 4] # clusters range you want to select
dataToFit = [[12,23],[112,46],[45,23]] # sample data
best_clusters = 0 # best cluster number which you will get
previous_silh_avg = 0.0
for n_clusters in range_n_clusters:
clusterer = KMeans(n_clusters=n_clusters)
cluster_labels = clusterer.fit_predict(dataToFit)
silhouette_avg = silhouette_score(dataToFit, cluster_labels)
if silhouette_avg > previous_silh_avg:
previous_silh_avg = silhouette_avg
best_clusters = n_clusters
# Final Kmeans for best_clusters
kmeans = KMeans(n_clusters=best_clusters, random_state=0).fit(dataToFit)
Existe algo chamado Regra de Polegar. Diz que o número de clusters pode ser calculado por
k = (n/2)^0.5
onde n é o número total de elementos da sua amostra. Você pode verificar a veracidade dessas informações no seguinte documento:
http://www.ijarcsms.com/docs/paper/volume1/issue6/V1I6-0015.pdf
Há também outro método chamado G-means, em que sua distribuição segue uma distribuição gaussiana ou distribuição normal. Consiste em aumentar k até que todos os seus grupos k sigam uma distribuição gaussiana. Requer muitas estatísticas, mas pode ser feito. Aqui está a fonte:
http://papers.nips.cc/paper/2526-learning-the-k-in-k-means.pdf
Eu espero que isso ajude!
Primeiro, crie uma árvore de abrangência mínima dos seus dados. A remoção das arestas mais caras do K-1 divide a árvore em clusters K,
para que você possa construir o MST uma vez, examinar espaçamentos / métricas de cluster para vários K e assumir o controle da curva.
Isso funciona apenas para Single-linkage_clustering , mas para isso é rápido e fácil. Além disso, os MSTs produzem bons visuais.
Veja, por exemplo, o gráfico MST no
software de visualização stats.stackexchange para cluster .
Estou surpreso que ninguém tenha mencionado este excelente artigo: http://www.ee.columbia.edu/~dpwe/papers/PhamDN05-kmeans.pdf
Depois de seguir várias outras sugestões, finalmente encontrei este artigo enquanto lia este blog: https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/
Depois disso, eu o implementei no Scala, uma implementação que, para meus casos de uso, fornece resultados realmente bons. Aqui está o código:
import breeze.linalg.DenseVector
import Kmeans.{Features, _}
import nak.cluster.{Kmeans => NakKmeans}
import scala.collection.immutable.IndexedSeq
import scala.collection.mutable.ListBuffer
/*
https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/
*/
class Kmeans(features: Features) {
def fkAlphaDispersionCentroids(k: Int, dispersionOfKMinus1: Double = 0d, alphaOfKMinus1: Double = 1d): (Double, Double, Double, Features) = {
if (1 == k || 0d == dispersionOfKMinus1) (1d, 1d, 1d, Vector.empty)
else {
val featureDimensions = features.headOption.map(_.size).getOrElse(1)
val (dispersion, centroids: Features) = new NakKmeans[DenseVector[Double]](features).run(k)
val alpha =
if (2 == k) 1d - 3d / (4d * featureDimensions)
else alphaOfKMinus1 + (1d - alphaOfKMinus1) / 6d
val fk = dispersion / (alpha * dispersionOfKMinus1)
(fk, alpha, dispersion, centroids)
}
}
def fks(maxK: Int = maxK): List[(Double, Double, Double, Features)] = {
val fadcs = ListBuffer[(Double, Double, Double, Features)](fkAlphaDispersionCentroids(1))
var k = 2
while (k <= maxK) {
val (fk, alpha, dispersion, features) = fadcs(k - 2)
fadcs += fkAlphaDispersionCentroids(k, dispersion, alpha)
k += 1
}
fadcs.toList
}
def detK: (Double, Features) = {
val vals = fks().minBy(_._1)
(vals._3, vals._4)
}
}
object Kmeans {
val maxK = 10
type Features = IndexedSeq[DenseVector[Double]]
}
Se você usa o MATLAB, qualquer versão desde 2013b, é possível usar a função evalclusters
para descobrir qual deve k
ser o melhor para um determinado conjunto de dados.
Esta função permite escolher entre três algoritmos de agrupamento - kmeans
, linkage
e gmdistribution
.
Ele também permite que você escolha entre critérios de avaliação 4 de agrupamento - CalinskiHarabasz
, DaviesBouldin
, gap
e silhouette
.
Se você não souber os números dos clusters k a fornecer como parâmetro para k-means, então existem quatro maneiras de encontrá-lo automaticamente:
Algortitmo G-significa: ele descobre o número de grupos automaticamente usando um teste estatístico para decidir se deve dividir um centro de K-médias em dois. Esse algoritmo adota uma abordagem hierárquica para detectar o número de clusters, com base em um teste estatístico para a hipótese de que um subconjunto de dados segue uma distribuição gaussiana (função contínua que aproxima a distribuição binomial exata de eventos) e, se não, divide o cluster . Ele começa com um pequeno número de centros, digamos, apenas um cluster (k = 1), então o algoritmo o divide em dois centros (k = 2) e divide cada um desses dois centros novamente (k = 4), tendo quatro centros em total. Se G-means não aceitar esses quatro centros, então a resposta é a etapa anterior: neste caso, dois centros (k = 2). Esse é o número de clusters nos quais o conjunto de dados será dividido. G-means é muito útil quando você não tem uma estimativa do número de clusters que receberá após o agrupamento de suas instâncias. Observe que uma escolha inconveniente para o parâmetro "k" pode gerar resultados incorretos. A versão paralela do g-means é chamadap-significa . Fontes G-significa: fonte 1 fonte 2 fonte 3
x-means : um novo algoritmo que pesquisa com eficiência o espaço das localizações dos clusters e o número de clusters para otimizar a medida do Critério de Informação Bayesiano (BIC) ou do Akaike Information Criterion (AIC). Esta versão do k-means encontra o número k e também acelera o k-means.
K-means on-line ou Streaming k-means: permite executar o k-means digitalizando todos os dados uma vez e encontra automaticamente o número ideal de k. O Spark o implementa.
Algoritmo MeanShift : é uma técnica de agrupamento não paramétrica que não requer conhecimento prévio do número de clusters e não restringe a forma dos clusters. O agrupamento por turnos médios visa descobrir "bolhas" em uma densidade suave de amostras. É um algoritmo baseado em centróide, que funciona atualizando os candidatos aos centróides como a média dos pontos em uma determinada região. Esses candidatos são então filtrados em um estágio de pós-processamento para eliminar quase duplicatas para formar o conjunto final de centróides. Fontes: source1 , source2 , source3
Usei a solução que encontrei aqui: http://efavdb.com/mean-shift/ e funcionou muito bem para mim:
import numpy as np
from sklearn.cluster import MeanShift, estimate_bandwidth
from sklearn.datasets.samples_generator import make_blobs
import matplotlib.pyplot as plt
from itertools import cycle
from PIL import Image
#%% Generate sample data
centers = [[1, 1], [-.75, -1], [1, -1], [-3, 2]]
X, _ = make_blobs(n_samples=10000, centers=centers, cluster_std=0.6)
#%% Compute clustering with MeanShift
# The bandwidth can be automatically estimated
bandwidth = estimate_bandwidth(X, quantile=.1,
n_samples=500)
ms = MeanShift(bandwidth=bandwidth, bin_seeding=True)
ms.fit(X)
labels = ms.labels_
cluster_centers = ms.cluster_centers_
n_clusters_ = labels.max()+1
#%% Plot result
plt.figure(1)
plt.clf()
colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
my_members = labels == k
cluster_center = cluster_centers[k]
plt.plot(X[my_members, 0], X[my_members, 1], col + '.')
plt.plot(cluster_center[0], cluster_center[1],
'o', markerfacecolor=col,
markeredgecolor='k', markersize=14)
plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()
Minha idéia é usar o coeficiente de silhueta para encontrar o número ideal de cluster (K). Detalhes explicação está aqui .
Supondo que você tenha uma matriz de dados chamada DATA
, é possível executar o particionamento em torno dos medoids com estimativa do número de clusters (por análise de silhueta) como este:
library(fpc)
maxk <- 20 # arbitrary here, you can set this to whatever you like
estimatedK <- pamk(dist(DATA), krange=1:maxk)$nc
Uma resposta possível é usar o algoritmo meta-heurístico, como o algoritmo genético, para encontrar k. Isso é simples. você pode usar K aleatório (em algum intervalo) e avaliar a função de ajuste do algoritmo genético com algumas medidas como Silhouette And Find Best K base on fit function.
km=[]
for i in range(num_data.shape[1]):
kmeans = KMeans(n_clusters=ncluster[i])#we take number of cluster bandwidth theory
ndata=num_data[[i]].dropna()
ndata['labels']=kmeans.fit_predict(ndata.values)
cluster=ndata
co=cluster.groupby(['labels'])[cluster.columns[0]].count()#count for frequency
me=cluster.groupby(['labels'])[cluster.columns[0]].median()#median
ma=cluster.groupby(['labels'])[cluster.columns[0]].max()#Maximum
mi=cluster.groupby(['labels'])[cluster.columns[0]].min()#Minimum
stat=pd.concat([mi,ma,me,co],axis=1)#Add all column
stat['variable']=stat.columns[1]#Column name change
stat.columns=['Minimum','Maximum','Median','count','variable']
l=[]
for j in range(ncluster[i]):
n=[mi.loc[j],ma.loc[j]]
l.append(n)
stat['Class']=l
stat=stat.sort(['Minimum'])
stat=stat[['variable','Class','Minimum','Maximum','Median','count']]
if missing_num.iloc[i]>0:
stat.loc[ncluster[i]]=0
if stat.iloc[ncluster[i],5]==0:
stat.iloc[ncluster[i],5]=missing_num.iloc[i]
stat.iloc[ncluster[i],0]=stat.iloc[0,0]
stat['Percentage']=(stat[[5]])*100/count_row#Freq PERCENTAGE
stat['Cumulative Percentage']=stat['Percentage'].cumsum()
km.append(stat)
cluster=pd.concat(km,axis=0)## see documentation for more info
cluster=cluster.round({'Minimum': 2, 'Maximum': 2,'Median':2,'Percentage':2,'Cumulative Percentage':2})
Outra abordagem é usar o SOP (Self Organizing Maps) para encontrar o número ideal de clusters. O SOM (Mapa Auto-Organizável) é uma metodologia de rede neural não supervisionada, que precisa apenas da entrada usada para agrupar na solução de problemas. Essa abordagem foi usada em um artigo sobre segmentação de clientes.
A referência do artigo é
Abdellah Amine et al., Modelo de segmentação de clientes em comércio eletrônico usando técnicas de cluster e modelo LRFM: o caso de lojas on-line em Marrocos, Academia Mundial de Ciências, Engenharia e Tecnologia Revista Internacional de Engenharia de Computação e Informação Vol: 9, No: 8 , 2015, 1999 - 2010
Oi, vou simplificar e esclarecer, gosto de determinar os clusters usando a biblioteca 'NbClust'.
Agora, como usar a função 'NbClust' para determinar o número certo de clusters: Você pode verificar o projeto real no Github com dados e clusters reais - A extensão desse algoritmo 'kmeans' também foi executada usando o número certo de 'centros'.
Link do projeto Github: https://github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook
Você pode escolher o número de clusters inspecionando visualmente seus pontos de dados, mas em breve perceberá que há muita ambiguidade nesse processo para todos, exceto os conjuntos de dados mais simples. Isso nem sempre é ruim, porque você está aprendendo sem supervisão e há alguma subjetividade inerente no processo de rotulagem. Aqui, ter experiência anterior com esse problema específico ou algo semelhante o ajudará a escolher o valor certo.
Se você quiser alguma dica sobre o número de clusters que deve usar, pode aplicar o método Elbow:
Primeiro, calcule a soma do erro quadrático (SSE) para alguns valores de k (por exemplo 2, 4, 6, 8, etc.). O SSE é definido como a soma da distância ao quadrado entre cada membro do cluster e seu centróide. Matematicamente:
SSE = ∑Ki = 1∑x∈cidista (x, ci) 2
Se você plotar k no SSE, verá que o erro diminui à medida que k aumenta; isso ocorre porque quando o número de clusters aumenta, eles devem ser menores, portanto a distorção também é menor. A idéia do método do cotovelo é escolher o k no qual o SSE diminui abruptamente. Isso produz um "efeito cotovelo" no gráfico, como você pode ver na figura a seguir:
Nesse caso, k = 6 é o valor que o método Elbow selecionou. Leve em consideração que o método Elbow é uma heurística e, como tal, pode ou não funcionar bem no seu caso particular. Às vezes, há mais de um cotovelo, ou nenhum cotovelo. Nessas situações, você geralmente calcula o melhor k avaliando o desempenho de k-means no contexto do problema específico de cluster que você está tentando resolver.
Eu trabalhei em um pacote Python kneed (algoritmo Kneedle). Ele encontra o número do cluster dinamicamente como o ponto em que a curva começa a achatar. Dado um conjunto de valores x e y, o kneed retornará o ponto do joelho da função. O ponto do joelho é o ponto de curvatura máxima. Aqui está o código de exemplo.
y = [7.342,1301373073857, 6.881,7109460930769, 6.531,1657905495022,
6.356,2255554679778, 6.209,8382535595829, 6.094,9052166741121, 5.980,0191582610196, 5.880,1869867848218, 5.779,8957906367368, 5.691,1879324562778, 5.617,5153566271356, 5.532,2613232619951, 5.467,352265375117, 5.395,4493783888756, 5.345,3459908298091, 5.290,6769823693812, 5.243,5271656371888, 5.207,2501206569532, 5.164,9617535255456]
x = intervalo (1, len (y) +1)
da importação kneed KneeLocator kn = KneeLocator (x, y, curva = 'convexa', direção = 'decrescente')
print (kn.knee)