416 lines
16 KiB
Markdown
416 lines
16 KiB
Markdown
# 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
|
||
- 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=True` werden 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 → 0`
|
||
- `unknown → 0`
|
||
- `basic.4y → 1`
|
||
- `basic.6y → 2`
|
||
- `basic.9y → 3`
|
||
- `professional.course → 4`
|
||
- `high.school → 5`
|
||
- `university.degree → 6`
|
||
- Umsetzung über `.replace()` mit einem (verschachtelten) Dictionary, das vorher definiert wird:
|
||
```python
|
||
data.replace(replace_nums, inplace=True)
|
||
```
|
||
- Hinweis: `sklearn.preprocessing.OrdinalEncoder` macht in Wahrheit nur eine Faktorisierung — echtes ordinales Mapping erfordert deutlich aufwändigere Parametrisierung.
|
||
|
||
#### Spezialfall: 0-1 Encodieren
|
||
|
||
- Bei nur zwei Kategorien reicht `np.where`:
|
||
```python
|
||
data['contact'] = np.where(data.contact == 'cellular', 1, 0)
|
||
```
|
||
- Achtung: alles, was *nicht* `cellular` ist, wird 0 (inkl. NAs)
|
||
- Danach ggf. Spalte umbenennen für Transparenz:
|
||
```python
|
||
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:
|
||
```python
|
||
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
|
||
|
||
- 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.preprocessing` statt Handformel:
|
||
- `MinMaxScaler` → Normalisierung
|
||
- `StandardScaler` → Standardisierung
|
||
- `.set_output(transform="pandas")` behält den DataFrame, statt ein numpy-Array zurückzugeben:
|
||
```python
|
||
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
|
||
```python
|
||
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
|
||
```python
|
||
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
|
||
```python
|
||
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 extrahieren
|
||
```python
|
||
data['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`)
|
||
|
||
## 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:
|
||
```python
|
||
new_names = old_names.str.replace('[^a-zA-Z0-9_]', '_', regex=True)
|
||
```
|
||
|
||
## Dekomposition
|
||
|
||
- Informatik: Kernmethode um grosse Probleme in kleine, handhabbare Teilaufgaben aufzuteilen
|
||
- Wirtschaft und Mathematik: Analyse von Daten und Prozesse in einzelne Komponenten aufteilen, Trends, Zeitreihenanalyse und Restrauschen
|
||
- In der Datenanalyse:
|
||
- Saisonbereinigung vs. Trend
|
||
- Prognose/Forecasting -> Aus Trend und Saisonalität kann Zukunft abgeleitet werden
|
||
- Fehleranalyse -> Ist das "Restrauschen" normal oder hat es plötzliche Ausschläge?
|
||
|
||
### Beispiel: Eisverkauf
|
||
|
||
- Saisonalität ist eindeutig
|
||
- Wird die Saisonalität herausgerechnet, sieht man den Trend
|
||
- Zufälle: Bspw Firmenfeier oder Schulabschluss
|
||
|
||
## Merkmals-Dekomposition
|
||
|
||
- Standardverfahren zur Dimensionsreduktion
|
||
- Viele Features können zu wenigen aussagekräftigen Hauptfaktoren zusammengelegt werden
|
||
- Die wichtigsten Algorithmen
|
||
- PCA (principlan component analysis)
|
||
- Sucht nach den Richtungen (Achsen) in denen die Daten die grösste Varianz aufweisen
|
||
- t-SNE (t-distributed Stochastic Neighbor Embedding)
|
||
- Besonders gut darin nicht lineare Daten abzubilden
|
||
- Faktorenanalyse
|
||
- Geht davon aus, dass es latente Variablen gibt
|
||
|
||
### PCA
|
||
|
||
- Zentrierung: Man schiebt die Datenwolke (Pixelhaufen) so, dass ihr Mittelpunkt genau bei Null liegt
|
||
- Berechnung der Hauptkomponenten
|
||
- Die 1. Hauptkomponente PC1 ist die Linie die so mitten durch die Daten gelegt wird, dass die Punkte so weit wie möglich darauf verteilt sind
|
||
- Die 2. Hauptkomponente PC2 steht im rechten Winkel zur ersten und fängt den rest der Infromation ein
|
||
- Vereinfacht einen riesigen Datensatz so, dass
|
||
- nur die wichtigsten Merkmale bleiben
|
||
- ohne das Gesamtbild zu verlieren
|
||
- Visualisierung
|
||
- Daten mit 10 oder 50 Merkmalen kann man nicht zeichnen
|
||
- Nach PCA hat man 2 Hauptkomponenten und
|
||
- man kann sie als Punkte darstellen
|
||
- Geschwindigkeit: KI-Modelle lernen viel schneller wenn sie statt 1000 nur noch 10 komprimierte Merkmale verarbeiten müssen
|
||
- Rauschunterdrückung: Kleine unwichtige Schwankungen (Rauschen) gehen verloren!
|
||
- Voraussetzungen
|
||
- keine Missing values
|
||
- keine numerischen Daten
|
||
- bereinigung anderer möglichen Anomalien
|
||
- Features -> X
|
||
- Target -> Y
|
||
```python
|
||
from sklearn.decomposition import PCA
|
||
model = PCA()
|
||
pred = model.fit_transform(X) # train and apply trainer on data
|
||
print(pred[:3,:]) # check result
|
||
```
|
||
- Interessant: Scatterplot PC1 vs PC2
|
||
|
||
## Stichproben
|
||
|
||
- Eie Stichprobe ist ein vollständiges, verkleinertes Spiegelbild der Grundgesamtheit.
|
||
- Sie gibt damit auch alle wesentlichen Eigenschaften der Grundgesamtheit wieder
|
||
- Mit eine Probeziehung wird ein repräsentativer Teil einer Population ausgewählt um Rückschlüsse auf die Gesamtheit zu ziehen
|
||
- Repräsentativ
|
||
- Eine Stichprobe ist dann repräsentativ wenn alle Beobachtungen der Grundgesamtheit die gleiche Chance besessen haben, Teil dieser Stichprobe zu werden
|
||
|
||
### Stichprobengrösse
|
||
|
||
- Maschinelles Lernen: Als Faustregel gilt, dass Sie mindestens zehnmalso viele Datenpunkte/Beobachtungen benötigen, wie Ihr Datensatz Features enthält
|
||
- Art des Ziehens
|
||
- Mit oder ohne zurücklegen
|
||
|
||
### Einfache Stichprobe (Zufallsstichprobe)
|
||
|
||
- Rein zufällige Features werden gezogen
|
||
- Jede Beobachtung hat die gleiche Chance gezogen zu werden
|
||
- Vorteil
|
||
- Ist die Zufallsstichprobe gross genug werden automatisch alle Beobachtungen in der Stichprobe auftauchen
|
||
|
||
### Geschichtete Stichprobenziehung (Stratifizierung)
|
||
|
||
- Ziel
|
||
- Die Grundgesamtheit so genau wie möglich darzustellen
|
||
- Anforderungen an die Schichten
|
||
- Sie sollten sich gegenseitig ausschliessen und gemeinsam erschöpfend sein
|
||
- Vorgehen
|
||
- relevante Variablen identifizieren
|
||
- alter, geschlecht, einkommen, standort
|
||
- Grundgesamtheit wird auf Grundlage dieser Variablen in Untergruppen (schichten) eingeteilt
|
||
- Zufallsstichprobe aus jeder Schicht wählen:
|
||
- Proportional -> entsprechend dem Anteil der Schicht an der Grundgesamtheit
|
||
- Disproportional -> etwa Gleich grosse Stichproben aus jeder Schicht
|
||
|
||
### Proportionale Stratifizierung
|
||
|
||
- Die schichten werden originalgetreu gewichtet
|
||
- Vorteile
|
||
- Repräsentativität -> die Grundgesamtheit ist in der Stichprobe gut abgebildet
|
||
- Präzise Schätzungen möglich
|
||
- Nachteile
|
||
- Aufwand
|
||
- Komplexität
|
||
|
||
### Disproportionale Stratifizierung
|
||
|
||
- Die Schichten werden unterschiedlich stark gewichtet
|
||
- Verwendung wenn
|
||
- bestimmte Schichten von besonderem Interesse sind
|
||
- Kosten der Datenerhebung in den veschiedenen Schichten variieren
|
||
- Ziel: Ausreichende Anzahl von Elementen jeder Schicht zu haben
|
||
- Gewichtung: Faktor der die ursprüngliche Verteilung der Grundgesamtheit berücksichtigt
|
||
- Vorteile:
|
||
- Genauigkeit
|
||
- Effizienz
|
||
- Berücksichtigt Heterogenität
|
||
- Detailiertere Analyse der unterschiedlichen Schichten möglich
|
||
- Nachteile:
|
||
- Verzerrte Ergebnisse
|
||
- Aufwändige Analyse
|
||
|
||
### Klumpenstichprobe
|
||
|
||
- Grundgesamtheit zunächst hinsichtlich eines Merkmals in natürliche Klumpen einteilen
|
||
- Wie bspw. Klassen in einer Schule
|
||
- Klumpen untereinander Homogen
|
||
- Jeder Klumpen ist ein verkleinertes Abbild der Population
|
||
- Alle Klumpen können sich stark ähneln
|
||
|
||
## Algorithmen
|
||
|
||
- Wichtig
|
||
- Distanzmasse
|
||
- Overfitting
|
||
- Training vs Anwenden
|
||
|
||
## Euklidisches Distanzmass
|
||
|
||
- Wird am häufigsten verwendet in der Clusteranalyse
|
||
- "Luftlinie", die den geometrischen Abstand zwischen zwei Punkten in einem Koordinatensystem misst
|
||
- Für zwei Punkte P und Q in einem mehrdimensionalen Raum berechnet sich die Distanz nach dem Satz des Pythagoras
|
||
- Optische Verzerrung
|
||
- Nicht alle Features fallen gleich stark ins Gewicht
|
||
- Lösung: Standardisierung
|
||
|
||
## Manhattan-Distanz (Taxi Prinzip)
|
||
|
||
- Summe der absoluten Differenzen ihrer Einzelmasse und keine "Luftlinie"
|
||
- Wenig anfälliger für Ausreisser
|
||
|
||
## Overfitting
|
||
|
||
- Ein ML-Model lernen die Trainingsdaten zu gut auswendig und lernt
|
||
- Zufallsschwankungen und Rauschen
|
||
- Es wirkt intelligent aber in Wahrheit ist es nicht mehr generalisierungsfähig
|
||
- Modell sieht Muster wo keine sind
|
||
- Passiert wenn das Modell
|
||
- zu komplex ist
|
||
- zu wenig Daten hat
|
||
- zu lange trainiert wure
|
||
- Rauschen in den Daten als echtes Muster interpretiert wird
|
||
- Ein Entscheidungsbaum könnte so stark wachsen, dass er jeden einzelnen Trainingspunkt perfekt trennt, sogar Ausreisser
|
||
- Wie verhindert man das?
|
||
- Cross-Validation
|
||
- bei kleinen Datensätzen wichtig
|
||
- Teilung des Datensatz in bestimmte Mengen
|
||
- Bspw: Ten-fold cross validation (10:1 Trainings zu Testdaten)
|
||
- Regularisierungen (L1,L2)
|
||
- Frühzeitiges Stoppen
|
||
- Pruning bei Entscheidungsbäumen
|
||
- Mehr Trainingsdaten
|
||
- Dropout bei neuronalen Netzen
|
||
- Modell vereinfachen
|
||
- Wenn sich Test Error und Training Error stark unterscheiden
|
||
- Ist das fast immer ein Zeichen für Overfitting
|
||
|
||
## Modeltraining vs Modelanwendung
|
||
|
||
- Modelltraining
|
||
- Input
|
||
- Daten
|
||
- Antworten (Zielvariable)
|
||
- Algorithmus aussuchen
|
||
- Algorithmen lernen Regeln
|
||
- Auswählen des Algorithmus der am besten performed
|
||
- Modelanwendung
|
||
- Das Modell bekommt neue unbekannte Daten
|
||
- Macht eine Vorhersage basierend auf den Trainingsdaten
|
||
|
||
## Algorithmen Übersicht
|
||
|
||
- lineare Modelle
|
||
- Baumverfahren
|
||
- Ensemble-Verfahren
|
||
- Suport Vector Machines
|
||
- Naive Bayes
|
||
- k-Nearest Neighbors
|
||
- Neuronale Netze
|
||
|
||
## kNN: k Nearest Neighbors
|
||
|
||
- Ist sehr intuitiv
|
||
- Berechnet man anhand von Distanzen
|
||
- Kosinus Distanz
|
||
- Manhattan Distanz
|
||
- Euklidische Distanz
|
||
- k Nachbarn auswählen (k ist eine natürliche Zahl) die berücksichtig werden
|
||
- einer der wichtigsten Schritte bei diesem Modell
|
||
- schlecht gewähltes k führt zu Over- oder Underfitting
|
||
- ist abhänig von der Datenmenge
|
||
- entscheidung treffen
|
||
- Klassifikation: Mehrheit gewinnt
|
||
- Regression: Durchschnitt der Nachbaren
|
||
- Grundprinzip
|
||
- kelines k -> Overfitting -> Modell reagiert auf zu viele Punkte
|
||
- grosses k -> Underfitting -> Modell wird zu grob
|
||
- Vorteile
|
||
- Einfachheit
|
||
- Nachteile
|
||
- langsames Training
|
||
- viel Rechenaufwand
|
||
- kNN wid vor allem dort eingesetzt wo die Ähnlichkeit zwischen Datenpunkten eine grosse Rolle spielt!
|
||
- kNN ist kein Clusterin Algorithmus aber es kann ähnliche Ergebnisse liefern
|
||
- kNN funktioniert am besten, wenn Daten übersichtlich, niederdimensional und gut skaliert sind
|
||
|
||
## kNN mit scikit-learn
|
||
|
||
- kNN ist ein Klassifikator, das generelle Vorgehen ist wie folgt
|
||
1. laden der Daten
|
||
2. auftrennen in feature Matrix (X) und Traget Vektor (y): Features - Target - Split
|
||
3. auftrennen von X und y in trainingsset (X_train, y_train) und Testset (X_Test und y_test)
|
||
4. importieren der Trainingsfunktion
|
||
5. definieren des zu lernenden Modells mit gewünschter Parametrisierung
|
||
6. trainieren des Modells
|
||
7. anwenden des Modells
|
||
8. evaluieren der performance
|