Demonstriert die Wirkung verschiedener Metriken auf das hierarchische Clustering.

Das Beispiel wurde entwickelt, um die Auswirkungen der Wahl verschiedener Metriken zu zeigen. Es wird auf Wellenformen angewendet, die als hochdimensionaler Vektor angesehen werden können. Tatsächlich ist der Unterschied zwischen den Metriken in der Regel in der hohen Dimension (insbesondere bei Euklidischen und Stadtblöcken) stärker ausgeprägt.

Wir generieren Daten aus drei Gruppen von Wellenformen. Zwei der Wellenformen (Wellenform 1 und Wellenform 2) sind zueinander proportional. Der Kosinusabstand ist gegenüber einer Skalierung der Daten invariant, daher kann er diese beiden Wellenformen nicht unterscheiden. Auch ohne Rauschen trennt das Clustering mit diesem Abstand die Wellenformen 1 und 2.

Wir fügen diesen Wellenformen Beobachtungsrauschen hinzu. Wir erzeugen sehr wenig Rauschen: Nur 6% der Zeitpunkte enthalten Rauschen. Als Ergebnis ist die l1-Norm dieses Rauschens (dh der „Stadtblock“-Abstand) viel kleiner als die l2-Norm („euklidischer“ Abstand). Dies ist an den Interklassen-Distanzmatrizen zu erkennen: Die Werte auf der Diagonalen, die die Streuung der Klasse charakterisieren, sind für die euklidische Distanz viel größer als für die Cityblock-Distanz.

Wenn wir Clustering auf die Daten anwenden, stellen wir fest, dass das Clustering widerspiegelt, was sich in den Distanzmatrizen befand. Tatsächlich sind die Klassen für den euklidischen Abstand wegen des Rauschens schlecht getrennt, und somit trennt die Clusterbildung die Wellenformen nicht. Für den Cityblock-Abstand ist die Trennung gut und die Wellenformklassen werden wiederhergestellt. Schließlich trennt sich der Kosinusabstand überhaupt nicht von den Wellenformen 1 und 2, daher bringt die Clusterbildung sie in denselben Cluster.

  • Grundwahrheit
  • Kosinusabstände zwischen den Klassen
  • Euklidische Abstände zwischen den Klassen
  • Abstände zwischen den Klassenblöcken
  • Agglomeratives Clustering (Affinität = Kosinus)
  • Agglomeratives Clustering (Affinität=euklidisch)
  • Agglomeratives Clustering (Affinität=Stadtblock)
# Author: Gael Varoquaux
# License: BSD 3-Clause or CC-0

import matplotlib.pyplot as plt
import numpy as np

from sklearn.cluster import AgglomerativeClustering
from sklearn.metrics import pairwise_distances

np.random.seed(0)

# Generate waveform data
n_features = 2000
t = np.pi * np.linspace(0, 1, n_features)


def sqr(x):
    return np.sign(np.cos(x))

X = list()
y = list()
for i, (phi, a) in enumerate([(.5, .15), (.5, .6), (.3, .2)]):
    for _ in range(30):
        phase_noise = .01 * np.random.normal()
        amplitude_noise = .04 * np.random.normal()
        additional_noise = 1 - 2 * np.random.rand(n_features)
        # Make the noise sparse
        additional_noise[np.abs(additional_noise) < .997] = 0

        X.append(12 * ((a + amplitude_noise)
                 * (sqr(6 * (t + phi + phase_noise)))
                 + additional_noise))
        y.append(i)

X = np.array(X)
y = np.array(y)

n_clusters = 3

labels = ('Waveform 1', 'Waveform 2', 'Waveform 3')

# Plot the ground-truth labelling
plt.figure()
plt.axes([0, 0, 1, 1])
for l, c, n in zip(range(n_clusters), 'rgb',
                   labels):
    lines = plt.plot(X[y == l].T, c=c, alpha=.5)
    lines[0].set_label(n)

plt.legend(loc='best')

plt.axis('tight')
plt.axis('off')
plt.suptitle("Ground truth", size=20)


# Plot the distances
for index, metric in enumerate(["cosine", "euclidean", "cityblock"]):
    avg_dist = np.zeros((n_clusters, n_clusters))
    plt.figure(figsize=(5, 4.5))
    for i in range(n_clusters):
        for j in range(n_clusters):
            avg_dist[i, j] = pairwise_distances(X[y == i], X[y == j],
                                                metric=metric).mean()
    avg_dist /= avg_dist.max()
    for i in range(n_clusters):
        for j in range(n_clusters):
            plt.text(i, j, '%5.3f' % avg_dist[i, j],
                     verticalalignment='center',
                     horizontalalignment='center')

    plt.imshow(avg_dist, interpolation='nearest', cmap=plt.cm.gnuplot2,
               vmin=0)
    plt.xticks(range(n_clusters), labels, rotation=45)
    plt.yticks(range(n_clusters), labels)
    plt.colorbar()
    plt.suptitle("Interclass %s distances" % metric, size=18)
    plt.tight_layout()


# Plot clustering results
for index, metric in enumerate(["cosine", "euclidean", "cityblock"]):
    model = AgglomerativeClustering(n_clusters=n_clusters,
                                    linkage="average", affinity=metric)
    model.fit(X)
    plt.figure()
    plt.axes([0, 0, 1, 1])
    for l, c in zip(np.arange(model.n_clusters), 'rgbk'):
        plt.plot(X[model.labels_ == l].T, c=c, alpha=.5)
    plt.axis('tight')
    plt.axis('off')
    plt.suptitle("AgglomerativeClustering(affinity=%s)" % metric, size=20)


plt.show()

Gesamtlaufzeit des Skripts: ( 0 Minuten 1.761 Sekunden)

Startordner

Download Python source code: plot_agglomerative_clustering_metrics.py

Download Jupyter notebook: plot_agglomerative_clustering_metrics.ipynb