C.1 Unsupervised machine learning

C.1 Unsupervised machine learning#

mode = "svg"

import matplotlib

font = {'family' : 'Dejavu Sans',
        'weight' : 'normal',
        'size'   : 20}

matplotlib.rc('font', **font)

import matplotlib
from matplotlib import pyplot as plt
from graspologic.simulations import sbm
from graspologic.embed import AdjacencySpectralEmbed as ASE
import numpy as np

ns = [50, 40, 30]
B = [[0.6, 0.2, 0.2],
     [0.2, 0.6, 0.2],
     [0.2, 0.2, 0.6]]

np.random.seed(1234)
A = sbm(n=ns, p = B)

# the true community labels
z = [0 for i in range(0,ns[0])] + [1 for i in range(0, ns[1])] + [2 for i in range(0, ns[2])]
Xhat = ASE(n_components=3).fit(A).latent_left_
from pandas import DataFrame
import seaborn as sns
import matplotlib.pyplot as plt

data = DataFrame({"Dimension 2" : Xhat[:,1], "Dimension 3" : Xhat[:,2]})
palette = {"0" : "blue", "1": "green", "2": "red"}
fig, ax = plt.subplots(1, 1, figsize=(6, 4))
sns.scatterplot(data=data, x="Dimension 2", y="Dimension 3", color="gray", ax=ax)
ax.set_title("Estimates of latent positions");
../../_images/6a24eca5d2364aab6638ddf808f0b9f8c0cc710708f6645e59055ec3acc46dd8.png
centers = np.array([[.5, .5], [-0.05, 0.05], [-0.05, -0.05]])
datcenters = DataFrame({"Dimension 2": centers[:,0], "Dimension 3": centers[:,1], "Cluster": ["0", "1","2"]})
from scipy.spatial import distance_matrix
distances = distance_matrix(Xhat[:,1:3], centers)
assignment = np.argmin(distances, axis=1)

data["Closest Center"] = assignment.astype(str)
centers = np.array([np.mean(Xhat[assignment == k,1:3], axis=0) for k in range(0, 3)])

datcenters = DataFrame({"Dimension 2": centers[:,0], "Dimension 3": centers[:,1], "Cluster": ["0", "1","2"]})
distances = distance_matrix(Xhat[:,1:3], centers)
assignment = np.argmin(distances, axis=1)
centers_new = np.array([np.mean(Xhat[assignment == k,1:3], axis=0) for k in range(0, 3)])

data["Closest Center"] = assignment.astype(str)
import os

fig, axs = plt.subplots(1, 3, figsize=(20, 6))
color_kwarg = [{"color": "gray"}, {"hue": "Closest Center"}, {"hue": "Closest Center"}]
cdat = [centers, centers, centers_new]
titles = ["(A) Centers from previous iteration", "(B) Temporary cluster assignments", "(C) Update centers"]

for i, ax in enumerate(axs.flat):
    sns.scatterplot(data=data, x="Dimension 2", y="Dimension 3", ax=ax, **color_kwarg[i],
                    palette=palette, legend=False)
    datcenters = DataFrame({"Dimension 2": cdat[i][:,0], "Dimension 3": cdat[i][:,1], "Cluster": ["0", "1","2"]})
    sns.scatterplot(data=datcenters, x="Dimension 2", y="Dimension 3", hue="Cluster",
                    palette=palette, ax=ax, s=200)
    ax.set_title(titles[i])
    if i != 2:
        ax.get_legend().remove()

fig.tight_layout()

os.makedirs("Figures", exist_ok=True)
fname = "kmeans_process"
if mode != "png":
    os.makedirs(f"Figures/{mode:s}", exist_ok=True)
    fig.savefig(f"Figures/{mode:s}/{fname:s}.{mode:s}")

os.makedirs("Figures/png", exist_ok=True)
fig.savefig(f"Figures/png/{fname:s}.png")
/tmp/ipykernel_2112/2519076243.py:9: UserWarning: Ignoring `palette` because no `hue` variable has been assigned.
  sns.scatterplot(data=data, x="Dimension 2", y="Dimension 3", ax=ax, **color_kwarg[i],
../../_images/8148943cdc4883521d5c3f6c201daa2a4ef8bd7ed56aab08908953cc731936f3.png
from sklearn.cluster import KMeans

labels_kmeans = KMeans(n_clusters = 3, random_state=1234).fit_predict(Xhat)
from graspologic.plot import pairplot

fig = pairplot(Xhat, labels=labels_kmeans, title="Pairplot of embedding of $A$", legend_name="Predicted Cluster")

fname = "kmeans_out"
if mode != "png":
    fig.savefig(f"Figures/{mode:s}/{fname:s}.{mode:s}")

fig.savefig(f"Figures/png/{fname:s}.png")
../../_images/f15ea55e44ab016a88aba96a4a785afabfa56bbedda4159ce446043aee0cdb75.png
from sklearn.metrics import confusion_matrix
# compute the confusion matrix between the true labels z
# and the predicted labels labels_kmeans
cf_matrix = confusion_matrix(z, labels_kmeans)
cfm_norm = cf_matrix/cf_matrix.sum(axis=1)[:,None]
from graphbook_code import cmaps

fig, axs = plt.subplots(1,2, figsize=(12,5))

sns.heatmap(cf_matrix, cmap=cmaps["sequential"], ax=axs[0], annot=True, cbar_kws={"label": "Count", "shrink": 0.6})
axs[0].set_title("(A) Confusion matrix")
axs[0].set_ylabel("True Label")
axs[0].set_xlabel("Predicted Label")

sns.heatmap(cfm_norm, cmap=cmaps["sequential"], ax=axs[1], annot=True, cbar_kws={"label": "Fraction", "shrink": 0.6})
axs[1].set_title("(B) Normalized confusion matrix")
axs[1].set_ylabel("True Label")
axs[1].set_xlabel("Predicted Label")

fig.tight_layout()

fname = "kmeans_cfmtx"
if mode != "png":
    fig.savefig(f"Figures/{mode:s}/{fname:s}.{mode:s}")

fig.savefig(f"Figures/png/{fname:s}.png")
../../_images/7b8fe42cccbf86e305d5078b3d58657e74a45beae2c0659bbff409ec79231f7f.png
from sklearn.metrics import adjusted_rand_score

ari_kmeans = adjusted_rand_score(z, labels_kmeans)
print("ARI(predicted communities, true communities) = {}".format(ari_kmeans))
ARI(predicted communities, true communities) = 1.0