K-Means-Clustering für handschriftliche Ziffern

Beginner

This tutorial is from open-source community. Access the source code

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 StandardScaler skalieren 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.