KMEANS에서 k의 수를 추정하기 위해 BIC 사용


13

현재 장난감 데이터 세트 (ofc iris (:))의 BIC를 계산하려고합니다. 여기에 표시된 결과를 재현하려고합니다 (그림 5).이 논문은 BIC 공식의 소스이기도합니다.

나는 이것에 2 가지 문제가있다 :

  • 표기법:
    • ni = 클러스터 의 요소 수i
    • Ci = 군집 중심 좌표i
    • xj = 클러스터 할당 된 데이터 포인트i
    • m = 클러스터 수

1) 식에서 정의 된 분산 (2) :

i=1nimj=1nixjCi2

내가 알 수있는 한, 문제는 있지만 클러스터의 요소보다 많은 클러스터 m 이 있을 때 분산이 음수가 될 수 있다는 것은 다루지 않습니다 . 이 올바른지?

2) 올바른 BIC를 계산하기 위해 코드를 작동시킬 수 없습니다. 잘만되면 오류가 없지만 누군가 확인할 수 있다면 높이 평가 될 것입니다. 전체 방정식은 Eq. 종이에 (5). scikit learn을 사용하여 모든 것을 지금 당장 사용하고 있습니다 (키워드 : 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 2015 년

ttnphns 감사합니다. 나는 당신의 대답을 전에 보았습니다. 그러나 그것은 단계가 어떻게 파생되는지에 대한 참조가 없으므로 내가 찾고있는 것이 아닙니다. 또한이 SPSS 출력 또는 구문이 읽을 수있는 것은 아닙니다. 어쨌든 고마워 이 질문에 대한 관심이 없기 때문에 참조를 찾고 분산에 대한 다른 추정치를 사용합니다.
Kam Sen

나는 이것이 귀하의 질문에 대답하지 않는다는 것을 알고 있습니다 (따라서 주석으로 남겨 두십시오). 나는 당신이 sklearn을 사용하고 있음을 이해하지만 단지 그것을 버리고 싶었습니다.
Brash Equilibrium

1
가슴 앓이, sklearn는 GMM이
eyaler

답변:


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.

const_term :

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

해야한다:

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

삼.

분산 공식 :

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

@eyaler 여기에서 저를 바로 잡아 주시겠습니까? : -stats.stackexchange.com/questions/342258/…
Pranay Wankhede

종이를 연결하거나 수학적 마크 업으로 작성할 수 있습니까?
donlan

Pl 여기 내 관련 질문을 참조하십시오 : stats.stackexchange.com/questions/374002/…
rnso

Seanny123 및 eyaler @ 포스트 참조하십시오 stats.stackexchange.com/questions/374002/... rnso에서합니다. 이 공식은 3 개의 군집이 있어야하는 홍채 데이터에 대해 약 9 개의 군집을 제공합니다
Bernardo Braga

11

이것은 기본적으로 eyaler의 솔루션이며 몇 가지 메모가 있습니다. 누군가가 빠른 복사 / 붙여 넣기를 원하면 방금 입력했습니다.

노트:

  1. eyalers 4 번째 코멘트가 잘못되었습니다. np.log는 이미 자연적인 로그이므로 변경할 필요가 없습니다

  2. 반대자들에 대한 5 번째 의견은 맞습니다. 아래 코드에서 MAXIMUM을 찾고 있습니다.이 예에는 음의 BIC 숫자가 있습니다.

코드는 다음과 같습니다 (다시 말해서 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

github.com/bobhancock/goxmeans/blob/master/doc/BIC_notes.pdf를 보면 이 BIC 공식이 MAXIMUM에 어떻게 최적화되어 있는지 설명 할 수 있습니까? 최소를 보여주고 언어로 무엇을하는지 설명해 주시겠습니까? 공식을 해석하기 어려운 것을 발견 함
user305883

Pl 여기 내 관련 질문을 참조하십시오 : stats.stackexchange.com/questions/374002/…
rnso

1
수식에 버그가있는 것 같습니다. 누구든지 그것을 고쳤습니까?
STiGMa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.