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
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):
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):
DecisionTreeClassifier(random_state=1234) # train=1.0, test≈0.8296 → overfit
Falls
bfh_cas_pml/bank_data_prep.csvnicht zur Hand sind: als Fallback tut es jedertrain_test_splitauf 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)
- Grob: weiter Bereich, grobe Schritte, um die Region des Maximums zu
lokalisieren — z. B.
np.arange(0, 0.02, 0.001). - Fein: um das gefundene Maximum herum zoomen — z. B.
np.arange(0, 0.004, 0.0002). - 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
0startest 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 aufmax(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_decreasedirekt gegenX_testgetunt — 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 viacost_complexity_pruning_path()direkt eine sinnvolle Kandidatenliste statt manuellernp.arange-Rate-Erei — nur als Zeiger, nicht Teil der Aufgabe.