Ben yaklaşık inceliyordum k-ortalamalar kümeleme ve net değil bir şey k değerini seçmek nasıl. Sadece deneme yanılma mıydı yoksa daha fazlası mı var?
R
) benzer bir Q yanıtladım : stackoverflow.com/a/15376462/1036500
Ben yaklaşık inceliyordum k-ortalamalar kümeleme ve net değil bir şey k değerini seçmek nasıl. Sadece deneme yanılma mıydı yoksa daha fazlası mı var?
R
) benzer bir Q yanıtladım : stackoverflow.com/a/15376462/1036500
Yanıtlar:
Bayesian Bilgi Ölçütünü (BIC) en üst düzeye çıkarabilirsiniz:
BIC(C | X) = L(X | C) - (p / 2) * log n
burada L(X | C)
veri kümesi log-olasılık olan X
modele göre C
, p
model parametrelerinin sayısı C
, ve n
veri kümesi içinde nokta sayısıdır. Bkz. ICML 2000'de Dan Pelleg ve Andrew Moore tarafından "X-anlamları: K -ortalamalarını küme sayısını etkili bir şekilde tahmin ederek genişletme " .
Başka bir yaklaşım, k
artık açıklama uzunluğunu azaltmayana kadar sentroidleri büyük bir değerle başlamak ve çıkarmaya devam etmektir (k azaltarak). Bkz "sağlam vektör nicemleme için MDL ilkesini" de Horst Bischof, Ales LEONARDIS, ve Alexander Selb tarafından Desen Analizi ve Uygulamaları vol. 2, s. 59-72, 1999.
Son olarak, bir kümeyle başlayabilir, ardından her kümeye atanan noktalar bir Gauss dağılımına sahip olana kadar kümeleri bölmeye devam edebilirsiniz. In "Öğrenme k içinde k -Ben" (2003 NIPS), Greg Hamerly ve Charles Elkan bu eserler daha iyi BIC daha ve bu BIC yeterince güçlü modelin karmaşıklığını cezalandırmak olmadığını bazı kanıtlar göstermektedir.
Temel olarak, iki değişken arasında bir denge bulmak istersiniz: küme sayısı ( k ) ve kümelerin ortalama varyansı. Birincisini en aza indirirken ikincisini de küçültmek istiyorsunuz. Tabii ki, küme sayısı arttıkça ortalama varyans azalır (önemsiz k = n ve varyans = 0 durumuna kadar ).
Veri analizinde her zaman olduğu gibi, her durumda diğerlerinden daha iyi çalışan tek bir gerçek yaklaşım yoktur. Sonunda, kendi en iyi kararınızı kullanmalısınız. Bunun için, kümelerin sayısını ortalama varyansa göre çizmeye yardımcı olur (algoritmayı birkaç k değeri için zaten çalıştırdığınızı varsayar ). Sonra eğrinin dizindeki kümelerin sayısını kullanabilirsiniz.
Evet, Dirsek yöntemini kullanarak kümelerin en iyi sayısını bulabilirsiniz, ancak komut dosyası kullanarak dirsek grafiğinden kümelerin değerini bulmak zahmetli buldum. Dirsek grafiğini gözlemleyebilir ve dirsek noktasını kendiniz bulabilirsiniz, ancak senaryodan bulmak çok işti.
Yani başka bir seçenek bulmak için Silhouette Metodu kullanmaktır . Silhouette'in sonucu R'deki Dirsek yönteminin sonucuna tamamen uygundur.
İşte yaptığım şey.
#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")
Umarım yardımcı olur!!
Kod örneği arayan benim gibi yeni başlayan biri olabilir. silhouette_score ile ilgili bilgilere buradan ulaşabilirsiniz.
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)
Başparmak Kuralı denilen bir şey var. Küme sayısının şu şekilde hesaplanabileceğini söylüyor:
k = (n/2)^0.5
burada n, numunenizdeki toplam öğe sayısıdır. Aşağıdaki bilgilerin bu bilgilerin doğruluğunu kontrol edebilirsiniz:
http://www.ijarcsms.com/docs/paper/volume1/issue6/V1I6-0015.pdf
Ayrıca, dağıtımınızın bir Gauss Dağılımını veya Normal Dağılım'ı izlediği G-yolları adı verilen başka bir yöntem daha vardır. Tüm k gruplarınız bir Gauss Dağılımını takip edene kadar k'nın arttırılmasından oluşur. Çok fazla istatistik gerektirir, ancak yapılabilir. İşte kaynak:
http://papers.nips.cc/paper/2526-learning-the-k-in-k-means.pdf
Umarım bu yardımcı olur!
Önce verilerinizden oluşan minimum bir ağaç oluşturun. K-1'in en pahalı kenarlarını kaldırmak, ağacı K kümelerine ayırır,
böylece MST'yi bir kez oluşturabilir, çeşitli K için küme aralıklarına / metriklerine bakabilir ve eğrinin dizini alabilirsiniz.
Bu sadece Tekli bağlantı_kırma için çalışır , ancak bunun için hızlı ve kolaydır. Ayrıca, MST'ler iyi görseller oluşturur.
Örneğin, kümeleme için stats.stackexchange görselleştirme yazılımı altındaki MST grafiğine bakın
.
Kimsenin bu mükemmel makaleden bahsetmediğine şaşırdım: http://www.ee.columbia.edu/~dpwe/papers/PhamDN05-kmeans.pdf
Diğer birkaç öneriyi izledikten sonra nihayet bu blogu okurken bu makaleye rastladım: https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/
Bundan sonra Scala'da uyguladım, kullanım durumlarım için gerçekten iyi sonuçlar veren bir uygulama. İşte kod:
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]]
}
MATLAB'ı, 2013b'den bu yana herhangi bir sürümü kullanırsanız, belirli bir veri kümesi için evalclusters
en uygun olanı bulmak için işlevi kullanabilirsiniz k
.
- Bu işlev 3 kümeleme algoritmaları arasından seçim yapmanızı sağlar kmeans
, linkage
ve gmdistribution
.
- Ayrıca 4 kümelenme değerlendirme kriterleri arasında seçim yapmanızı sağlar CalinskiHarabasz
, DaviesBouldin
, gap
ve silhouette
.
K-araçlarına parametre olarak sağlanacak k kümelerinin sayısını bilmiyorsanız, otomatik olarak bulmanın dört yolu vardır:
G-algortitm anlamına gelir: bir k-ortalama merkezinin ikiye bölünüp bölünmeyeceğine karar vermek için istatistiksel bir test kullanarak kümelerin sayısını otomatik olarak keşfeder. Bu algoritma, bir veri alt kümesinin bir Gauss dağılımını (olayların tam binom dağılımına yaklaşan sürekli işlev) izlediği hipotezi için istatistiksel bir sınamaya dayalı olarak kümelerin sayısını tespit etmek için hiyerarşik bir yaklaşım benimser ve eğer değilse kümeyi böler . Sadece bir küme (k = 1) gibi az sayıda merkezle başlar, ardından algoritma onu iki merkeze böler (k = 2) ve bu iki merkezin her birini tekrar (k = 4) böler, Toplam. G-ortalaması bu dört merkezi kabul etmezse, cevap bir önceki adımdır: bu durumda iki merkez (k = 2). Bu, veri kümenizin bölüneceği küme sayısıdır. G-Ortalamaları, örneklerinizi grupladıktan sonra alacağınız küme sayısı hakkında bir tahmininiz olmadığında çok yararlıdır. "K" parametresi için uygunsuz bir seçimin size yanlış sonuçlar verebileceğine dikkat edin. G-araçlarının paralel versiyonuna denirp-anlamına gelir . G-kaynakları anlamına gelir: kaynak 1 kaynak 2 kaynak 3
x-anlamına gelir : Bayesian Bilgi Ölçütü (BIC) veya Akaike Bilgi Ölçütü (AIC) ölçüsünü optimize etmek için verimli bir şekilde küme konumlarını ve küme sayısını araştıran yeni bir algoritma. Bu k-araç versiyonu k sayısını bulur ve k-araçlarını hızlandırır.
Çevrimiçi k-araçları veya Akış k-araçları: tüm verileri bir kez tarayarak k-araçlarının yürütülmesine izin verir ve otomatik olarak optimum k sayısını bulur. Spark uygular.
MeanShift algoritması : kümelerin sayısı hakkında önceden bilgi gerektirmeyen ve kümelerin şeklini kısıtlamayan parametrik olmayan bir kümeleme tekniğidir. Ortalama vardiya kümelenmesi, numunelerin düzgün yoğunluğundaki “lekeleri” keşfetmeyi amaçlamaktadır. Bu, belirli bir bölgedeki noktaların ortalaması olacak şekilde sentroid adaylarını güncelleyerek çalışan bir sentroid tabanlı algoritmadır. Bu adaylar daha sonra son sentroid setini oluşturmak üzere kopyaları neredeyse ortadan kaldırmak için bir işleme sonrası aşamada filtrelenir. Kaynaklar: kaynak1 , kaynak2 , source3
Burada bulduğum çözümü kullandım: http://efavdb.com/mean-shift/ ve benim için çok iyi çalıştı:
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()
Benim fikrim, optimal küme numarasını (K) bulmak için Silhouette Katsayısı kullanmaktır . Ayrıntılar açıklama burada .
Olası bir cevap, k'yi bulmak için Genetik Algoritma gibi Meta Sezgisel Algoritmayı kullanmaktır. Bu basit. rastgele K'yi (bazı aralıklarda) kullanabilir ve Genetik Algoritmanın fit fonksiyonunu Silhouette ve Find fonksiyonundaki en iyi K bazını ölçebilirsiniz.
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})
Başka bir yaklaşım, optimum sayıda kümeyi bulmak için Kendi Kendini Düzenleyen Haritaları (SOP) kullanmaktır. SOM (Kendi Kendini Düzenleyen Harita) denetimsiz bir sinir ağı metodolojisidir ve problem çözme için kümelemede sadece girdinin kullanılması gerekir. Bu yaklaşım, müşteri segmentasyonu hakkında bir makalede kullanılmıştır.
Makalenin referansı
Abdellah Amine vd., Kümeleme Teknikleri ve LRFM Modeli Kullanarak E-ticarette Müşteri Segmentasyon Modeli: Fas'ta Online Mağazalar Örneği, Dünya Bilim, Mühendislik ve Teknoloji Akademisi Uluslararası Bilgisayar ve Bilişim Mühendisliği Dergisi Cilt: 9, No: 8 , 2015, 1999-2010
Merhaba ben açıklamak basit ve düz yapacak, 'NbClust' kitaplığı kullanarak kümeleri belirlemek istiyorum.
Şimdi, doğru sayıda kümeyi belirlemek için 'NbClust' işlevini kullanma: Github'daki gerçek projeyi gerçek veriler ve kümeler ile kontrol edebilirsiniz - Doğru sayıda 'merkez' kullanılarak gerçekleştirilen bu 'kmeans' algoritmasına eklenti.
Github Projesi Bağlantısı: https://github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook
Veri noktalarınızı görsel olarak inceleyerek kümelerin sayısını seçebilirsiniz, ancak yakında bu süreçte en basit veri kümeleri hariç herkes için çok fazla belirsizliğin olduğunu fark edeceksiniz. Bu her zaman kötü değildir, çünkü denetimsiz öğrenim görüyorsunuz ve etiketleme sürecinin doğasında bir sübjektiflik var. Burada, belirli bir problemle veya benzer bir şeyle daha önce deneyim sahibi olmanız, doğru değeri seçmenize yardımcı olacaktır.
Kullanmanız gereken küme sayısı hakkında bir ipucu istiyorsanız, Dirsek yöntemini uygulayabilirsiniz:
Her şeyden önce, bazı k değerleri (örneğin 2, 4, 6, 8, vb.) İçin karesel hatanın (SSE) toplamını hesaplayın. SSE, kümenin her bir üyesi ile sentroidi arasındaki kare mesafenin toplamı olarak tanımlanır. Matematiksel olarak:
SSE = ΣKi = 1Σx∈cidist (x, Cl) 2
K'yi SSE'ye göre çizerseniz, k büyüdükçe hatanın azaldığını görürsünüz; bunun nedeni, kümelerin sayısı arttığında daha küçük olmaları gerektiğinden bozulma da daha az olur. Dirsek yönteminin fikri, SSE'nin aniden azaldığı k'yi seçmektir. Bu, aşağıdaki resimde görebileceğiniz gibi, grafikte bir "dirsek efekti" üretir:
Bu durumda, k = 6 Dirsek yönteminin seçtiği değerdir. Dirsek yönteminin sezgisel bir yöntem olduğunu ve bu nedenle, özel durumunuzda iyi çalışabileceğini veya çalışmayabileceğini dikkate alın. Bazen birden fazla dirsek vardır veya hiç dirsek yoktur. Bu gibi durumlarda genellikle, k-araçlarının çözmeye çalıştığınız belirli kümeleme problemi bağlamında ne kadar iyi performans gösterdiğini değerlendirerek en iyi k değerini hesaplarsınız.
Diz çökmüş bir Python paketi üzerinde çalıştım (Kneedle algoritması). Küme numarasını, eğrinin düzleşmeye başladığı nokta olarak dinamik olarak bulur. Bir dizi x ve y değeri verildiğinde, diz fonksiyonun diz noktasını döndürür. Diz noktası maksimum eğrilik noktasıdır. İşte örnek kod.
y = [7342,1301373073857, 6881,7109460930769, 6531,1657905495022,
6356,2255554679778, 6209,8382535595829, 6094,9052166741121, 5980,0191582610196, 5880,1869867848218, 5779,8957906367368, 5691,1879324562778, 5617,5153566271356, 5532,2613232619951, 5467,352265375117, 5395,4493783888756, 5345,3459908298091, 5290,6769823693812, 5243,5271656371888, 5207,2501206569532, 5164,9617535255456]
x = aralık (1, len (y) +1)
diz içe aktarmadan KneeLocator kn = KneeLocator (x, y, eğri = 'dışbükey', yön = 'azalan')
yazdırmak (kn.knee)