Sử dụng BIC để ước tính số lượng k trong KMEANS


13

Tôi hiện đang cố gắng tính BIC cho bộ dữ liệu đồ chơi của mình (ofc iris (:). Tôi muốn sao chép các kết quả như được hiển thị ở đây (Hình 5). Bài báo đó cũng là nguồn của tôi cho các công thức BIC.

Tôi có 2 vấn đề với điều này:

  • Ký hiệu:
    • nTôi = số phần tử trong cụmTôi
    • CTôi = tọa độ trung tâm của cụmTôi
    • xj = điểm dữ liệu được gán cho cụmTôi
    • m = số cụm

1) Phương sai như được định nghĩa trong biểu thức. (2):

ΣTôi= =1nTôi-mΣj= =1nTôixj-CTôi2

Theo như tôi có thể thấy nó có vấn đề và không được đề cập rằng phương sai có thể âm khi có nhiều cụm hơn các phần tử trong cụm. Điều này có đúng không?m

2) Tôi chỉ không thể làm cho mã của mình hoạt động để tính BIC chính xác. Hy vọng không có lỗi, nhưng nó sẽ được đánh giá cao nếu ai đó có thể kiểm tra. Toàn bộ phương trình có thể được tìm thấy trong phương trình. (5) trong bài báo. Tôi đang sử dụng scikit learn cho mọi thứ ngay bây giờ (để biện minh cho từ khóa: 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")

Kết quả của tôi cho BIC trông như thế này:

Điều này thậm chí không gần với những gì tôi đã mong đợi và cũng không có ý nghĩa gì cả ... Tôi đã xem xét các phương trình bây giờ và không nhận được bất kỳ sai lầm nào nữa):


Bạn có thể tìm thấy tính toán của BIC để phân cụm ở đây . Đó là cách SPSS làm điều đó. Không nhất thiết phải chính xác như cách bạn thể hiện.
ttnphns

Cảm ơn bạn ttnphns. Tôi đã thấy câu trả lời của bạn trước đây. Nhưng điều đó không có tài liệu tham khảo về cách các bước được bắt nguồn và do đó không phải là những gì tôi đang tìm kiếm. Ngoài ra, đầu ra SPSS này hoặc bất kỳ cú pháp nào là không dễ đọc. Dù sao cũng cảm ơn bạn. Do không quan tâm đến câu hỏi này, tôi sẽ tìm tài liệu tham khảo và sử dụng một ước tính khác cho phương sai.
Kam Sen

Tôi biết điều này không trả lời câu hỏi của bạn (vì vậy tôi để nó như một nhận xét), nhưng gói R mclust phù hợp với các mô hình hỗn hợp hữu hạn (một phương pháp phân cụm tham số) và tự động tối ưu hóa số lượng, hình dạng, kích thước, định hướng và tính không đồng nhất của các cụm. Tôi hiểu bạn đang sử dụng sklearn nhưng chỉ muốn ném nó ra khỏi đó.
Cân bằng Brash

1
Brash, sklearn cũng có GMM
eyaler

@KamSen bạn có thể vui lòng giúp tôi ở đây? : - stats.stackexchange.com/questions/342258/ từ
Pranay Wankhede

Câu trả lời:


14

Có vẻ như bạn có một vài lỗi trong công thức của mình, như được xác định bằng cách so sánh với:

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

Ở đây có ba lỗi trong bài báo, dòng thứ tư và thứ năm thiếu hệ số d, dòng cuối cùng thay thế m cho 1. Nó phải là:

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.

Các const_term:

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

nên là:

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

3.

Công thức phương sai:

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

nên là một vô hướng:

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.

Sử dụng nhật ký tự nhiên, thay vì nhật ký cơ sở10 của bạn.

5.

Cuối cùng, và quan trọng nhất, BIC bạn đang tính toán có dấu hiệu nghịch đảo từ định nghĩa thông thường. vì vậy bạn đang tìm cách tối đa hóa thay vì giảm thiểu


1
MK(φ)2

@eyaler bạn có thể vui lòng sửa cho tôi ở đây? : - stats.stackexchange.com/questions/342258/ từ
Pranay Wankhede

bạn có thể liên kết một bài báo, hoặc viết điều này trong đánh dấu toán học?
donlan

Pl xem câu hỏi có liên quan của tôi ở đây: stats.stackexchange.com/questions/374002/...
rnso

@ Seanny123 và eyaler vui lòng xem số liệu thống kê bài viết.stackexchange.com/questions / 374002 / Fọ từ rnso. Công thức này đưa ra khoảng 9 cụm trên dữ liệu mống mắt nên có 3 cụm
Bernardo Braga

11

Đây là giải pháp cơ bản cho mắt, với một vài ghi chú .. Tôi chỉ cần gõ nó ra nếu ai đó muốn sao chép / dán nhanh:

Ghi chú:

  1. Nhận xét thứ 4 không đúng np.log đã là một bản ghi tự nhiên, không cần thay đổi

  2. Eyalers Nhận xét thứ 5 về nghịch đảo là chính xác. Trong mã bên dưới, bạn đang tìm kiếm MAXIMUM - hãy nhớ rằng ví dụ này có số BIC âm

Mã như sau (một lần nữa, tất cả tín dụng cho người xem):

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

Nhìn vào github.com/bobhancock/goxmeans/blob/master/doc/BIC_notes.pdf bạn có thể giải thích cách công thức BIC này tối ưu hóa cho MAXIMUM không? Bạn có thể hiển thị cho Tối thiểu và giải thích những gì nó làm bằng ngôn ngữ bằng lời nói? khó tìm cách giải thích công thức
user305883

Xin vui lòng xem câu hỏi liên quan của tôi ở đây: stats.stackexchange.com/questions/374002/NH
rnso

1
dường như có một lỗi trong công thức. Có ai quản lý để sửa nó?
STiGMa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.