<jupyter_start><jupyter_text>Agglomerative clustering with different metrics===============================================Demonstrates the effect of different metrics on the hierarchical clustering.The example is engineered to show the effect of the choice of differentmetrics. It is applied to waveforms, which can be seen ashigh-dimensional vector. Indeed, the difference between metrics isusually more pronounced in high dimension (in particular for euclideanand cityblock).We generate data from three groups of waveforms. Two of the waveforms(waveform 1 and waveform 2) are proportional one to the other. The cosinedistance is invariant to a scaling of the data, as a result, it cannotdistinguish these two waveforms. Thus even with no noise, clusteringusing this distance will not separate out waveform 1 and 2.We add observation noise to these waveforms. We generate very sparsenoise: only 6% of the time points contain noise. As a result, thel1 norm of this noise (ie "cityblock" distance) is much smaller than it'sl2 norm ("euclidean" distance). This can be seen on the inter-classdistance matrices: the values on the diagonal, that characterize thespread of the class, are much bigger for the Euclidean distance than forthe cityblock distance.When we apply clustering to the data, we find that the clusteringreflects what was in the distance matrices. Indeed, for the Euclideandistance, the classes are ill-separated because of the noise, and thusthe clustering does not separate the waveforms. For the cityblockdistance, the separation is good and the waveform classes are recovered.Finally, the cosine distance does not separate at all waveform 1 and 2,thus the clustering puts them in the same cluster.<jupyter_code># Author: <NAME>
# 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()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11824623560673161, 'fraction_numerical': 0.01550044286979628, 'mean_word_length': 3.4546351084812623, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '79014', 'license': 'Apache-2.0', 'n_tokens_mistral': 1500, 'n_tokens_neox': 1353, 'n_words': 468, 'path': '01 Machine Learning/scikit_examples_jupyter/cluster/plot_agglomerative_clustering_metrics.ipynb', 'repo_name': 'alphaolomi/colab', 'size': '4524'}