Attualmente sto provando a calcolare il BIC per il mio set di dati giocattolo (ofc iris (:). Voglio riprodurre i risultati come mostrato qui (Fig. 5). Quel documento è anche la mia fonte per le formule BIC.
Ho 2 problemi con questo:
- Notazione:
- = numero di elementi nel cluster
- = coordinate centrali del cluster
- = punti dati assegnati al cluster
- = numero di cluster
1) La varianza come definita nell'Eq. (2):
Per quanto posso vedere, è problematico e non coperto che la varianza possa essere negativa quando ci sono più cluster rispetto agli elementi nel cluster. È corretto?
2) Non riesco proprio a far funzionare il mio codice per calcolare il BIC corretto. Speriamo che non ci siano errori, ma sarebbe molto apprezzato se qualcuno potesse controllare. L'intera equazione può essere trovata nell'Eq. (5) nel documento. Sto usando Scikit Learn per tutto in questo momento (per giustificare la parola chiave: 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")
I miei risultati per il BIC si presentano così:
Il che non è nemmeno vicino a quello che mi aspettavo e non ha nemmeno senso ... Ho guardato le equazioni ormai da un po 'di tempo e non riesco più a localizzare il mio errore):