7.4 KiB
7.4 KiB
Notizen SL Lektion 3
Thema: Feature Engineering Datum: 28.05.2026 Dozentin: Violeta Vogel
Recap
- Sandbox Prinzip
- Daten werden immer als Kopie bearbeitet (
data = ori_data.copy()), damit Transformationsschritte sich nicht gegenseitig beeinflussen und die Ausgangsdaten nicht neu geladen werden müssen
- Daten werden immer als Kopie bearbeitet (
- hohe Kardinalität
- bezeichnet eine hohe Anzahl an eindeutigen Werten
Arten von Variablen
- Numerische Variablen
- messbare Zahlen
- Stetig (kontinuierlich)
- Können jeden beliebigen Wert annehmen und unendlich fein unterteilt werden.
- Beispiele: Körpergröße, Gewicht, Temperatur, Zeit
- Diskret
- Können nur in bestimmten, meist ganzzahligen Schritten gezählt werden.
- Beispiele: Anzahl der Kinder, Autoverkäufe, Besucher eines Konzerts
- Kategoriale Variablen
- Gruppen oder Eigenschaften
- Diese Variablen teilen Beobachtungen in verschiedene Gruppen oder Kategorien ein. Sie geben eine Eigenschaft an.
- Nominal
- Die Kategorien haben keine logische Reihenfolge.
- Beispiele: Geschlecht, Haarfarbe, Augenfarbe, Postleitzahlen.
- Ordinal
- Die Kategorien haben eine natürliche Rangordnung oder Reihenfolge.
- Beispiele: Zufriedenheitsgrade (sehr zufrieden, zufrieden, unzufrieden), Schulnoten (1 bis 6)
Transformationen: Numerisieren Kategorialer Variablen
- Numerisieren
- Numerische Darstellung einer Variablen, damit ML damit rechnen kann
- Verschiedene Methoden
- Faktorisieren
- Ordinal Encodieren
- Nominal Encodieren
- Faustregel: nominal → One-Hot, ordinal → Ordinal Encoding, reines Label ohne Bedeutung → Faktorisieren
Faktorisieren
- Jeder Kategorie einer kategorialen Variablen wird ein Integer-Wert zugeordnet, beginnend bei 0
data.job = pd.factorize(data.job)[0]pd.factorize()gibt ein Tupel zurück:[0]→ faktorisierte Werte (numpy.ndarray), beginnend bei 0[1]→ Index mit der Zuordnung der Werte zu den Ausgangswerten
- Werte werden per Default in Reihenfolge des Auftretens im Dataset vergeben (nicht sortiert)
- mit
sort=Truewerden sie lexikografisch (bezogen auf die Ausgangswerte) vergeben - Schwäche: die numerische Zuordnung ist im Grunde willkürlich (Reihenfolge im Datensatz) → es wird eine Ordnung impliziert, die inhaltlich keine ist. Taugt sauber nur für nominale Daten, wo die Zahl reines Label ist.
Ordinal Encodieren
- Behebt die Faktorisier-Schwäche: bei einer tatsächlich ordinalen Variable werden die Zahlen gezielt der natürlichen Rangordnung zugeordnet
- Beispiel
education:illiterate → 0unknown → 0basic.4y → 1basic.6y → 2basic.9y → 3professional.course → 4high.school → 5university.degree → 6
- Umsetzung über
.replace()mit einem (verschachtelten) Dictionary, das vorher definiert wird:data.replace(replace_nums, inplace=True) - Hinweis:
sklearn.preprocessing.OrdinalEncodermacht in Wahrheit nur eine Faktorisierung — echtes ordinales Mapping erfordert deutlich aufwändigere Parametrisierung.
Spezialfall: 0-1 Encodieren
- Bei nur zwei Kategorien reicht
np.where:data['contact'] = np.where(data.contact == 'cellular', 1, 0) - Achtung: alles, was nicht
cellularist, wird 0 (inkl. NAs) - Danach ggf. Spalte umbenennen für Transparenz:
data.rename(columns={'contact': 'contact_cellular'}, inplace=True)
Nominal Encodieren (One-Hot)
- Für Variablen ohne Rangordnung — hier wäre eine ordinale Zahl irreführend
pd.get_dummies()erstellt pro Kategorie eine neue Dummy-Variable (0/1) und entfernt die Ausgangsvariable- Wichtige Parameter:
drop_first=True→ eine Dummy weniger als Kategorien (vermeidet perfekte Multikollinearität / Dummy-Trap)prefix='marital'→ benennt die neuen Spalten mit Präfix (sinnvoll bei mehreren Variablen)columns=[...]→ mehrere Variablen auf einmal
- Trick für alle kategorialen Spalten außer Target:
target = 'y' sel_vars = data.select_dtypes(include=['object']).columns.drop(target) data = pd.get_dummies(data, columns=sel_vars, drop_first=True)
Transformationen: Numerische Variablen
Hinweis: Normalisieren und Standardisieren sind Unterarten von Skalieren, nicht drei gleichrangige Methoden.
- Methoden
- Skalieren
- Normalisieren
- Standardisieren
- Binning
- Skalieren
Skalieren
- Bringt numerische Variablen auf vergleichbare Wertebereiche
- Nur sinnvoll, wenn auf alle relevanten Variablen gleich angewendet
- Muss ggf. für spätere neue Daten gespeichert werden → daher in der Praxis
sklearn.preprocessingstatt Handformel:MinMaxScaler→ NormalisierungStandardScaler→ Standardisierung
.set_output(transform="pandas")behält den DataFrame, statt ein numpy-Array zurückzugeben:from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler().set_output(transform="pandas") data = scaler.fit_transform(data)
Normalisieren
- Skaliert auf festen Bereich [0, 1]
- Formel:
(x - min) / (max - min) - min → 0, max → 1
Standardisieren
- Zentriert auf Mittelwert 0, Standardabweichung 1 (z-Transformation)
- Formel:
(x - mean) / std - danach: mean ≈ 0, std = 1
Wichtig: Keines der beiden Verfahren ändert die Form der Verteilung — nur die Skala der x-Achse. Schiefe bleibt schief.
Binning
- Numerische Variable in Klassen/Bins zusammenfassen → wird quasi (ordinal-)kategorial
- Equal Binning: teilt min–max in gleich breite Bereiche
bins = 10 data.age = pd.cut(data.age, bins=bins, labels=list(range(1, bins + 1))) - Custom Bins: eigene Grenzen, nützlich bei stark schiefen Verteilungen
data.campaign = pd.cut( data.campaign, bins=[0, 1, 2, 3, 4, 5, 10, 1000], labels=[1, 2, 3, 4, 5, '6-10', '>10']) - Zur optimalen Bin-Anzahl gibt es keinen Konsens (Freedman-Diaconis, Sturges, …) → experimentell ermitteln
Konstruktion
- Neue Variablen aus bestehenden ableiten
- Ziele: Komplexität reduzieren, Korrelationen vermeiden
- Beispiel zyklische Daten (Windrichtung): 359° und 1° sind nah beieinander, numerisch aber weit weg → Zerlegung in sin/cos-Komponenten löst das
data['x'] = np.sin(data.direction * np.pi / 180) * data.speed data['y'] = np.cos(data.direction * np.pi / 180) * data.speed- allgemein relevant für alles Zyklische (Stunden, Monate, Winkel)
- Beispiel Datum: String →
pd.to_datetime(), dann Komponenten extrahierendata['date_dt'] = pd.to_datetime(data.Date, format="%d/%m/%Y") data['year'] = data.date_dt.dt.year data['month'] = data.date_dt.dt.month data['day'] = data.date_dt.dt.day- oder Differenzen zu einem Startdatum (
(data.date_dt - start_date).dt.days)
- oder Differenzen zu einem Startdatum (
Bereinigen von Variablennamen
- Nach One-Hot entstehen Namen mit Leerzeichen / Bindestrichen / Punkten (
job_blue collar,emp.var.rate), die manche ML-Frameworks als Bezeichner ablehnen - Erlaubte Zeichen:
a-z,A-Z,0-9,_ - Per Regex unerlaubte Zeichen durch
_ersetzen:new_names = old_names.str.replace('[^a-zA-Z0-9_]', '_', regex=True)