# Source: content/notes/ml/unsupervised-learning.md
# Independent CPU example; use the curriculum environment.
# See /notes/ml/#example-environment or /notes/deep-learning/#example-environment.

import numpy as np
from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_blobs
from sklearn.metrics import adjusted_rand_score, silhouette_score
from sklearn.preprocessing import StandardScaler

X, truth = make_blobs(n_samples=180, centers=3, cluster_std=0.7, random_state=22)
Z = StandardScaler().fit_transform(X)
ward = AgglomerativeClustering(n_clusters=3, linkage="ward",
                               metric="euclidean", compute_distances=True)
labels = ward.fit_predict(Z)
assert labels.shape == truth.shape
assert ward.children_.shape == (len(Z) - 1, 2)
assert np.all(ward.distances_ >= 0)
print("Ward silhouette:", silhouette_score(Z, labels))
print("Ward synthetic ARI:", adjusted_rand_score(truth, labels))
for method in ["single", "complete", "average"]:
    other = AgglomerativeClustering(n_clusters=3, linkage=method, metric="euclidean")
    result = other.fit_predict(Z)
    assert len(np.unique(result)) == 3
    print(method, "ARI", adjusted_rand_score(truth, result))
# Dendrogram coordinates are inspectable without opening a plotting window.
tree = linkage(Z, method="ward")
diagram = dendrogram(tree, no_plot=True)
assert len(diagram["leaves"]) == len(Z)
print("Last three merges [left, right, height, count]:\n", tree[-3:])
