<jupyter_start><jupyter_text>First, we generate some sample data.<jupyter_code>n_samples = 1500
random_state = 170
X, _ = make_blobs(n_samples=n_samples,
                  centers=4,
                  random_state=random_state)

mins = np.amin(X, axis=0)
maxs = np.amax(X, axis=0)<jupyter_output><empty_output><jupyter_text>Then we set the number of clusters k.<jupyter_code>k = 2<jupyter_output><empty_output><jupyter_text>Define Helper function for plotting<jupyter_code>colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, k)]
old_clusters = []

def plot_kmeans(cluster_coords, ind):
    plt.figure(figsize=(10, 7))
    plt.title("k = {}, iteration = {}".format(k, iteration))
    
    # Data points
    plt.scatter(X[:, 0],
                X[:, 1],
                c=list(map(lambda x: colors[x[0]], ind)),
                s=2)
    
    # Current cluster center
    plt.scatter(cluster_coords[:, 0],
                cluster_coords[:, 1],
                marker="o",
                edgecolors='k',
                facecolors=colors,
                s=150)

    # Old cluster centers
    for old_cluster in old_clusters:
        plt.scatter(old_cluster[:, 0],
                    old_cluster[:, 1],
                    marker="o",
                    edgecolors='k',
                    facecolors=colors,
                    alpha=0.3,
                    s=100)
    # Lines
    for i in range(len(cluster_coords)):
        xs = [old_cluster[i, 0] for old_cluster in old_clusters] + [cluster_coords[i, 0]]
        ys = [old_cluster[i, 1] for old_cluster in old_clusters] + [cluster_coords[i, 1]]
        plt.plot(xs, ys, color=colors[i], alpha=0.3)

    plt.xlim(mins[0], maxs[0])
    plt.ylim(mins[1], maxs[1])
    plt.show()<jupyter_output><empty_output><jupyter_text>Initialize random cluster centers<jupyter_code>cluster_coords = np.random.uniform(low=mins,
                                   high=maxs,
                                   size=(k, 2))

tree = KDTree(cluster_coords)
dist, ind = tree.query(X, k=1)<jupyter_output><empty_output><jupyter_text>Assign data points to nearest cluster center and update cluster centers<jupyter_code>max_iterations = 30
iteration = 0
has_converged = False

plot_kmeans(cluster_coords, ind)

while not has_converged and iteration < max_iterations:
    iteration += 1
    old_clusters.append(np.copy(cluster_coords))

    # Assign 
    tree = KDTree(cluster_coords)
    dist, ind = tree.query(X, k=1)

    # Update cluster centers
    idx = ind.reshape(X.shape[0])
    for i in range(k):
        cluster_coords[i] = X[idx==i,:].mean(axis=0)

    plot_kmeans(cluster_coords, ind)

    norm = np.linalg.norm(cluster_coords - old_clusters[-1])
    print(norm)
    has_converged = math.isclose(norm, 0.0)
from sklearn.cluster import KMeans
import sklearn
kmeans_loss = []
sil_score = []

ks = range(2, 15, 1)

for k in ks:
    kmeans = KMeans(n_clusters=k).fit(X)
    kmeans_loss.append(kmeans.inertia_)
    sil_score.append(sklearn.metrics.silhouette_score(X, kmeans.labels_))

plt.figure()
plt.plot(ks, kmeans_loss)
plt.xlabel("k")
plt.ylabel("k-Means cost function")
plt.grid()
plt.show()

plt.figure()
plt.plot(ks, sil_score)
plt.xlabel("k")
plt.ylabel("Silhouette coefficient")
plt.grid()
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1296014602981442, 'fraction_numerical': 0.017645269242470337, 'mean_word_length': 2.8546307151230947, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '38650', 'license': 'MIT', 'n_tokens_mistral': 1243, 'n_tokens_neox': 1161, 'n_words': 222, 'path': 'clustering/lloyd_kmeans_demo.ipynb', 'repo_name': 'mie-lab/teaching_examples', 'size': '3287'}