# CAS PML – Unsupervised Learning: Clustering-Aufgaben > Modul: CAS Practical Machine Learning – Unsupervised Learning (Dehmer) > Inhalt: zwei Clustering-Übungen rund um K-Means und die Wahl der Clusterzahl $k$ ## Projektstruktur ``` . ├── data/ │ └── data_delivery_fleet.tsv # Übung 1 (tab-separiert) ├── plots/ # generierte PNGs (headless) ├── src/ │ ├── uebung1_kmeans_fleet.py # Übung 1: k-Means auf Fleet-Daten │ └── k_means2_elbow_measures.py # Übung 2: Elbow & Gütemasse (synthetisch) ├── devenv.nix └── README.md ``` > Tipp für konsistente Namen: `k_means2_elbow_measures.py` ggf. zu `uebung2_elbow_measures.py` umbenennen. ## Setup & Ausführen In der devenv-Shell: ``` python src/uebung1_kmeans_fleet.py python src/k_means2_elbow_measures.py ``` Beide Skripte laufen **headless**: Plots werden als PNG nach `plots/` geschrieben (kein `plt.show()`, da in der Shell kein Display vorhanden ist – Agg-Backend). ## Gütemasse zur Wahl von $k$ (gemeinsame Referenz) - Inertia / WCSS – Summe der quadrierten Abstände zum Zentroid; sinkt monoton mit $k$, daher nur "Knick" (Elbow), kein echtes Optimum $$ \text{WCSS} = \sum_{i=1}^{k} \sum_{x \in P_i} \lVert x - \mu_i \rVert^2 $$ - Erklärte Varianz – Anteil der Between-Cluster-Varianz an der Gesamtvarianz; nutzt $\text{TSS} = \text{WCSS} + \text{BSS}$, höher = besser (ideal 100 %) $$ \text{Variance Explained} = \frac{\text{BSS}}{\text{TSS}} \cdot 100\,\% $$ - Silhouette-Score – $a_i$ = mittlere Intra-, $b_i$ = mittlere nächste Inter-Cluster-Distanz; Bereich $[-1, 1]$, höher = besser $$ s_i = \frac{b_i - a_i}{\max(a_i, b_i)} $$ - Davies-Bouldin (nur Übung 2) – mittleres Verhältnis Streuung/Abstand; niedriger = besser (Achtung: umgekehrt zur Silhouette) $$ DB = \frac{1}{k} \sum_{i=1}^{k} \max_{j \neq i} \frac{\sigma_i + \sigma_j}{d(c_i, c_j)} $$ --- ## Übung 1 — k-Means: Delivery Fleet Aufgabenstellung (Skript): Fleet-Daten von Lieferfahrer:innen clustern. 1. Datensatz aus tab-separiertem File laden (Pandas) 2. Daten visualisieren und eine sinnvolle Clusterzahl visuell *und* systematisch finden 3. Daten clustern Datensatz `data_delivery_fleet.tsv` (3 Spalten): - `Driver_ID` – ID der Fahrer:in - `Distance_Feature` – mittlere gefahrene Meilen pro Tag - `Speeding_Feature` – % der Zeit über dem Tempolimit (>5 mph) Geclustert wird auf `Distance_Feature` × `Speeding_Feature`. Ablauf von `uebung1_kmeans_fleet.py` (erzeugt PNGs in `plots/`): 1. Rohdaten-Scatter (`01_rohdaten.png`) 2. K-Means mit frei gewähltem $k=4$ (`02_kmeans_k4.png`) 3. Sweep $k = 1 \dots 8$ als Übersichts-Grid (`03_kmeans_sweep_k1-8.png`) 4. $k$ bestimmen über Inertia/Elbow (`04`), erklärte Varianz (`05`) und Silhouette (`06`) 5. finales Modell mit bestem $k$ (`07_final.png`) Verständnisfragen: - [ ] Legen Elbow, erklärte Varianz und Silhouette dasselbe $k$ nahe? - [ ] Sollte man die zwei Features vor dem Clustern skalieren (Meilen vs. %, sehr unterschiedliche Spannweiten)? - [ ] Die Hartigan-Regel ist im Lösungs-Notebook enthalten, gilt aber als veraltet – warum bevorzugt man Silhouette/Elbow? > Anpassungen ggü. dem Notebook: `.as_matrix()` → `.to_numpy()` (in aktuellem Pandas entfernt); `plt.show()` → `savefig` (headless); die Hartigan-Funktion ist als optionaler Legacy-Block enthalten (`RUN_HARTIGAN = False`). --- ## Übung 2 — Elbow-Methode & Gütemasse (synthetisch) Ziel: auf synthetischen 2D-Daten (drei Gauss-Blobs) K-Means für verschiedene $k$ laufen lassen und die "richtige" Clusterzahl systematisch über Gütemasse bestimmen – statt nur visuell zu schätzen. Ablauf von `k_means2_elbow_measures.py` (erzeugt einen 4-Panel-Plot): 1. Daten generieren: je 100 Punkte um $(0,0)$, $(6,6)$, $(0,6)$ (Seed fix → reproduzierbar) 2. Für $k = 1 \dots 8$ K-Means fitten und sammeln: Inertia, Silhouette, Davies-Bouldin (Letztere ab $k \geq 2$) 3. Bestes $k$ wählen (vereinfacht: maximaler Silhouette-Score) 4. Finales Modell fitten → Labels + Zentren 5. Visualisierung: Rohdaten | Elbow (Inertia) | Silhouette | finales Clustering Verständnisfragen: - [ ] Warum nimmt man zur $k$-Wahl die Silhouette und nicht die Inertia? - [ ] Warum sind die Cluster im Ergebnis-Plot farblich klar getrennt? - [ ] Warum können verschiedene Runs unterschiedliche Ergebnisse liefern? - [ ] Ist das gefundene $k$ immer "korrekt"? Experimente (zum Ausprobieren): - [ ] Zentren näher zusammenlegen (Daten stärker überlappen) → wie verändern sich Elbow und Scores? - [ ] Davies-Bouldin statt Silhouette als $k$-Kriterium (dann `argmin` statt `argmax`!) → dasselbe $k$? - [ ] `n_init` reduzieren / Seed variieren → wie stabil ist das Ergebnis? > Zu den Verständnisfragen stehen im Skript kurze Musterantworten als Kommentar.