Menggunakan BIC untuk memperkirakan jumlah k dalam KMEANS


13

Saat ini saya mencoba menghitung BIC untuk kumpulan data mainan saya (ofc iris (:). Saya ingin mereproduksi hasil seperti yang ditunjukkan di sini (Gbr. 5). Makalah itu juga merupakan sumber saya untuk formula BIC.

Saya memiliki 2 masalah dengan ini:

  • Notasi:
    • ni = jumlah elemen dalam klasteri
    • Ci = pusat koordinat clusteri
    • xj = titik data yang ditetapkan untuk clusteri
    • m = jumlah cluster

1) Varians sebagaimana didefinisikan dalam Persamaan. (2):

i=1nimj=1nixjCi2

Sejauh yang saya lihat itu bermasalah dan tidak tercakup bahwa varians bisa negatif ketika ada lebih banyak cluster m daripada elemen dalam cluster. Apakah ini benar?

2) Saya tidak bisa membuat kode saya berfungsi untuk menghitung BIC yang benar. Semoga tidak ada kesalahan, tetapi akan sangat dihargai jika seseorang bisa memeriksanya. Seluruh persamaan dapat ditemukan dalam Persamaan. (5) di koran. Saya menggunakan scikit belajar untuk semuanya sekarang (untuk membenarkan kata kunci: 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")

Hasil saya untuk BIC terlihat seperti ini:

Yang bahkan tidak mendekati apa yang saya harapkan dan juga tidak masuk akal ... Saya melihat persamaan sekarang untuk beberapa waktu dan saya tidak mendapatkan lebih jauh menemukan kesalahan saya):


Anda dapat menemukan perhitungan BIC untuk pengelompokan di sini . Begitulah cara SPSS melakukannya. Tidak harus persis dengan cara yang sama seperti yang Anda tunjukkan.
ttnphns

Terima kasih ttnphn. Saya melihat jawaban Anda sebelumnya. Tetapi itu tidak memiliki referensi tentang bagaimana langkah-langkah itu diturunkan dan dengan demikian bukan apa yang saya cari. Apalagi output SPSS ini atau apapun sintaksinya tidak terlalu mudah dibaca. Terima kasih. Karena kurangnya minat pada pertanyaan ini, saya akan mencari referensi dan menggunakan perkiraan lain untuk varians.
Kam Sen

Saya tahu ini tidak menjawab pertanyaan Anda (jadi saya meninggalkannya sebagai komentar), tetapi paket R mclust cocok untuk model campuran hingga (metode pengelompokan parametrik) dan secara otomatis mengoptimalkan jumlah, bentuk, ukuran, orientasi, dan heterogenitas kluster. Saya mengerti Anda menggunakan sklearn tetapi hanya ingin membuangnya di sana.
Brash Equilibrium

1
Brash, sklearn juga punya GMM
eyaler

@ SamSen, bisakah Anda membantu saya di sini : - stats.stackexchange.com/questions/342258/…
Pranay Wankhede

Jawaban:


14

Tampaknya Anda memiliki beberapa kesalahan dalam rumus Anda, sebagaimana ditentukan dengan membandingkan dengan:

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

Di sini ada tiga kesalahan di koran, baris keempat dan kelima tidak ada faktor d, ganti baris terakhir m untuk 1. Seharusnya:

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)

seharusnya:

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

3.

Rumus varians:

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)]

harus berupa skalar:

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.

Gunakan log natural, bukan log base10 Anda.

5.

Akhirnya, dan yang paling penting, BIC yang Anda hitung memiliki tanda kebalikan dari definisi reguler. jadi Anda ingin memaksimalkan bukannya meminimalkan


1
Sebagai tambahan, dalam BIC_notes ( https://github.com/bobhancock/goxmeans/blob/master/doc/BIC_notes.pdf ), turunan dari (21) hingga (22) mendapat tanda salah. Kode dalam jawaban pilihan tertinggi benar. MK(ϕ)2
Mikoyan

@eyaler tolong perbaiki saya di sini? : - stats.stackexchange.com/questions/342258/…
Pranay Wankhede

dapatkah Anda menautkan makalah, atau menulis ini di markup matematika?
Donlan

Pl lihat pertanyaan terkait saya di sini: stats.stackexchange.com/questions/374002/...
rnso

@ Seanny123 dan eyaler silakan lihat posting stats.stackexchange.com/questions/374002/… dari rnso. Formula ini memberikan sekitar 9 klaster pada data iris yang seharusnya memiliki 3 kluster
Bernardo Braga

11

Ini pada dasarnya adalah solusi eyeral, dengan beberapa catatan .. Saya baru saja mengetiknya jika seseorang menginginkan salinan / tempel cepat:

Catatan:

  1. eyaler komentar ke-4 salah np.log sudah menjadi log natural, tidak diperlukan perubahan

  2. eyaler komentar ke-5 tentang invers benar. Dalam kode di bawah ini, Anda mencari MAKSIMUM - ingat bahwa contohnya memiliki angka BIC negatif

Kode adalah sebagai berikut (sekali lagi, semua kredit ke eyaler):

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

Melihat github.com/bobhancock/goxmeans/blob/master/doc/BIC_notes.pdf dapatkah Anda menjelaskan bagaimana rumus BIC ini dioptimalkan untuk MAKSIMUM? Bisakah Anda menunjukkan Minimum dan menjelaskan apa yang dilakukannya dalam bahasa verbal? menemukan kesulitan untuk menafsirkan rumus
user305883

Tolong lihat pertanyaan saya yang terkait di sini: stats.stackexchange.com/questions/374002/...
rnso

1
sepertinya ada bug dalam formula. Adakah yang berhasil memperbaikinya?
STiGMa
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.