ใช้ BIC เพื่อประมาณจำนวน k ใน KMEANS


13

ขณะนี้ฉันกำลังพยายามคำนวณ BIC สำหรับชุดข้อมูลของเล่นของฉัน (ofc iris (:)) ฉันต้องการสร้างผลลัพธ์ดังที่แสดงที่นี่ (รูปที่ 5) กระดาษนั้นก็เป็นแหล่งของสูตร BIC ด้วย

ฉันมี 2 ปัญหากับสิ่งนี้:

  • โน้ต:
    • ni = จำนวนขององค์ประกอบในคลัสเตอร์i
    • Ci = พิกัดกลางของคลัสเตอร์i
    • xj = จุดข้อมูลที่กำหนดให้กับคลัสเตอร์i
    • m = จำนวนกลุ่ม

1) ความแปรปรวนตามที่กำหนดไว้ใน Eq (2):

i=1nimj=1nixjCi2

เท่าที่ฉันเห็นมันเป็นปัญหาและไม่ครอบคลุมว่าความแปรปรวนอาจเป็นลบเมื่อมีกลุ่มmมากกว่าองค์ประกอบในคลัสเตอร์ ถูกต้องหรือไม่

2) ฉันไม่สามารถทำให้โค้ดของฉันทำงานเพื่อคำนวณ BIC ที่ถูกต้องได้ หวังว่าจะไม่มีข้อผิดพลาด แต่มันจะได้รับการชื่นชมอย่างมากหากมีใครสามารถตรวจสอบได้ สมการทั้งหมดสามารถพบได้ในสมการ (5) ในกระดาษ ฉันกำลังใช้ scikit เรียนรู้ทุกอย่างตอนนี้ (เพื่อปรับคำหลัก: 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 เป็นดังนี้:

ซึ่งไม่ใกล้เคียงกับสิ่งที่ฉันคาดไว้และไม่สมเหตุสมผล ... ฉันดูสมการในขณะนี้มาระยะหนึ่งแล้ว


คุณอาจพบการคำนวณ BIC สำหรับการจัดกลุ่มที่นี่ มันเป็นวิธีที่ SPSS ทำ ไม่จำเป็นต้องเป็นแบบเดียวกับที่คุณแสดง
ttnphns

ขอบคุณ ttnphns ฉันเห็นคำตอบของคุณมาก่อน แต่นั่นไม่มีการอ้างอิงถึงขั้นตอนที่ได้มาและไม่ใช่สิ่งที่ฉันกำลังมองหา ยิ่งกว่านั้นเอาต์พุต SPSS นี้หรือสิ่งที่ไวยากรณ์ไม่สามารถอ่านได้มาก ขอบคุณอยู่ดี เนื่องจากการขาดความสนใจในคำถามนี้ฉันจะค้นหาการอ้างอิงและใช้การประมาณค่าความแปรปรวนอื่น
Kam Sen

ฉันรู้ว่าสิ่งนี้ไม่ได้ตอบคำถามของคุณ (ดังนั้นฉันจึงแสดงความคิดเห็น) แต่ R package mclust เหมาะกับแบบจำลองการรวมแบบ จำกัด (วิธีการจัดกลุ่มแบบพารามิเตอร์) และปรับขนาดรูปร่างขนาดการปฐมนิเทศและความหลากหลายของกลุ่มให้เหมาะสมโดยอัตโนมัติ ฉันเข้าใจว่าคุณกำลังใช้ sklearn แต่อยากจะโยนมันทิ้งไป
Brash Equilibrium

1
Brash, sklearn ยังมี GMM
eyaler

@ Kamen คุณช่วยฉันได้ไหมที่นี่ : - stats.stackexchange.com/questions/342258/…
Pranay Wankhede

คำตอบ:


14

ดูเหมือนว่าคุณมีข้อผิดพลาดเล็กน้อยในสูตรตามที่กำหนดโดยเปรียบเทียบกับ:

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

ที่นี่มีข้อผิดพลาดสามข้อในกระดาษบรรทัดที่สี่และห้าขาดปัจจัย d บรรทัดสุดท้ายแทน m สำหรับ 1 ควรเป็น:

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

The const_term:

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

ควรจะเป็น:

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

3

สูตรผลต่าง:

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

ควรเป็นเซนต์คิตส์และเนวิส:

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 ของคุณ

5

สุดท้ายและที่สำคัญที่สุดคือ BIC ที่คุณใช้งานอยู่มีเครื่องหมายผกผันจากคำจำกัดความปกติ ดังนั้นคุณกำลังมองหาที่จะเพิ่มสูงสุดแทนการลด


1
เพียงพูดถึงใน BIC_notes ( https://github.com/bobhancock/goxmeans/blob/master/doc/BIC_notes.pdf ) ที่มาจาก (21) ถึง (22) ได้รับสัญลักษณ์ของผิด รหัสในคำตอบที่ได้รับคะแนนสูงสุดถูกต้อง MK(ϕ)2
Mikoyan

@ ผู้จำหน่ายคุณช่วยแก้ไขให้ฉันที่นี่ได้มั้ย : - stats.stackexchange.com/questions/342258/ …
Pranay Wankhede

คุณสามารถเชื่อมโยงกระดาษหรือเขียนสิ่งนี้ในมาร์กอัปทางคณิตศาสตร์ได้ไหม
donlan

โปรดดูคำถามที่เกี่ยวข้องของฉันที่นี่: stats.stackexchange.com/questions/374002/…
rnso

@ Seanny123 และ eyaler โปรดดูโพสต์stats.stackexchange.com/questions/374002/…จาก rnso สูตรนี้ให้ประมาณ 9 กลุ่มกับข้อมูลม่านตาซึ่งควรมี 3 กลุ่ม
Bernardo Braga

11

นี่เป็นวิธีแก้ปัญหาของผู้เห็นภาพโดยมีเพียงไม่กี่ข้อ .. ฉันเพิ่งพิมพ์ออกมาถ้ามีคนต้องการคัดลอก / วางอย่างรวดเร็ว:

หมายเหตุ:

  1. eyalers ความคิดเห็นที่ 4 ไม่ถูกต้อง np.log เป็นบันทึกธรรมดาแล้วไม่จำเป็นต้องเปลี่ยนแปลง

  2. eyalers ความคิดเห็นที่ 5 เกี่ยวกับสิ่งที่ตรงกันข้ามนั้นถูกต้อง ในรหัสด้านล่างนี้คุณกำลังค้นหา MAXIMUM - โปรดทราบว่าตัวอย่างมีหมายเลข BIC ติดลบ

รหัสมีดังต่อไปนี้ (อีกครั้งเครดิตทั้งหมดให้กับอายแชโดว์):

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คุณสามารถอธิบายได้อย่างไรว่าสูตร BIC นี้ได้รับการปรับให้เหมาะสมสำหรับ MAXIMUM หรือไม่ คุณสามารถแสดงขั้นต่ำและอธิบายสิ่งที่มันทำในภาษาวาจา หายากที่จะตีความสูตร
user305883

โปรดดูคำถามที่เกี่ยวข้องของฉันที่นี่: stats.stackexchange.com/questions/374002/…
rnso

1
ดูเหมือนว่าจะมีข้อบกพร่องในสูตร มีใครจัดการเพื่อแก้ไขหรือไม่
STiGMa
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.