Einführung
In diesem Lab werden wir den K-Means-Clustering-Algorithmus mithilfe der scikit-learn-Bibliothek in Python untersuchen. Wir werden den Datensatz mit handschriftlichen Ziffern verwenden, der 64 Merkmale enthält, die ein 8x8-Bild einer Ziffer darstellen, und versuchen, die Bilder zusammen zu gruppieren, basierend auf der Ziffer, die sie darstellen. Wir werden die verschiedenen Initialisierungsmethoden für K-Means vergleichen und die Leistung der Clustering mit verschiedenen Metriken bewerten.
Tipps für die VM
Nachdem der VM-Start abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu nutzen.
Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund der Einschränkungen in Jupyter Notebook nicht automatisiert werden.
Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.
Lade den Datensatz
Wir beginnen, indem wir den Datensatz mit handschriftlichen Ziffern mithilfe der Funktion load_digits() von scikit-learn laden. Diese Funktion gibt die Merkmale und die Labels für den Datensatz zurück.
import numpy as np
from sklearn.datasets import load_digits
data, labels = load_digits(return_X_y=True)
(n_samples, n_features), n_digits = data.shape, np.unique(labels).size
Definiere das Evaluierungsbenchmark
Wir werden einen Benchmark definieren, um verschiedene Initialisierungsmethoden für K-Means zu vergleichen. Unser Benchmark wird:
- einen Pipeline erstellen, die die Daten mit einem
StandardScalerskalieren wird - die Pipeline-Anpassung trainieren und zeitlich messen
- die Leistung der Clustering, die über verschiedene Metriken erhalten wird, messen
from time import time
from sklearn import metrics
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
def bench_k_means(kmeans, name, data, labels):
"""Benchmark to evaluate the KMeans initialization methods.
Parameters
----------
kmeans : KMeans instance
A `KMeans` instance with the initialization already set.
name : str
Name given to the strategy. It will be used to show the results in a table.
data : ndarray of shape (n_samples, n_features)
The data to cluster.
labels : ndarray of shape (n_samples,)
The labels used to compute the clustering metrics which require some supervision.
"""
t0 = time()
estimator = make_pipeline(StandardScaler(), kmeans).fit(data)
fit_time = time() - t0
results = [name, fit_time, estimator[-1].inertia_]
## Define the metrics which require only the true labels and estimator labels
clustering_metrics = [
metrics.homogeneity_score,
metrics.completeness_score,
metrics.v_measure_score,
metrics.adjusted_rand_score,
metrics.adjusted_mutual_info_score,
]
results += [m(labels, estimator[-1].labels_) for m in clustering_metrics]
## The silhouette score requires the full dataset
results += [
metrics.silhouette_score(
data,
estimator[-1].labels_,
metric="euclidean",
sample_size=300,
)
]
## Show the results
formatter_result = (
"{:9s}\t{:.3f}s\t{:.0f}\t{:.3f}\t{:.3f}\t{:.3f}\t{:.3f}\t{:.3f}\t{:.3f}"
)
print(formatter_result.format(*results))
Führe den Benchmark aus
Wir werden drei Ansätze zum Initialisieren von K-Means vergleichen:
- eine Initialisierung mit
k-means++. Diese Methode ist stochastisch und wir werden die Initialisierung 4-mal ausführen; - eine zufällige Initialisierung. Diese Methode ist ebenfalls stochastisch und wir werden die Initialisierung 4-mal ausführen;
- eine Initialisierung basierend auf einer PCA-Projektion. Wir werden die Komponenten der PCA verwenden, um K-Means zu initialisieren. Diese Methode ist deterministisch und eine einzelne Initialisierung ist ausreichend.
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
print(82 * "_")
print("init\t\ttime\tinertia\thomo\tcompl\tv-meas\tARI\tAMI\tsilhouette")
kmeans = KMeans(init="k-means++", n_clusters=n_digits, n_init=4, random_state=0)
bench_k_means(kmeans=kmeans, name="k-means++", data=data, labels=labels)
kmeans = KMeans(init="random", n_clusters=n_digits, n_init=4, random_state=0)
bench_k_means(kmeans=kmeans, name="random", data=data, labels=labels)
pca = PCA(n_components=n_digits).fit(data)
kmeans = KMeans(init=pca.components_, n_clusters=n_digits, n_init=1)
bench_k_means(kmeans=kmeans, name="PCA-based", data=data, labels=labels)
print(82 * "_")
Visualisiere die Ergebnisse auf PCA-reduzierten Daten
Wir werden PCA verwenden, um den Datensatz auf 2 Dimensionen zu reduzieren und die Daten und Cluster in diesem neuen Raum zu plotten.
import matplotlib.pyplot as plt
reduced_data = PCA(n_components=2).fit_transform(data)
kmeans = KMeans(init="k-means++", n_clusters=n_digits, n_init=4)
kmeans.fit(reduced_data)
## Schrittweite des Gitters. Verringern, um die Qualität der VQ zu erhöhen.
h = 0.02 ## Punkt im Gitter [x_min, x_max]x[y_min, y_max].
## Plot die Entscheidungsgrenze. Dazu werden wir jeder
x_min, x_max = reduced_data[:, 0].min() - 1, reduced_data[:, 0].max() + 1
y_min, y_max = reduced_data[:, 1].min() - 1, reduced_data[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
## Erhalte Labels für jeden Punkt im Gitter. Verwende das zuletzt trainierte Modell.
Z = kmeans.predict(np.c_[xx.ravel(), yy.ravel()])
## Bringe das Ergebnis in einen Farbplot
Z = Z.reshape(xx.shape)
plt.figure(1)
plt.clf()
plt.imshow(
Z,
interpolation="nearest",
extent=(xx.min(), xx.max(), yy.min(), yy.max()),
cmap=plt.cm.Paired,
aspect="auto",
origin="lower",
)
plt.plot(reduced_data[:, 0], reduced_data[:, 1], "k.", markersize=2)
## Plot die Zentren als weißes X
centroids = kmeans.cluster_centers_
plt.scatter(
centroids[:, 0],
centroids[:, 1],
marker="x",
s=169,
linewidths=3,
color="w",
zorder=10,
)
plt.title(
"K-means clustering on the digits dataset (PCA-reduced data)\n"
"Centroids are marked with white cross"
)
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.xticks(())
plt.yticks(())
plt.show()
Zusammenfassung
In diesem Lab haben wir den K-Means-Clustering-Algorithmus untersucht und ihn auf den Datensatz mit handschriftlichen Ziffern angewendet. Wir haben verschiedene Initialisierungsmethoden verglichen und die Leistung der Clustering mit verschiedenen Metriken ausgewertet. Wir haben auch die Ergebnisse in einem 2-dimensionalen Raum mithilfe von PCA visualisiert.