Ich versuche derzeit, den BIC für meinen Spielzeugdatensatz (ofc iris (:)) zu berechnen. Ich möchte die hier gezeigten Ergebnisse reproduzieren (Abb. 5). Dieses Papier ist auch meine Quelle für die BIC-Formeln.
Ich habe 2 Probleme damit:
- Notation:
- = Anzahl der Elemente in Cluster
- = Mittelkoordinaten des Clusters
- = Datenpunkte, die dem Cluster i zugewiesen sind
- = Anzahl der Cluster
1) Die Varianz wie in Gl. (2):
Soweit ich sehe, ist es problematisch und nicht abgedeckt, dass die Varianz negativ sein kann, wenn es mehr Cluster als Elemente im Cluster gibt. Ist das richtig?
2) Ich kann meinen Code einfach nicht zum Arbeiten bringen, um den korrekten BIC zu berechnen. Hoffentlich gibt es keinen Fehler, aber es wäre sehr dankbar, wenn jemand nachsehen könnte. Die ganze Gleichung ist in Gl. (5) in der Zeitung. Ich benutze Scikit Learn für alles im Moment (um das Schlüsselwort zu rechtfertigen: 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")
Meine Ergebnisse für den BIC sehen so aus:
Was nicht annähernd dem entspricht, was ich erwartet habe und auch keinen Sinn ergibt ... Ich habe mir die Gleichungen jetzt einige Zeit angesehen und finde meinen Fehler nicht weiter):
quelle
Antworten:
Anscheinend haben Sie einige Fehler in Ihren Formeln, die durch den Vergleich mit folgenden Faktoren festgestellt wurden:
1.
Hier gibt es drei Fehler in der Arbeit, in der vierten und fünften Zeile fehlt ein Faktor von d, die letzte Zeile ersetzt m für 1. Es sollte sein:
2.
Der const_term:
sollte sein:
3.
Die Varianzformel:
sollte ein Skalar sein:
4.
Verwenden Sie natürliche Protokolle anstelle Ihrer base10-Protokolle.
5.
Schließlich und vor allem hat der BIC, den Sie berechnen, ein umgekehrtes Vorzeichen gegenüber der regulären Definition. Sie möchten also maximieren statt minimieren
quelle
Dies ist im Grunde die Lösung von eyaler, mit ein paar Notizen. Ich habe es nur getippt, wenn jemand ein schnelles Kopieren / Einfügen wünschte:
Anmerkungen:
eyalers 4. Kommentar ist falsch. np.log ist bereits ein natürliches Protokoll, keine Änderung erforderlich
eyalers 5. Kommentar über Inverse ist korrekt. Im folgenden Code suchen Sie nach dem MAXIMUM - denken Sie daran, dass das Beispiel negative BIC-Nummern hat
Der Code lautet wie folgt (wiederum alle Kredite an Eyaler):
quelle