From 342317207290fbf5a7439139889d680223cc58ea Mon Sep 17 00:00:00 2001 From: aaron Date: Thu, 18 Jun 2026 15:39:57 +0200 Subject: [PATCH] fix: add correct naming --- ..._measures.py => k_means_elbow_measures.py} | 0 NSL/aufgaben/src/uebung1_kmeans_fleet.py | 37 +++++++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) rename NSL/aufgaben/src/{uebung2_k_means_elbow_measures.py => k_means_elbow_measures.py} (100%) diff --git a/NSL/aufgaben/src/uebung2_k_means_elbow_measures.py b/NSL/aufgaben/src/k_means_elbow_measures.py similarity index 100% rename from NSL/aufgaben/src/uebung2_k_means_elbow_measures.py rename to NSL/aufgaben/src/k_means_elbow_measures.py diff --git a/NSL/aufgaben/src/uebung1_kmeans_fleet.py b/NSL/aufgaben/src/uebung1_kmeans_fleet.py index 64c9e1c..9925bb0 100644 --- a/NSL/aufgaben/src/uebung1_kmeans_fleet.py +++ b/NSL/aufgaben/src/uebung1_kmeans_fleet.py @@ -14,6 +14,7 @@ Umbau aus dem Lösungs-Notebook (lektion_1.ipynb): """ import matplotlib + matplotlib.use("Agg") # headless: nur in Dateien rendern from pathlib import Path @@ -29,7 +30,7 @@ from scipy.spatial.distance import cdist, pdist # EINSTELLUNGEN / PFADE # ========================================================= -BASE = Path(__file__).resolve().parent.parent # .../aufgaben +BASE = Path(__file__).resolve().parent.parent # .../aufgaben DATA = BASE / "data" / "data_delivery_fleet.tsv" PLOTS = BASE / "plots" PLOTS.mkdir(exist_ok=True) @@ -107,8 +108,10 @@ plt.close(fig) # ---- Within-Cluster Sum of Squares (Inertia) ---- Ks = range(1, 10) -inertia = [KMeans(n_clusters=k, n_init=10, random_state=RANDOM_SEED).fit(data).inertia_ - for k in Ks] +inertia = [ + KMeans(n_clusters=k, n_init=10, random_state=RANDOM_SEED).fit(data).inertia_ + for k in Ks +] fig, ax = plt.subplots() ax.bar(Ks, inertia) @@ -122,12 +125,14 @@ plt.close(fig) # ---- Percentage of Variance Explained ---- # TSS = WCSS + BSS -> Variance Explained = BSS / TSS ks = range(1, 10) -models = [KMeans(n_clusters=k, n_init=10, random_state=RANDOM_SEED).fit(data) for k in ks] +models = [ + KMeans(n_clusters=k, n_init=10, random_state=RANDOM_SEED).fit(data) for k in ks +] centroids = [m.cluster_centers_ for m in models] # Abstand jedes Punkts zum nächsten Zentrum -> WCSS pro k dist = [np.min(cdist(data, cent, "euclidean"), axis=1) for cent in centroids] -wcss = np.array([np.sum(d ** 2) for d in dist]) +wcss = np.array([np.sum(d**2) for d in dist]) tss = np.sum(pdist(data) ** 2) / data.shape[0] bss = tss - wcss @@ -143,11 +148,14 @@ plt.close(fig) # ---- Silhouette Score (erst ab k >= 2 definiert) ---- ks_sil = range(2, 10) -silhouette = [silhouette_score( - data, - KMeans(n_clusters=k, n_init=10, random_state=RANDOM_SEED).fit(data).labels_, - metric="euclidean") - for k in ks_sil] +silhouette = [ + silhouette_score( + data, + KMeans(n_clusters=k, n_init=10, random_state=RANDOM_SEED).fit(data).labels_, + metric="euclidean", + ) + for k in ks_sil +] fig, ax = plt.subplots() ax.plot(list(ks_sil), silhouette, marker="o") @@ -166,7 +174,9 @@ print(f"Bestes k nach Silhouette: {best_k}") # ========================================================= k_means_final = KMeans(n_clusters=best_k, n_init=10, random_state=RANDOM_SEED).fit(data) -save_kmeans(data, k_means_final, "07_final.png", title=f"Finales Clustering (k={best_k})") +save_kmeans( + data, k_means_final, "07_final.png", title=f"Finales Clustering (k={best_k})" +) print(f"Plots gespeichert in: {PLOTS}") @@ -177,6 +187,7 @@ print(f"Plots gespeichert in: {PLOTS}") # Im Lösungs-Notebook enthalten, gilt aber als veraltet (vgl. Chiang & Mirkin). # Silhouette/Elbow werden bevorzugt -> standardmässig deaktiviert (RUN_HARTIGAN). + def hartigan_k(data, threshold=12): """'Korrekte' Clusterzahl nach Hartigan: erstes k mit H <= threshold.""" inertia_list = np.zeros(len(data) + 1) @@ -186,7 +197,9 @@ def hartigan_k(data, threshold=12): kmn = KMeans(n_clusters=num + 1, n_init=10, random_state=RANDOM_SEED).fit(data) inertia_list[num + 1] = kmn.inertia_ if num > 0: - h_rule = ((float(inertia_list[num]) / inertia_list[num + 1]) - 1) * (len(data) - num - 1) + h_rule = ((float(inertia_list[num]) / inertia_list[num + 1]) - 1) * ( + len(data) - num - 1 + ) print(f"k={num}, H={h_rule:.2f}") num += 1 if h_rule > threshold: