不同度量的聚集聚類?

演示不同度量對分層聚類的影響。

該示例的設計表明了選擇不同度量標準的效果。它應用于波形,可視為高維向量。實際上,度量之間的差異通常在高維(特別是歐幾里得度量和城市街道度量)中更為明顯。

我們從三組波形中生成數據。兩種波形(波形1和波形2)是成比例的。余弦距離不受數據縮放的影響,因此無法區分這兩種波形。因此,即使沒有噪聲,使用這個距離的聚類也不會分離出波形1和2。

我們在這些波形中加入觀測噪聲。我們產生非常稀疏的噪聲:只有6%的時間點含有噪聲。因此,這種噪聲的L1范數(即“街道”距離)比它的L2范數(“歐幾里得”距離)要小得多。這可以在類間距離矩陣上看到:描述類的擴展的對角線上的值對于歐氏距離要比街道距離大得多。當我們將聚類應用于數據時,我們發現聚類反映了距離矩陣中的內容。實際上,對于歐氏距離,由于噪聲的影響,類之間是不分離的,因此聚類不分離波形。對于街道距離,分離良好,波形類恢復。最后,余弦距離在所有波形1和2都不分開,因此聚類將它們放在同一簇中。

# 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(01, 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([0011])
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=(54.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([0011])
    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()

腳本的總運行時間:(0分1.504秒)

Download Python source code:plot_agglomerative_clustering_metrics.py

Download Jupyter notebook:plot_agglomerative_clustering_metrics.ipynb