feature(workshop): add workshop5 decision tree tuning
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# Workshop 05 — Decision Tree Classifier: `min_impurity_decrease` Tuning
|
||||
|
||||
## Aufgabe
|
||||
|
||||
Untersuchen, wie verschiedene Werte von `min_impurity_decrease` beim
|
||||
`DecisionTreeClassifier` die erreichbare **Test-Accuracy** beeinflussen.
|
||||
|
||||
- Wertebereich **schrittweise eingrenzen** (grob → fein).
|
||||
- Resultate darstellen:
|
||||
- grafisch als **Liniendiagramm** (Parameter vs. Accuracy),
|
||||
- in der **Konsole**: bester Score + zugehöriger Parameterwert.
|
||||
|
||||
Hinweis aus den Folien: `range()` liefert Ganzzahlen, `np.arange()` liefert
|
||||
Gleitkommawerte. `min_impurity_decrease` ist ein Float → `np.arange`.
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
devenv shell # python + venv (pandas, numpy, sklearn, matplotlib, seaborn)
|
||||
```
|
||||
|
||||
Datengrundlage = vorbereiteter Bank-Datensatz aus W4. Geladen über das
|
||||
kursinterne Modul (muss auf dem `PYTHONPATH` / im Projektordner liegen):
|
||||
|
||||
```python
|
||||
from bfh_cas_pml import prep_data
|
||||
X_train, X_test, y_train, y_test = prep_data('bank_data_prep.csv', 'y', seed=1234)
|
||||
```
|
||||
|
||||
Baseline zum Abgleich (voll ausgewachsener Baum):
|
||||
|
||||
```python
|
||||
DecisionTreeClassifier(random_state=1234) # train=1.0, test≈0.8296 → overfit
|
||||
```
|
||||
|
||||
> Falls `bfh_cas_pml` / `bank_data_prep.csv` nicht zur Hand sind: als Fallback
|
||||
> tut es jeder `train_test_split` auf einem sklearn-Datensatz — die Mechanik
|
||||
> des Sweeps bleibt identisch.
|
||||
|
||||
## Theorie — was `min_impurity_decrease` tut
|
||||
|
||||
Ein Split wird **nur** ausgeführt, wenn er die (gewichtete, auf den ganzen
|
||||
Baum normierte) Impurity um mindestens diesen Wert senkt:
|
||||
|
||||
```
|
||||
ΔI_norm = (N_node / N_total) * ( I_parent
|
||||
- (N_left/N_node) * I_left
|
||||
- (N_right/N_node) * I_right )
|
||||
```
|
||||
|
||||
Kernpunkte fürs Verständnis:
|
||||
|
||||
- Es ist eine **Pre-Pruning**-Schwelle: schwache Splits werden gar nicht erst
|
||||
gemacht → der Baum bleibt kleiner → weniger Overfitting.
|
||||
- Der Wert ist mit dem **Anteil der Beobachtungen im Knoten** gewichtet
|
||||
(`N_node / N_total`). Tiefe Knoten betreffen wenige Samples → ihr ΔI_norm ist
|
||||
winzig. Darum liegen sinnvolle Schwellen im Bereich **~1e-4 bis ~1e-2**, nicht
|
||||
bei 0.1+. (Vgl. das Folien-Rechenbeispiel: ein *guter* Split nahe der Wurzel
|
||||
ergab 0.0421.)
|
||||
- `=0` → kein Pruning → Baseline-Baum (overfit).
|
||||
|
||||
## Vorgehen — Eingrenzung (der eigentliche Lerninhalt)
|
||||
|
||||
1. **Grob**: weiter Bereich, grobe Schritte, um die Region des Maximums zu
|
||||
lokalisieren — z. B. `np.arange(0, 0.02, 0.001)`.
|
||||
2. **Fein**: um das gefundene Maximum herum zoomen — z. B.
|
||||
`np.arange(0, 0.004, 0.0002)`.
|
||||
3. Wiederholen, bis Lage/Wert des Peaks stabil sind.
|
||||
|
||||
Jede Iteration ist ein eigener Sweep (gleicher Loop, anderer `np.arange`).
|
||||
Im README/Notes die drei (o. ä.) Ranges + jeweils Peak dokumentieren — das
|
||||
*ist* die geforderte „schrittweise Eingrenzung“.
|
||||
|
||||
## Erwartetes Verhalten (Sanity-Check)
|
||||
|
||||
- Bei `0` startest du auf der Baseline (~0.83).
|
||||
- Mit steigendem Wert zunächst Plateau / leichter Bump (Rausch-Splits werden
|
||||
entfernt), dann **Kante nach unten**, sobald nützliche Splits wegfallen.
|
||||
- Im Extrem degeneriert der Baum zum Stumpf → Accuracy = Mehrheitsklasse.
|
||||
Der Bank-Datensatz wurde in W4 ~balanciert resampled → Floor liegt nahe
|
||||
~0.5. Wenn deine Kurve dort hin abstürzt, ist das korrekt, kein Bug.
|
||||
|
||||
## Deliverables
|
||||
|
||||
- [ ] Loop über `np.arange`-Range, `set_params(min_impurity_decrease=p)`,
|
||||
`fit`, `score(X_test, y_test)`, sammeln.
|
||||
- [ ] `sns.lineplot(x=params, y=scores)` + Scatter-Marker auf `max(scores)`,
|
||||
Achsen beschriftet (`min_impurity_decrease` / `accuracy`).
|
||||
- [ ] Konsole: `best score` + zugehöriger Parameterwert.
|
||||
- [ ] Mind. 2 Eingrenzungs-Stufen (grob + fein) dokumentiert.
|
||||
|
||||
## Caveats / Vertiefung (optional)
|
||||
|
||||
- **Optimistic bias** (wie in W4): hier wird `min_impurity_decrease` direkt
|
||||
gegen `X_test` getunt — derselbe Trap wie die manuelle Grid-Search ohne CV.
|
||||
Der gemeldete „beste“ Score ist dadurch optimistisch verzerrt. Die Folien
|
||||
machen es so; fürs Deliverable also bewusst übernehmen, aber als Deviation
|
||||
notieren. Sauber wäre Tuning auf einem Validation-Split bzw. `GridSearchCV`.
|
||||
- **Verwandter Faden, falls Zeit/Interesse**: `ccp_alpha` (Cost-Complexity /
|
||||
Minimal-Cost-Complexity-Pruning) ist sklearns „eigentlicher“ Pruning-Knopf
|
||||
und liefert via `cost_complexity_pruning_path()` direkt eine sinnvolle
|
||||
Kandidatenliste statt manueller `np.arange`-Rate-Erei — nur als Zeiger, nicht
|
||||
Teil der Aufgabe.
|
||||
Reference in New Issue
Block a user