Ho studiato il clustering di k-mean e una cosa che non è chiara è come si sceglie il valore di k. È solo una questione di tentativi ed errori, o c'è dell'altro?
R
) qui: stackoverflow.com/a/15376462/1036500
Ho studiato il clustering di k-mean e una cosa che non è chiara è come si sceglie il valore di k. È solo una questione di tentativi ed errori, o c'è dell'altro?
R
) qui: stackoverflow.com/a/15376462/1036500
Risposte:
È possibile massimizzare il criterio di informazione bayesiana (BIC):
BIC(C | X) = L(X | C) - (p / 2) * log n
dove L(X | C)
è la probabilità di log del set di dati in X
base al modello C
, p
è il numero di parametri nel modello C
ed n
è il numero di punti nel set di dati. Vedi "X-significa: estendere i mezzi K con una stima efficiente del numero di cluster" di Dan Pelleg e Andrew Moore in ICML 2000.
Un altro approccio è iniziare con un valore elevato per k
e continuare a rimuovere i centroidi (riducendo k) fino a quando non riduce più la lunghezza della descrizione. Vedi "Principio MDL per una solida quantizzazione vettoriale" di Horst Bischof, Ales Leonardis e Alexander Selb in Pattern Analysis and Applications vol. 2, p. 59-72, 1999.
Infine, puoi iniziare con un cluster, quindi continuare a dividere i cluster fino a quando i punti assegnati a ciascun cluster non hanno una distribuzione gaussiana. In "Imparare i k in k -means" (NIPS 2003), Greg Hamerly e Charles Elkan mostrano alcune prove che questo funziona meglio di BIC e che BIC non penalizza abbastanza fortemente la complessità del modello.
Fondamentalmente, si desidera trovare un equilibrio tra due variabili: il numero di cluster ( k ) e la varianza media dei cluster. Vuoi ridurre al minimo il primo riducendo al minimo anche il secondo. Naturalmente, all'aumentare del numero di cluster, la varianza media diminuisce (fino al caso banale di k = n e varianza = 0).
Come sempre nell'analisi dei dati, non esiste un vero approccio che funzioni meglio di tutti gli altri in tutti i casi. Alla fine, devi usare il tuo miglior giudizio. Per questo, aiuta a tracciare il numero di cluster rispetto alla varianza media (il che presuppone che tu abbia già eseguito l'algoritmo per diversi valori di k ). Quindi è possibile utilizzare il numero di cluster al ginocchio della curva.
Sì, puoi trovare il miglior numero di cluster usando il metodo Elbow, ma ho trovato problematico trovare il valore dei cluster dal grafico del gomito usando lo script. Puoi osservare il grafico del gomito e trovare tu stesso il punto del gomito, ma è stato molto lavoro trovarlo dalla sceneggiatura.
Quindi un'altra opzione è quella di utilizzare il metodo Silhouette per trovarlo. Il risultato di Silhouette è completamente conforme al risultato del metodo Elbow in R.
Ecco cosa ho fatto.
#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")
Spero che sia d'aiuto!!
Potrebbe essere un principiante come me in cerca di un esempio di codice. le informazioni per silhouette_score sono disponibili qui.
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)
C'è qualcosa chiamato Regola del pollice. Dice che il numero di cluster può essere calcolato da
k = (n/2)^0.5
dove n è il numero totale di elementi dal tuo campione. Puoi verificare la veridicità di queste informazioni sul seguente documento:
http://www.ijarcsms.com/docs/paper/volume1/issue6/V1I6-0015.pdf
C'è anche un altro metodo chiamato G-medie, in cui la tua distribuzione segue una distribuzione gaussiana o una distribuzione normale. Consiste nell'aumentare k fino a quando tutti i tuoi gruppi k seguono una distribuzione gaussiana. Richiede molte statistiche ma può essere fatto. Ecco la fonte:
http://papers.nips.cc/paper/2526-learning-the-k-in-k-means.pdf
Spero che aiuti!
Innanzitutto crea un albero di spanning minimo dei tuoi dati. La rimozione dei bordi più costosi di K-1 divide l'albero in cluster K, in
modo da poter costruire l'MST una volta, osservare le spaziature / metriche del cluster per vari K e prendere il ginocchio della curva.
Funziona solo con Single-linkage_clustering , ma per questo è semplice e veloce. Inoltre, gli MST creano una buona visuale.
Vedere ad esempio il diagramma MST nel
software di visualizzazione stats.stackexchange per il clustering .
Sono sorpreso che nessuno abbia menzionato questo eccellente articolo: http://www.ee.columbia.edu/~dpwe/papers/PhamDN05-kmeans.pdf
Dopo aver seguito diversi altri suggerimenti, mi sono finalmente imbattuto in questo articolo mentre leggevo questo blog: https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/
Dopo di che l'ho implementato in Scala, un'implementazione che per i miei casi d'uso fornisce risultati davvero buoni. Ecco il codice:
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 si utilizza MATLAB, qualsiasi versione a partire dal 2013b, è possibile utilizzare la funzione evalclusters
per scoprire quale dovrebbe k
essere ottimale per un determinato set di dati.
Questa funzione consente di scegliere tra 3 algoritmi di clustering - kmeans
, linkage
e gmdistribution
.
Essa consente inoltre di scegliere tra i criteri di valutazione 4 raggruppamento - CalinskiHarabasz
, DaviesBouldin
, gap
e silhouette
.
Se non conosci i numeri dei cluster k da fornire come parametro a k-significa quindi ci sono quattro modi per trovarlo automaticamente:
Algortitmo G-significa: scopre automaticamente il numero di cluster usando un test statistico per decidere se dividere un centro k-mean in due. Questo algoritmo adotta un approccio gerarchico per rilevare il numero di cluster, basato su un test statistico per l'ipotesi che un sottoinsieme di dati segua una distribuzione gaussiana (funzione continua che approssima l'esatta distribuzione binomiale degli eventi) e, in caso contrario, divide il cluster . Inizia con un piccolo numero di centri, ad esempio un solo cluster (k = 1), quindi l'algoritmo lo divide in due centri (k = 2) e divide nuovamente ciascuno di questi due centri (k = 4), con quattro centri in totale. Se G-mean non accetta questi quattro centri, la risposta è il passaggio precedente: due centri in questo caso (k = 2). Questo è il numero di cluster in cui verrà diviso il set di dati. G-mean è molto utile quando non hai una stima del numero di cluster che otterrai dopo aver raggruppato le tue istanze. Si noti che una scelta scomoda per il parametro "k" potrebbe dare risultati errati. Viene chiamata la versione parallela di g-meanp-significa . Sorgenti dei mezzi G: fonte 1 fonte 2 fonte 3
x-significa : un nuovo algoritmo che ricerca in modo efficiente lo spazio delle posizioni dei cluster e il numero di cluster per ottimizzare il criterio Bayesian Information Criterion (BIC) o Akaike Information Criterion (AIC). Questa versione di k-mean trova il numero k e accelera anche k-mean.
K-medie online o Streaming k-medie: consente di eseguire k-medie scansionando tutti i dati una volta e trova automaticamente il numero ottimale di k. Spark lo implementa.
Algoritmo MeanShift : è una tecnica di clustering non parametrico che non richiede una conoscenza preliminare del numero di cluster e non limita la forma dei cluster. Il clustering a spostamento medio mira a scoprire "blob" in una densità uniforme di campioni. È un algoritmo basato su centroidi, che funziona aggiornando i candidati per i centroidi in modo che siano la media dei punti all'interno di una data regione. Questi candidati vengono quindi filtrati in una fase di post-elaborazione per eliminare i quasi duplicati per formare il set finale di centroidi. Fonti: fonte1 , fonte2 , fonte3
Ho usato la soluzione che ho trovato qui: http://efavdb.com/mean-shift/ e ha funzionato molto bene per me:
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()
La mia idea è di utilizzare Silhouette Coefficient per trovare il numero di cluster ottimale (K). La spiegazione dei dettagli è qui .
Supponendo di avere una matrice di dati chiamati DATA
, è possibile eseguire il partizionamento attorno ai medoidi con una stima del numero di cluster (mediante analisi di silhouette) in questo modo:
library(fpc)
maxk <- 20 # arbitrary here, you can set this to whatever you like
estimatedK <- pamk(dist(DATA), krange=1:maxk)$nc
Una possibile risposta è usare l'algoritmo meta-euristico come l'algoritmo genetico per trovare k. È semplice. puoi usare K casuale (in un certo intervallo) e valutare la funzione di adattamento dell'algoritmo genetico con alcune misurazioni come Silhouette e Trova la migliore base K sulla funzione di adattamento.
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})
Un altro approccio consiste nell'utilizzare le mappe auto-organizzate (SOP) per trovare il numero ottimale di cluster. La SOM (Self-Organizing Map) è una metodologia di rete neurale non supervisionata, che richiede solo l'input utilizzato per il clustering per la risoluzione dei problemi. Questo approccio è stato utilizzato in un documento sulla segmentazione dei clienti.
Il riferimento del documento è
Abdellah Amine et al., Modello di segmentazione della clientela nell'e-commerce utilizzando tecniche di clustering e modello LRFM: il caso dei negozi online in Marocco, Accademia mondiale delle scienze, ingegneria e tecnologia International Journal of Computer and Information Engineering Vol: 9, No: 8 , 2015, 1999-2010
Ciao, lo spiegherò in modo semplice e diretto, mi piace determinare i cluster usando la libreria "NbClust".
Ora, come usare la funzione 'NbClust' per determinare il giusto numero di cluster: puoi controllare il progetto reale in Github con dati e cluster effettivi - L'estensione a questo algoritmo 'kmeans' è stata eseguita anche usando il giusto numero di 'centri'.
Link al progetto Github: https://github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook
Puoi scegliere il numero di cluster ispezionando visivamente i tuoi punti dati, ma ti accorgerai presto che c'è molta ambiguità in questo processo per tutti tranne che per i set di dati più semplici. Questo non è sempre negativo, perché stai imparando senza supervisione e c'è una soggettività intrinseca nel processo di etichettatura. Qui, avere un'esperienza precedente con quel particolare problema o qualcosa di simile ti aiuterà a scegliere il giusto valore.
Se vuoi un suggerimento sul numero di cluster che dovresti usare, puoi applicare il metodo Elbow:
Prima di tutto, calcola la somma dell'errore al quadrato (SSE) per alcuni valori di k (ad esempio 2, 4, 6, 8, ecc.). Il SSE è definito come la somma della distanza quadrata tra ciascun membro del cluster e il suo centroide. Matematicamente:
SSE = ΣKi = 1Σx∈cidist (x, CI) 2
Se tracciate k contro SSE, vedrete che l'errore diminuisce man mano che k diventa più grande; questo perché quando il numero di cluster aumenta, dovrebbero essere più piccoli, quindi anche la distorsione è minore. L'idea del metodo del gomito è quella di scegliere la k in cui l'SSE diminuisce bruscamente. Questo produce un "effetto gomito" nel grafico, come puoi vedere nella figura seguente:
In questo caso, k = 6 è il valore selezionato dal metodo Elbow. Tieni presente che il metodo Elbow è euristico e, in quanto tale, può o meno funzionare bene nel tuo caso particolare. A volte, ci sono più di un gomito o nessun gomito. In quelle situazioni di solito si finisce per calcolare il miglior k valutando il rendimento di k-mean nel contesto del particolare problema di cluster che si sta tentando di risolvere.
Ho lavorato su un pacchetto Python in ginocchio (algoritmo Kneedle). Trova dinamicamente il numero di cluster come il punto in cui la curva inizia ad appiattirsi .. Dato un insieme di valori xey, il ginocchio restituirà il punto del ginocchio della funzione. La punta del ginocchio è il punto di massima curvatura. Ecco il codice di esempio.
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 = intervallo (1, len (y) +1)
da import in ginocchio KneeLocator kn = KneeLocator (x, y, curve = 'convex', direction = 'decreasing')
stampare (kn.knee)