This repository has been archived on 2026-06-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cas-pml/NSL/aufgaben/README.md
T

4.8 KiB
Raw Blame History

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.