KMEANS'taki k sayısını tahmin etmek için BIC kullanma


13

Şu anda oyuncak veri setim için BIC'yi hesaplamaya çalışıyorum (ofc iris (:). Sonuçları burada gösterildiği gibi çoğaltmak istiyorum (Şekil 5) Bu makale aynı zamanda BIC formülleri için kaynağım.

Bu konuda 2 problemim var:

  • Gösterim:
    • ni ben küme eleman = sayısıi
    • Ci i = küme merkez koordinatlarıi
    • xj i = küme atanan veri noktalarıi
    • m = küme sayısı

1) Denklemde tanımlanan varyans. (2):

i=1nimj=1nixjCi2

Gördüğüm kadarıyla sorunludur ve kümedeki elemanlardan daha fazla küme m olduğunda varyansın negatif olabileceği kapsanmamıştır . Bu doğru mu?

2) Kodumu doğru BIC'yi hesaplamak için çalıştıramıyorum. Umarım bir hata yoktur, ancak birisinin kontrol edebilmesi çok takdir edilecektir. Denklemin tamamı Denklemde bulunabilir. (5). Şu anda her şey için scikit öğrenmek kullanıyorum (anahtar kelimeyi haklı göstermek için: P).

from sklearn import cluster
from scipy.spatial import distance
import sklearn.datasets
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import numpy as np

def compute_bic(kmeans,X):
    """
    Computes the BIC metric for a given clusters

    Parameters:
    -----------------------------------------
    kmeans:  List of clustering object from scikit learn

    X     :  multidimension np array of data points

    Returns:
    -----------------------------------------
    BIC value
    """
    # assign centers and labels
    centers = [kmeans.cluster_centers_]
    labels  = kmeans.labels_
    #number of clusters
    m = kmeans.n_clusters
    # size of the clusters
    n = np.bincount(labels)
    #size of data set
    N, d = X.shape

    #compute variance for all clusters beforehand
    cl_var = [(1.0 / (n[i] - m)) * sum(distance.cdist(X[np.where(labels == i)], [centers[0][i]], 'euclidean')**2)  for i in xrange(m)]

    const_term = 0.5 * m * np.log10(N)

    BIC = np.sum([n[i] * np.log10(n[i]) -
           n[i] * np.log10(N) -
         ((n[i] * d) / 2) * np.log10(2*np.pi) -
          (n[i] / 2) * np.log10(cl_var[i]) -
         ((n[i] - m) / 2) for i in xrange(m)]) - const_term

    return(BIC)



# IRIS DATA
iris = sklearn.datasets.load_iris()
X = iris.data[:, :4]  # extract only the features
#Xs = StandardScaler().fit_transform(X)
Y = iris.target

ks = range(1,10)

# run 9 times kmeans and save each result in the KMeans object
KMeans = [cluster.KMeans(n_clusters = i, init="k-means++").fit(X) for i in ks]

# now run for each cluster the BIC computation
BIC = [compute_bic(kmeansi,X) for kmeansi in KMeans]

plt.plot(ks,BIC,'r-o')
plt.title("iris data  (cluster vs BIC)")
plt.xlabel("# clusters")
plt.ylabel("# BIC")

BIC sonuçlarım şöyle:

Bu, beklediğim şeye yakın bile değil ve aynı zamanda bir anlam ifade etmiyor ... Bir süre için denklemlere baktım ve hatamı daha fazla bulamıyorum):


Kümeleme için BIC hesaplamasını burada bulabilirsiniz . SPSS bunu böyle yapar. Mutlaka gösterdiğiniz gibi olması gerekmez.
ttnphns

Teşekkürler ttnphns. Cevabını daha önce gördüm. Ama bu adımların nasıl türetildiğine dair bir referansı yok ve bu yüzden aradığım şey değil. Dahası, bu SPSS çıktısı veya sözdizimi ne olursa olsun çok okunabilir değildir. Yine de teşekkürler. Bu sorulara ilgi göstermemesi nedeniyle referansı arayacağım ve varyans için başka bir tahmin kullanacağım.
Kam Sen

Bunun sorunuza cevap vermediğini biliyorum (bu yüzden bir yorum olarak bırakıyorum), ancak R paketi mclust sonlu karışım modellerine (parametrik bir kümeleme yöntemi) uyar ve kümelerin sayısını, şeklini, boyutunu, yönünü ve heterojenliğini otomatik olarak optimize eder. Sklearn kullandığınızı anlıyorum ama sadece bunu dışarı atmak istedim.
Küstah Denge

1
Küstah, sklearn'in GMM'si de var
eyaler

@KamSen lütfen bana yardım edebilir misin? : - stats.stackexchange.com/questions/342258/…
Pranay Wankhede

Yanıtlar:


14

Formüllerinizde aşağıdakilerle karşılaştırılarak belirlendiği gibi birkaç hatanız var gibi görünüyor:

1.

np.sum([n[i] * np.log(n[i]) -
               n[i] * np.log(N) -
             ((n[i] * d) / 2) * np.log(2*np.pi) -
              (n[i] / 2) * np.log(cl_var[i]) -
             ((n[i] - m) / 2) for i in range(m)]) - const_term

Burada gazetede üç hata var, dördüncü ve beşinci satırlarda d faktörü eksik, son satır 1 yerine m.

np.sum([n[i] * np.log(n[i]) -
               n[i] * np.log(N) -
             ((n[i] * d) / 2) * np.log(2*np.pi*cl_var) -
             ((n[i] - 1) * d/ 2) for i in range(m)]) - const_term

2.

Const_term:

const_term = 0.5 * m * np.log(N)

olmalı:

const_term = 0.5 * m * np.log(N) * (d+1)

3.

Varyans formülü:

cl_var = [(1.0 / (n[i] - m)) * sum(distance.cdist(p[np.where(label_ == i)], [centers[0][i]], 'euclidean')**2)  for i in range(m)]

skaler olmalı:

cl_var = (1.0 / (N - m) / d) * sum([sum(distance.cdist(p[np.where(labels == i)], [centers[0][i]], 'euclidean')**2) for i in range(m)])

4.

Base10 günlükleriniz yerine doğal günlükler kullanın.

5.

Son olarak ve en önemlisi, hesapladığınız BIC'nin düzenli tanımdan ters işareti vardır. minimize etmek yerine maksimize etmek istiyorsunuz


1
Sadece bahsetmek gerekirse, BIC_notes'ta ( https://github.com/bobhancock/goxmeans/blob/master/doc/BIC_notes.pdf ), (21) 'den (22)' ye kadar olan türevde yanlış. En çok oy verilen cevaptaki kod doğrudur. MK(ϕ)2
Mikoyan

@eyaler lütfen beni burada düzeltebilir misin? : - stats.stackexchange.com/questions/342258/…
Pranay Wankhede

bir makaleyi bağlayabilir veya bunu matematiksel işaretlemeyle yazabilir misiniz?
donlan

Pl ilgili soruma burada bakın: stats.stackexchange.com/questions/374002/…
rnso

@ Seanny123 ve eyaler rnso'dan gönderi istatistiklerine bakınız. Stackexchange.com/questions/374002/… Bu formül, 3 kümeye sahip olması gereken iris verileri hakkında yaklaşık 9 küme veriyor
Bernardo Braga

11

Bu temelde eyaler'ın çözümü, birkaç notla .. Birisi hızlı bir kopyala / yapıştır isterse sadece yazdım:

Notlar:

  1. eyalers 4. yorum yanlış np.log zaten doğal bir günlük, değişiklik gerekli değil

  2. eyalers ters 5. yorum doğru. Aşağıdaki kodda, MAKSİMUM'u arıyorsunuz - örneğin negatif BIC numaraları olduğunu unutmayın

Kod aşağıdaki gibidir (yine, eyaler'a verilen tüm krediler):

from sklearn import cluster
from scipy.spatial import distance
import sklearn.datasets
from sklearn.preprocessing import StandardScaler
import numpy as np

def compute_bic(kmeans,X):
    """
    Computes the BIC metric for a given clusters

    Parameters:
    -----------------------------------------
    kmeans:  List of clustering object from scikit learn

    X     :  multidimension np array of data points

    Returns:
    -----------------------------------------
    BIC value
    """
    # assign centers and labels
    centers = [kmeans.cluster_centers_]
    labels  = kmeans.labels_
    #number of clusters
    m = kmeans.n_clusters
    # size of the clusters
    n = np.bincount(labels)
    #size of data set
    N, d = X.shape

    #compute variance for all clusters beforehand
    cl_var = (1.0 / (N - m) / d) * sum([sum(distance.cdist(X[np.where(labels == i)], [centers[0][i]], 
             'euclidean')**2) for i in range(m)])

    const_term = 0.5 * m * np.log(N) * (d+1)

    BIC = np.sum([n[i] * np.log(n[i]) -
               n[i] * np.log(N) -
             ((n[i] * d) / 2) * np.log(2*np.pi*cl_var) -
             ((n[i] - 1) * d/ 2) for i in range(m)]) - const_term

    return(BIC)



# IRIS DATA
iris = sklearn.datasets.load_iris()
X = iris.data[:, :4]  # extract only the features
#Xs = StandardScaler().fit_transform(X)
Y = iris.target

ks = range(1,10)

# run 9 times kmeans and save each result in the KMeans object
KMeans = [cluster.KMeans(n_clusters = i, init="k-means++").fit(X) for i in ks]

# now run for each cluster the BIC computation
BIC = [compute_bic(kmeansi,X) for kmeansi in KMeans]

print BIC

Github.com/bobhancock/goxmeans/blob/master/doc/BIC_notes.pdf adresine bakarak bu BIC formülünün MAKSİMUM için nasıl optimize ettiğini açıklayabilir misiniz? Minimum'a gösterebilir ve sözlü dilde ne yaptığını açıklayabilir misiniz? formülü yorumlamak zor
user305883

Pl ilgili soruma burada bakın: stats.stackexchange.com/questions/374002/…
rnso

1
formülde bir hata var gibi görünüyor. Bunu düzeltmeyi başaran var mı?
STiGMa
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.