refactor: complete overwork of L2 Notizen with missing parts
This commit is contained in:
+239
-64
@@ -1,28 +1,14 @@
|
||||
# Notizen SL Lektion 2
|
||||
|
||||
>Thema: Datenverständnis, Explorative Datenanalyse, Feature Engineering
|
||||
>Datum: 21.05.2026
|
||||
>Dozentin: Violeta Vogel
|
||||
> Thema: Datenverständnis, Explorative Datenanalyse, Feature Engineering
|
||||
> Datum: 21.05.2026
|
||||
> Dozentin: Violeta Vogel
|
||||
|
||||
## Überwachtes Lernen vs. Unüberwachtes Lernen
|
||||
|
||||
- beim Überwachten Lernen kennt das Modell die richtigen Antworten (Labels) und das Modell lernt diese vorherzusagen
|
||||
- beim unüberwachten Lernen gibt es keine Labels, das Modell sucht selber Strukturen und Muster in den Daten
|
||||
|
||||
## Übungsaufgabe 1
|
||||
|
||||
> Alle genannten Modelle nutzen primär Self-Supervised Learning (im Tabellenschema am ehesten "unüberwacht", da keine händischen Labels)
|
||||
> für das Pretraining, gefolgt von überwachtem Fine-Tuning und Reinforcement Learning für das Alignment.
|
||||
|
||||
1. Pretraining
|
||||
- Self-Supervised (Next-Token-Prediction auf riesigen Text)
|
||||
- "Unsupervised"
|
||||
2. Supervised Fine-Tuning (SFT)
|
||||
- Überwacht (Mensch schreibt ideale Antworten auf Prompts)
|
||||
3. RLHF / RLAIF / DPO
|
||||
- Reinforcement Learning aus menschlichem (oder KI-) Feedback
|
||||
- DPO: Direct Preference Optimization
|
||||
|
||||
## Datenverständnis
|
||||
|
||||
1. Sammeln der Daten
|
||||
@@ -41,7 +27,6 @@
|
||||
- Sind die Daten vollständig?
|
||||
- Datenqualitätsbericht erstellen
|
||||
|
||||
|
||||
## EDA: Ziele und Methoden
|
||||
|
||||
- Mustererkennung
|
||||
@@ -54,17 +39,17 @@
|
||||
- Anomalien
|
||||
- Ausreisser, Datenpunkte die stark von der Norm abweichen
|
||||
- Mögliche Anomalien
|
||||
- Ausreisser -> einzelne Datenpunkte die signifikant von Rest abweichen
|
||||
- Kontextbezogene Anomalien -> Daten die nur in einem bestimmten Kontext ungewöhnlich sind
|
||||
- Kollekive Anomalien -> eine Gruppe von Datenpunkten die gemeinsam abweichen auch wenn sie einzeln normal wirken
|
||||
- Ausreisser → einzelne Datenpunkte die signifikant von Rest abweichen
|
||||
- Kontextbezogene Anomalien → Daten die nur in einem bestimmten Kontext ungewöhnlich sind
|
||||
- Kollektive Anomalien → eine Gruppe von Datenpunkten die gemeinsam abweichen, auch wenn sie einzeln normal wirken
|
||||
- mögliche Anomalien nach Variablenart
|
||||
- nicht numberische Daten
|
||||
- nicht numerische Daten
|
||||
- fehlende Werte
|
||||
- Duplikate
|
||||
- Kategorien Variablen
|
||||
- hohe Kardinalität (viele eindeutige Werte)
|
||||
- nicht balancierte Daten
|
||||
- numberische Variablen
|
||||
- numerische Variablen
|
||||
- schiefe Verteilung
|
||||
- Ausreisser
|
||||
- Korrelationen
|
||||
@@ -72,25 +57,21 @@
|
||||
|
||||
## Klassierung
|
||||
|
||||
> Die Klassierung in der deskriptiven Statistik ordnet viele, unterschiedliche
|
||||
Rohdaten in wenige, überschaubare Klassen (Intervalle) ein.
|
||||
> Die Klassierung in der deskriptiven Statistik ordnet viele, unterschiedliche Rohdaten in wenige, überschaubare Klassen (Intervalle) ein.
|
||||
|
||||
- Zweck: Reduzierung der Datenkomplexität (Muster und Trends erkennen)
|
||||
- Vorgehen: Festlegung von Klassengrenzen
|
||||
- Datstellung: Histogramme
|
||||
- Nachteile: Durch Gruppierungen geht die exakte Messgenauigkeit verloren, da einzelwerte nicht mehr erkennbar sind
|
||||
|
||||
- Darstellung: Histogramme
|
||||
- Nachteile: Durch Gruppierungen geht die exakte Messgenauigkeit verloren, da Einzelwerte nicht mehr erkennbar sind
|
||||
|
||||
# Aufbau eines Data Frames
|
||||
|
||||
- Objekte / Beobachtungen sind in den Zeilen (rows)
|
||||
- Merkmale / Attribute sind in den Spalten (columns) angegeben
|
||||
- Spalten enthalten sprechende Namen, über welche sie
|
||||
angesprochen werden können
|
||||
- pro Spalte ist ein Datentyp festgelegt, unterschiedliche Spalten können aber
|
||||
unterschiedliche Typen aufweisen
|
||||
- Spalten enthalten sprechende Namen, über welche sie angesprochen werden können
|
||||
- pro Spalte ist ein Datentyp festgelegt, unterschiedliche Spalten können aber unterschiedliche Typen aufweisen
|
||||
|
||||
## Workshop 1
|
||||
## Skalenniveaus (Workshop 1)
|
||||
|
||||
### Nominal
|
||||
|
||||
@@ -98,7 +79,7 @@ unterschiedliche Typen aufweisen
|
||||
|
||||
- Was geht:
|
||||
- Gleichheit prüfen (= oder ≠)
|
||||
- Was nicht geht:
|
||||
- Was nicht geht:
|
||||
- Reihenfolge
|
||||
- Abstände
|
||||
- Rechnen
|
||||
@@ -113,8 +94,8 @@ unterschiedliche Typen aufweisen
|
||||
- Häufigkeiten
|
||||
- Chi-Quadrat
|
||||
- Mittelwert ist Unsinn ("durchschnittliche Postleitzahl"...)
|
||||
- Stolperfalle:
|
||||
- Wenn Kategorien als Zahlen codiert sind (z.B. Postcode = 3000), sieht's numerisch aus, ist aber nominal. Pandas wird's als int einlesen – die Klassifikation musst du selbst machen.
|
||||
- Stolperfalle:
|
||||
- Wenn Kategorien als Zahlen codiert sind (z.B. Postcode = 3000), sieht's numerisch aus, ist aber nominal. Pandas wird's als int einlesen – die Klassifikation musst du selbst machen.
|
||||
|
||||
### Ordinal
|
||||
|
||||
@@ -125,12 +106,12 @@ unterschiedliche Typen aufweisen
|
||||
- Was nicht geht:
|
||||
- Abstände interpretieren
|
||||
- Rechnen
|
||||
- Beispiele:
|
||||
- Beispiele:
|
||||
- Schulnoten (ist der Abstand zwischen 4 und 5 derselbe wie zwischen 5 und 6? Nicht wirklich)
|
||||
- Likert-Skalen ("stimme zu" bis "stimme nicht zu")
|
||||
- Militärränge
|
||||
- T-Shirt-Grössen (S/M/L/XL)
|
||||
- Bildungsabschluss.
|
||||
- Bildungsabschluss
|
||||
- Sinnvolle Statistik:
|
||||
- Median
|
||||
- Quantile
|
||||
@@ -146,36 +127,230 @@ unterschiedliche Typen aufweisen
|
||||
- Alles bisherige
|
||||
- Abstände und Verhältnisse berechnen
|
||||
- Hier wird's manchmal weiter unterteilt:
|
||||
- Intervall: gleiche Abstände, aber kein echter Nullpunkt. Verhältnisse sind sinnlos. Beispiel: Temperatur in °C – 20°C ist nicht "doppelt so warm" wie 10°C, weil der Nullpunkt willkürlich gesetzt ist. Andere Beispiele: Kalenderjahre, IQ.
|
||||
- Ratio (Verhältnis): gleiche Abstände plus echter Nullpunkt. Verhältnisse sind sinnvoll. Beispiel: Preis (0 € heisst tatsächlich "nichts"), Länge, Gewicht, Anzahl Zimmer.
|
||||
- **Intervall**: gleiche Abstände, aber kein echter Nullpunkt. Verhältnisse sind sinnlos. Beispiel: Temperatur in °C – 20°C ist nicht "doppelt so warm" wie 10°C, weil der Nullpunkt willkürlich gesetzt ist. Andere Beispiele: Kalenderjahre, IQ.
|
||||
- **Ratio (Verhältnis)**: gleiche Abstände plus echter Nullpunkt. Verhältnisse sind sinnvoll. Beispiel: Preis (0 € heisst tatsächlich "nichts"), Länge, Gewicht, Anzahl Zimmer.
|
||||
- Sinnvolle Statistik:
|
||||
- Mittelwert
|
||||
- Standardabweichung
|
||||
- Pearson-Korrelation
|
||||
- alle parametrischen Tests
|
||||
|
||||
### Ergebnisse
|
||||
### Ergebnisse Workshop 1 – Melbourne Housing Dataset
|
||||
|
||||
Nr. Cholumn Dtype nominal ordinal metrisch
|
||||
0 Unnamed:0 int64 x
|
||||
1 Suburb object x
|
||||
2 Address object x
|
||||
3 Rooms int64 x
|
||||
4 Type object x
|
||||
5 Price float64 x
|
||||
6 Method object x
|
||||
7 SellerG object x
|
||||
8 Date object x x
|
||||
9 Distance float64 x
|
||||
10 Postcode float64 x
|
||||
11 Bedroom2 float64 x
|
||||
12 Bathroom float64 x
|
||||
13 Car float64 x
|
||||
14 Landsize float64 x
|
||||
15 BuildingArea float64 x
|
||||
16 YearBuilt float64 x x
|
||||
17 CouncilArea object x
|
||||
18 Lattitude float64 x
|
||||
19 Longtitude float64 x
|
||||
20 Regionname object x
|
||||
21 Propertycount float64 x
|
||||
| Nr. | Column | Dtype | nominal | ordinal | metrisch |
|
||||
|----:|--------|-------|:-------:|:-------:|:--------:|
|
||||
| 0 | Unnamed: 0 | int64 | | | x |
|
||||
| 1 | Suburb | object | x | | |
|
||||
| 2 | Address | object | x | | |
|
||||
| 3 | Rooms | int64 | | | x |
|
||||
| 4 | Type | object | x | | |
|
||||
| 5 | Price | float64 | | | x |
|
||||
| 6 | Method | object | x | | |
|
||||
| 7 | SellerG | object | x | | |
|
||||
| 8 | Date | object | | x | x |
|
||||
| 9 | Distance | float64 | | | x |
|
||||
| 10 | Postcode | float64 | x | | |
|
||||
| 11 | Bedroom2 | float64 | | | x |
|
||||
| 12 | Bathroom | float64 | | | x |
|
||||
| 13 | Car | float64 | | | x |
|
||||
| 14 | Landsize | float64 | | | x |
|
||||
| 15 | BuildingArea | float64 | | | x |
|
||||
| 16 | YearBuilt | float64 | | x | x |
|
||||
| 17 | CouncilArea | object | x | | |
|
||||
| 18 | Lattitude | float64 | | | x |
|
||||
| 19 | Longtitude | float64 | | | x |
|
||||
| 20 | Regionname | object | x | | |
|
||||
| 21 | Propertycount | float64 | | | x |
|
||||
|
||||
> Anmerkung zu `Date` und `YearBuilt`: Beide sind als ordinal **und** metrisch markiert. Das ist je nach Lesart vertretbar — ein Datum/Jahr hat eine klare Reihenfolge (ordinal) und gleiche Abstände ohne echten Nullpunkt (Intervall-metrisch). `Unnamed: 0` ist formal ein Index/Label und für ML eigentlich wertlos, auch wenn es als int64 "metrisch" aussieht (vgl. Nominal-Stolperfalle).
|
||||
|
||||
---
|
||||
|
||||
# EDA in der Praxis (pandas)
|
||||
|
||||
## Umgebung vorbereiten
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
data = pd.read_csv('bank_data.csv', sep=';')
|
||||
|
||||
# Indizes der kategorialen bzw. numerischen Variablen für späteren Gebrauch
|
||||
cat_vars = data.select_dtypes(include=['object']).columns
|
||||
num_vars = data.select_dtypes(exclude=['object']).columns
|
||||
```
|
||||
|
||||
- Merksatz Dtypes: `float64`, `int64` → numerisch; `object` → nicht numerisch (kategorial)
|
||||
|
||||
## Übersicht über den Data Frame
|
||||
|
||||
| Befehl | Zweck |
|
||||
|--------|-------|
|
||||
| `type(data)` | Objekttyp (`pandas.core.frame.DataFrame`) |
|
||||
| `data.shape` | Dimensionen `(rows, columns)` |
|
||||
| `data.info()` | Typ, Index, Dtypes, Non-Null-Count, Speicherbedarf |
|
||||
| `data.iloc[0:6, 0:6]` | erste paar rows/columns (Position-basiert) |
|
||||
| `data.head()` / `data.tail()` | erste / letzte rows |
|
||||
|
||||
## Missing Values (NAs)
|
||||
|
||||
```python
|
||||
data.isna().sum().sum() # Anzahl NAs insgesamt
|
||||
data.shape[0] - data.dropna().shape[0] # Anzahl rows mit mind. 1 NA
|
||||
s = data.isna().sum(); print(s[s > 0]) # NAs pro column
|
||||
```
|
||||
|
||||
- Wichtig: Anzahl NAs insgesamt ≠ Anzahl betroffener rows (eine row kann mehrere NAs haben)
|
||||
|
||||
## Duplikate
|
||||
|
||||
- Duplikate = Beobachtungen, die in **allen** Variablen denselben Wert aufweisen
|
||||
- `data.duplicated().sum()` → Anzahl
|
||||
- `.duplicated()` gibt eine boolesche Serie zurück → zum Anzeigen oder Entfernen nutzbar
|
||||
- ob Duplikate als Fehler gelten, ist eine **fachliche** Entscheidung
|
||||
|
||||
## Kategoriale Variablen – Kennzahlen
|
||||
|
||||
- `data.education.describe()` liefert bei kategorialen Variablen:
|
||||
- `count`: Anzahl nicht-Missing Values
|
||||
- `unique`: Anzahl unterschiedliche Werte (Kategorien / Levels)
|
||||
- `top`: häufigster Wert (→ Modalwert)
|
||||
- `freq`: Häufigkeit des Modalwertes
|
||||
- `data[cat_vars].describe()` → für alle kategorialen Variablen auf einmal
|
||||
- `data.education.value_counts()` → Frequenztabelle, sortiert nach **abnehmender** Häufigkeit (Modalwert zuerst); NAs werden per Default nicht ausgewiesen
|
||||
- `data[cat_vars].nunique()` → Anzahl Kategorien je Variable
|
||||
- sehr hohe Werte (nahe `count`) deuten auf ID-/Label-Charakter → kein Mehrwert für ML, und bei nominaler Umcodierung drohen sehr viele Dummy-Variablen
|
||||
|
||||
### Zero / Low Variance
|
||||
|
||||
- **Zero Variance**: alle Beobachtungen haben denselben Wert → kein Informationsgehalt, für ML wertlos
|
||||
- **Low Variance**: ein Wert dominiert die anderen stark → meist wenig nützlich, fachlich abzuklären
|
||||
- Konzept stammt aus der Analyse numerischer Variablen, lässt sich aber auch auf kategoriale anwenden
|
||||
|
||||
### Visualisierung kategorialer Variablen
|
||||
|
||||
- Standard: Barchart — `data.education.value_counts().plot.bar()` (Kategorien nach abnehmender Frequenz)
|
||||
- horizontaler Barplot: gut bei vielen Kategorien
|
||||
- Pie Plot: in der Data Analytics eher unbeliebt (Flächen/Winkel schwer vergleichbar)
|
||||
|
||||
## Numerische Variablen – Kennzahlen
|
||||
|
||||
- `data.age.describe()` liefert:
|
||||
|
||||
| Kennzahl | Bedeutung |
|
||||
|----------|-----------|
|
||||
| `count` | Anzahl (nicht-NA) Werte |
|
||||
| `mean` | Mittelwert (arithmetisches Mittel) |
|
||||
| `std` | Standardabweichung |
|
||||
| `min` | Minimum (→ 0. Quartil) |
|
||||
| `25%` | trennt kleinste 25 % ab → 1. Quartil |
|
||||
| `50%` | Median → 2. Quartil |
|
||||
| `75%` | trennt grösste 25 % ab → 3. Quartil |
|
||||
| `max` | Maximum (→ 4. Quartil) |
|
||||
|
||||
- `mean` und `std` heissen **parametrische** Kennzahlen (parametrisieren Normalverteilungsmodelle, werden auch zum Skalieren verwendet)
|
||||
- die übrigen (Quartile/Median) sind **nichtparametrische** Kennzahlen (vgl. Boxplot)
|
||||
- `describe()` gibt bei numerischen Variablen **keine** unique-Zahl aus → bei Bedarf `data[num_vars].nunique()` (sinnvoll v.a. bei Integer-Werten, um getarnte Kategorien zu finden)
|
||||
|
||||
### Stolperfalle Variablennamen
|
||||
|
||||
- Zugriff `data.<variable>.<funktion>()` klappt nur, wenn der Name den Python-Namenskonventionen entspricht
|
||||
- bei Namen wie `nr.employed` (Punkt!) → traditioneller Zugriff über Spaltenindex nötig:
|
||||
|
||||
```python
|
||||
print(data.age.mean()) # ok
|
||||
# print(data.nr.employed.mean()) # error
|
||||
print(data['nr.employed'].mean()) # ok
|
||||
```
|
||||
|
||||
### Visualisierung numerischer Variablen
|
||||
|
||||
- **Histogramm**: `data.age.plot.hist()` — Default 10 bins, via `bins=20` überschreibbar; zeigt Verteilungsform
|
||||
- **Densityplot (KDE)**: `data.age.plot.kde()` — Kernel Density Estimator: pro Beobachtung eine Normalverteilung der Fläche 1/n, additiv überlagert; mehr Detail als Histogramm, aber ressourcenhungrig
|
||||
- **Boxplot**: `data.age.plot.box(vert=False)` — zeigt nichtparametrische Kennzahlen + ausreisserverdächtige Werte
|
||||
|
||||
### Boxplot / Box-Whisker-Plot
|
||||
|
||||
- Box begrenzt durch 1. und 3. Quartil; Median innerhalb der Box markiert
|
||||
- Whiskers ("Schnauzhaare") = Werte ausserhalb der Box bis zur Ausreissergrenze
|
||||
- **IQR** (Interquartile Range) = 3. Quartil − 1. Quartil
|
||||
- als **Ausreisser** markiert werden Werte:
|
||||
- unterhalb von `Q1 − 1.5 × IQR`
|
||||
- oberhalb von `Q3 + 1.5 × IQR`
|
||||
- gruppierte Boxplots zum Vergleich: `data.boxplot(column=['age'], by='education', vert=False)`
|
||||
|
||||
### Ausreisser prüfen
|
||||
|
||||
- sortierte Ausgabe hilft einzuschätzen, ob Randwerte echte Extremwerte sind:
|
||||
|
||||
```python
|
||||
print(data.age.sort_values().head(10)) # kleinste
|
||||
print(data.age.sort_values(na_position="first").tail(10)) # grösste
|
||||
```
|
||||
|
||||
- Beispiel `age`: kleinster Wert (17) kommt mehrfach vor → plausibel; grösster Wert (116) setzt sich deutlich ab und ist fachlich unglaubwürdig → Ausreisser-Verdacht
|
||||
|
||||
### Schiefe Verteilungen
|
||||
|
||||
- Benennung (rechts-/linksschief) richtet sich nach der Position der **Extremwerte** (der "Schwanz")
|
||||
- rechtsschiefe Verteilungen sind in der Praxis häufig (z.B. Einkommen, hier `age` leicht, `duration` stark)
|
||||
- können oft mittels **Logarithmieren** in weniger schiefe Verteilungen transformiert werden
|
||||
|
||||
## Interaktionen zwischen Variablen
|
||||
|
||||
### Kategorial × kategorial
|
||||
|
||||
- **Kreuztabelle** (Mehrweg-Frequenztabelle): `pd.crosstab(data['job'], data['education'])`
|
||||
- farblich formatieren: `ct.style.background_gradient(axis=None)`
|
||||
- **Heatmap** (seaborn): `sns.heatmap(ct, annot=True, fmt='d')` — erleichtert Interpretation
|
||||
- mit Chi-Quadrat liessen sich Zusammenhänge quantifizieren, Vergleiche sind aber schwierig
|
||||
|
||||
> Toolwechsel: ab hier werden Visualisierungen mit **seaborn** (`sns`) gemacht — High-Level-Interface auf matplotlib, einfacher zu bedienen. matplotlib = mächtiges Low-Level-Interface mit steiler Lernkurve.
|
||||
> ```python
|
||||
> import matplotlib.pyplot as plt
|
||||
> import seaborn as sns
|
||||
> sns.set()
|
||||
> ```
|
||||
|
||||
### Numerisch × numerisch – Korrelationskoeffizient
|
||||
|
||||
- misst **Stärke und Richtung** des (linearen) Zusammenhangs zweier Variablen
|
||||
- `r` liegt zwischen −1 und +1:
|
||||
- +1 → perfekter positiver Zusammenhang (beide steigen; z.B. Körpergrösse/Gewicht)
|
||||
- 0 → kein linearer Zusammenhang (z.B. Schuhgrösse/Intelligenz)
|
||||
- −1 → perfekter negativer Zusammenhang (eine steigt, andere sinkt; z.B. Geschwindigkeit/Reisezeit)
|
||||
- Anwendung: Feature Selection (Zusammenhang mit Target), EDA (Muster/Beziehungen), Modellinterpretation
|
||||
- Achtung: misst nur **lineare** Zusammenhänge — Korrelation ≠ Kausalität
|
||||
|
||||
```python
|
||||
corr = data[['age', 'duration']].corr()
|
||||
```
|
||||
|
||||
- Diagonale immer 1.0 (Identität); Matrix ist symmetrisch, da `cor(x,y) = cor(y,x)` (kommutativ)
|
||||
- **Korrelogramm** (Heatmap) für die ganze Matrix:
|
||||
|
||||
```python
|
||||
plt.figure(figsize=(7, 6))
|
||||
ax = sns.heatmap(corr, annot=True, fmt='.2f',
|
||||
xticklabels=corr.columns, yticklabels=corr.columns,
|
||||
cmap=sns.diverging_palette(10, 220, as_cmap=True),
|
||||
vmin=-1, vmax=1)
|
||||
```
|
||||
|
||||
- **Scatterplot** für zwei Variablen, optional Gruppen einfärben:
|
||||
|
||||
```python
|
||||
sns.scatterplot(x='age', y='duration', data=data, hue='y')
|
||||
```
|
||||
|
||||
### Maskieren starker Zusammenhänge
|
||||
|
||||
- `.corr()` gibt selbst einen DataFrame → mit `.where()` lassen sich Werte maskieren, z.B. um in einem Korrelogramm nur stark korrelierte Paare zu zeigen:
|
||||
|
||||
```python
|
||||
mask = corr.where(abs(corr) >= 0.95)
|
||||
# danach mask in sns.heatmap(...) statt corr verwenden
|
||||
```
|
||||
|
||||
- nützlich, um redundante (hoch korrelierte) Features zu identifizieren → Kandidaten zum Entfernen
|
||||
|
||||
Reference in New Issue
Block a user