Skip to content
Snippets Groups Projects
Commit cf67b231 authored by Christof Kaufmann's avatar Christof Kaufmann
Browse files

Notebooks from applied-cs/data-science@b0c6376a

parent 2baf5d16
Branches
No related tags found
No related merge requests found
%% Cell type:markdown id:0005-d5cffa8f0704cf548e53737237da4d3ed2a6e83201311bc15ef4335e995 tags:
# Auto-Klassen mit Scikit-Learn
Anbei liegt wieder die Datei `autos.csv` mit Merkmalen von Autos und der
zugehörigen Klasse (im Sinne von Kleinstwagen etc.). Stellen Sie ihr
Arbeitsverzeichnis auf das Verzeichnis des Scripts ein. Sie können das
aktuelle Arbeitsverzeichnis in einer IPython-Konsole einfach mit `pwd`
(print working directory) ausgeben. Mit `cd PFAD` (z. B. `cd ..`) können
Sie das Verzeichnis wechseln.
## a) k Nearest Neighbors mit Scikit-Learn
- Lesen Sie die Daten mit Pandas ein.
- Teilen Sie den DataFrame in `X` und `y` auf, wobei `X` nur
numerische Features enthalten soll und `y` die Fahrzeugklasse. `X`
und `y` werden wir auch im nächsten Aufgabenteil brauchen.
- Splitten Sie Ihre Daten in Trainings- und Testmenge auf.
- Erstellen Sie ein `KNeighborsClassifier`-Objekt mit den
Standardwerten.
- Trainieren Sie das Modell indem Sie die `fit`-Methode mit der
Trainingsmenge aufrufen.
- Machen Sie eine Vorhersage (auch: Inferenz) für die Testmenge.
- Geben Sie die Genauigkeit aus, indem Sie die Test-Labels und die
vorhergesagten Labels in die Funktion `accuracy_score` übergeben.
Alternativ können Sie einfach `(y_test == y_pred).mean()` verwenden.
- *Bonus: Wie hoch ist die Genauigkeit, wenn die vorhergesagte
Fahrzeugklasse um eine Klasse daneben liegen darf?*
### Lösung zu a)
Wir laden zunächst die Daten und teilen sie in `X_train`, `X_test`,
`y_train`, `y_test` auf:
%% Cell type:code id:0006-c1652ecfe289903fe272ddb057b2b8ee0182c2f23c2e173384b6f1b9fde tags:
```
import optuna
import pandas as pd
from sklearn.metrics import accuracy_score
from sklearn.model_selection import cross_val_score, RepeatedStratifiedKFold, StratifiedKFold, train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import RobustScaler
df = pd.read_csv('autos.csv')
X = df.drop(columns=['Marke', 'Modell', 'Fahrzeugklasse'])
y = df['Fahrzeugklasse']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y)
```
%% Cell type:markdown id:0007-7355d79e0338534377a20e748034d9dbe360c14acf738d309a076505c1c tags:
Als nächstes erstellen wir ein Modell für $k$ Nearest Neighbors mit
Standardwerten ($k = 5$, $p = 2$ und alle Nachbarn zählen gleich viel),
trainieren es und werten es auf der Testmenge aus:
%% Cell type:code id:0008-6bd58ca167e0053fe33b658469a10f17e6b43f6896dadf06a0cf8dc6fd6 tags:
```
model = KNeighborsClassifier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
score = accuracy_score(y_test, y_pred)
```
%% Cell type:markdown id:0009-19f963d04e0849544556edd745a9be471ceb58af797b4db2b38d22fa480 tags:
Die Genauigkeit beträgt ungefähr – je nach zufälliger Aufteilung der
Trainings- und Testmengen – zwischen 41% und 70% und im Mittel ungefähr:
%% Cell type:code id:0010-851f37ceb0a7044dfa1fd10aaaa6c95b36520a0daa77af6d92a2ffc565c tags:
```
print(f'{score:.2%}')
```
%% Output
56.91%
%% Cell type:markdown id:0011-c808456d33568ef391dd7f3b317070d77e2bf593a17ab55b3c39720291d tags:
Wenn wir eine Toleranz von 1 Fahrzeugklasse verwenden, liegt die
Genauigkeit ungefähr zwischen und 83% und 100% und im Mittel ungefähr:
%% Cell type:code id:0012-1a056c770eab1c5dbdead803360ee3d448c0fd07feafcd3cca3af571230 tags:
```
near_miss_score = ((y_test - y_pred).abs() <= 1).mean()
print(f'{near_miss_score:.2%}')
```
%% Output
93.50%
%% Cell type:markdown id:0017-4dd0afa75578cad75b210fc616896d2ec10d95932f06e3996c0b5274d10 tags:
Das bedeutet vermutlich, dass die Vorhersage nicht komplett daneben
liegt.
## b) Skalierung
Skalieren Sie die Daten und ermitteln die Genauigkeit erneut.
### Lösung zu b)
Wir skalieren die Daten mit dem hier am besten geeigneten `RobustScaler`
und machen dasselbe wie zuvor. Beim Skalieren muss man darauf achten,
dass man nur einmal `fit` mit den Trainingsdaten aufruft, weil das die
Perzentile (25%, 50%, 75%) berechnet. Man skaliert dann die
Trainingsdaten und die Testdaten mit denselben werten.
%% Cell type:code id:0018-5e1919c285c5f9db87f5ade5c8a7f39c26f8bdd4958c4c6c021886296c4 tags:
```
scaler = RobustScaler()
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
model = KNeighborsClassifier()
model.fit(X_train_scaled, y_train)
y_pred_s = model.predict(X_test_scaled)
score_scaled = accuracy_score(y_test, y_pred_s)
```
%% Cell type:markdown id:0019-0bf204d53815dfc0965e543aae77b558e780a212333b5db15702b0d78ae tags:
Nun beträgt die Genauigkeit ungefähr zwischen 53% und 80% (anstatt 41%
und 70% ohne Skalierung) und im Mittel ungefähr:
%% Cell type:code id:0020-7371b9a07c7f1fe25d35f203d86a7e69a1192272662e6ac06a14fe78ab2 tags:
```
print(f'{score_scaled:.2%}')
```
%% Output
67.48%
%% Cell type:markdown id:0025-3ba483c9689e0d7ba3eb16e1838979f16c9bee44ce69a979eb97d285ca5 tags:
## c) Kreuzvalidierung
Ermitteln Sie die Genauigkeit über eine Kreuzvalidierung (aber mit der
Testmenge, also quasi eine Kreuzevaluation).
1. Dazu verwenden wir zunächst die gesamte Menge *ohne* eine Aufteilung
in Trainings- und Testmengen. Skalieren Sie also das gesamte `X`.
*Hinweis: Anstatt `fit` und `transform` separat aufzurufen, können
Sie auch `fit_transform` aufrufen.*
2. Erstellen Sie ein `StratifiedKFold`-Objekt (bereits importiert).
*Bonus: Erstellen Sie stattdessen ein
`RepeatedStratifiedKFold`-Objekt
([doc](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RepeatedStratifiedKFold.html)).*
3. Verwenden Sie `cross_val_score` wie in den Folien, aber mit
`X_scaled`.
4. Geben Sie den Mittelwert der Ergebnisse aus.
### Lösung zu c)
Wir skalieren nun die gesamten Daten wieder mit dem `RobustScaler` und
rufen `cross_val_score` mit `X_scaled` auf. Dabei gibt es kein
Data-Leakage, weil in jedem Training die Testmenge außen vor bleibt und
– ganz wichtig – wir das Ergebnis nicht nutzen um uns auf einem Teil der
Menge zu verbessern.
%% Cell type:code id:0026-a91779d7fcfbedb201cbceb62273acc7d645c72b54c7dec33f4a53e48a8 tags:
```
scaler = RobustScaler()
X_scaled = scaler.fit_transform(X)
folds = StratifiedKFold(5, shuffle=True)
scores_scaled_cv = cross_val_score(model, X_scaled, y, cv=folds, scoring='accuracy')
score_scaled_cv = scores_scaled_cv.mean()
```
%% Cell type:markdown id:0027-3bfb561f3875f077095b32a0c7d0377f93fe688d38d4bb75de6898ef257 tags:
Nun beträgt die Genauigkeit ungefähr zwischen 63.5% und 70.5% (anstatt
53% und 80% ohne Kreuzvalidierung) und im Mittel unverändert ungefähr:
%% Cell type:code id:0028-98a7f9a2738231b6905840f64f990616c7cacfb64bc2570d40af1bfa18d tags:
```
print(f'{score_scaled_cv:.2%}')
```
%% Output
67.15%
%% Cell type:markdown id:0034-ae5d5a5918f209ffcbd24188436259e7ef46c1b452327ef493c1324aeef tags:
Mit `RepeatedStratifiedKFold` mit Default-Werten (also `n_splits=5` und
`n_repeats=10`) liegt die Genauigkeit zwischen 66.4% und 68.6%. Das ist
eine sehr geringe Spanne, die besser für eine Hyperparameteroptimierung
geeignet ist.
## d) Optuna
In diesem Teil geht es darum zusätzliche Skalierungsfaktoren zu
optimieren.
1. Der Startcode implementiert bereits die Optimierung von $k$ und $p$
mit Optuna. Schauen Sie sich den Startcode an und probieren ihn aus.
2. Fügen Sie in die `objective`-Funktion für jedes Feature jeweils
einen Skalierungsfaktor als Hyperparameter hinzu, der das Feature
nach der Skalierung umskaliert. Vielleicht ist es von Vorteil, wenn
einige Features den Abstand stärker beeinflussen als andere.
3. Führen Sie die Optimierung durch.
4. Betrachten Sie die Ergebnisse im Parallele-Koordinaten-Plot und
wählen Sie gute Parameter.
### Lösung zu d)
Wir skalieren die Features jeweils zwischen $[10^{-2}, 10^2]$ mit
logarithmischwer Verteilung, weil wir wollen, dass der Bereich
$[10^{-2}, 10^0] = [0.01, 1]$ genauso wahrscheinlich ist, wie der
Bereich $[10^0, 10^2] = [1, 100]$.
%% Cell type:code id:0035-a2dc6bde9454a074f712141df254855d6bc6d43503890bc2db31962e1a8 tags:
%% Cell type:code id:0035-2239964036f73944f5196e8c13aab9159de4669ccec74a6d83ea087ec8d tags:
```
folds = RepeatedStratifiedKFold()
def objective(trial):
k = trial.suggest_int('k', 1, 9)
p = trial.suggest_categorical('p', [1, 2, 4, np.inf])
p = trial.suggest_categorical('p', [1, 2, 4, float('inf')])
scale_factores = [trial.suggest_float('scale_' + col, 1e-2, 1e2, log=True) for col in X.columns]
model = KNeighborsClassifier(n_neighbors=k, p=p, weights='distance')
scores_cv = cross_val_score(model, X_train_scaled * scale_factores, y_train, cv=folds, scoring='accuracy')
return scores_cv.mean()
```
%% Cell type:markdown id:0036-8f570a8c845c9b7351be9dc2ff5943af11f8ea2daf43c6e6946cae8935d tags:
### Tests zu d)
%% Cell type:code id:0037-8565d9b2658fda0d997f9c5e7b432ba8c45ae399d1222bad654c1e3608d tags:
%% Cell type:code id:0037-79487c80368ad85001b24281bc990d3a53e0e926e8d11a2d56ee7b43d52 tags:
```
study = optuna.create_study(direction='maximize', sampler=optuna.samplers.GPSampler(deterministic_objective=True)) # less duplicate trials
study.optimize(objective, n_trials=100, n_jobs=4)
optuna.visualization.plot_parallel_coordinate(study)
fig = optuna.visualization.plot_parallel_coordinate(study)
```
......
%% Cell type:markdown id:0004-8aed67bf1a5065a62440343a778365e49e5143ddca600561cbb5ec2e72f tags:
# Auto-Klassen mit Scikit-Learn
Anbei liegt wieder die Datei `autos.csv` mit Merkmalen von Autos und der
zugehörigen Klasse (im Sinne von Kleinstwagen etc.). Stellen Sie ihr
Arbeitsverzeichnis auf das Verzeichnis des Scripts ein. Sie können das
aktuelle Arbeitsverzeichnis in einer IPython-Konsole einfach mit `pwd`
(print working directory) ausgeben. Mit `cd PFAD` (z. B. `cd ..`) können
Sie das Verzeichnis wechseln.
## a) k Nearest Neighbors mit Scikit-Learn
- Lesen Sie die Daten mit Pandas ein.
- Teilen Sie den DataFrame in `X` und `y` auf, wobei `X` nur
numerische Features enthalten soll und `y` die Fahrzeugklasse. `X`
und `y` werden wir auch im nächsten Aufgabenteil brauchen.
- Splitten Sie Ihre Daten in Trainings- und Testmenge auf.
- Erstellen Sie ein `KNeighborsClassifier`-Objekt mit den
Standardwerten.
- Trainieren Sie das Modell indem Sie die `fit`-Methode mit der
Trainingsmenge aufrufen.
- Machen Sie eine Vorhersage (auch: Inferenz) für die Testmenge.
- Geben Sie die Genauigkeit aus, indem Sie die Test-Labels und die
vorhergesagten Labels in die Funktion `accuracy_score` übergeben.
Alternativ können Sie einfach `(y_test == y_pred).mean()` verwenden.
- *Bonus: Wie hoch ist die Genauigkeit, wenn die vorhergesagte
Fahrzeugklasse um eine Klasse daneben liegen darf?*
Hier Ihr Start-Code:
%% Cell type:code id:0005-682ba86e4b2ef1a270871f098102d4349b3f2b0977c41614e4b442895f7 tags:
```
import pandas as pd
import optuna
from sklearn.metrics import accuracy_score
from sklearn.model_selection import cross_val_score, StratifiedKFold, train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import RobustScaler
# TODO: Daten laden
# TODO: In X, y aufteilen
# TODO: In Training- und Testmengen splitten
# TODO: k-NN erstellen, trainieren, vorhersagen
# TODO: Genauigkeit ausgeben
```
%% Cell type:markdown id:0007-d9e25205ef98d910bef301fd97bad7094675f32062447639cceb4728289 tags:
## b) Skalierung
Skalieren Sie die Daten und ermitteln die Genauigkeit erneut.
%% Cell type:code id:0008-44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 tags:
```
```
%% Cell type:markdown id:0011-7e58ce651003652ff193df6731b83f9d835ed244d0ef5387f3325e8cb42 tags:
## c) Kreuzvalidierung
Ermitteln Sie die Genauigkeit über eine Kreuzvalidierung (aber mit der
Testmenge, also quasi eine Kreuzevaluation).
1. Dazu verwenden wir zunächst die gesamte Menge *ohne* eine Aufteilung
in Trainings- und Testmengen. Skalieren Sie also das gesamte `X`.
*Hinweis: Anstatt `fit` und `transform` separat aufzurufen, können
Sie auch `fit_transform` aufrufen.*
2. Erstellen Sie ein `StratifiedKFold`-Objekt (bereits importiert).
*Bonus: Erstellen Sie stattdessen ein
`RepeatedStratifiedKFold`-Objekt
([doc](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RepeatedStratifiedKFold.html)).*
3. Verwenden Sie `cross_val_score` wie in den Folien, aber mit
`X_scaled`.
4. Geben Sie den Mittelwert der Ergebnisse aus.
%% Cell type:code id:0012-44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 tags:
```
```
%% Cell type:markdown id:0015-1a2cb5f0269a7d88b4861ef37715bd33303afa2fbaa8fa3b50c9bcc2ab2 tags:
## d) Optuna
In diesem Teil geht es darum zusätzliche Skalierungsfaktoren zu
optimieren.
1. Der Startcode implementiert bereits die Optimierung von $k$ und $p$
mit Optuna. Schauen Sie sich den Startcode an und probieren ihn aus.
2. Fügen Sie in die `objective`-Funktion für jedes Feature jeweils
einen Skalierungsfaktor als Hyperparameter hinzu, der das Feature
nach der Skalierung umskaliert. Vielleicht ist es von Vorteil, wenn
einige Features den Abstand stärker beeinflussen als andere.
3. Führen Sie die Optimierung durch.
4. Betrachten Sie die Ergebnisse im Parallele-Koordinaten-Plot und
wählen Sie gute Parameter.
%% Cell type:code id:0016-5b5d432c8107554b190e9b5f88594153f66d68e9ed8cb2d394aa224898d tags:
%% Cell type:code id:0016-91d49960a264a20d3d42fc074dda98db8fa9710f976efc5e31c705f5c9f tags:
```
folds = RepeatedStratifiedKFold()
def objective(trial):
k = trial.suggest_int('k', 1, 9)
p = trial.suggest_categorical('p', [1, 2, 4, np.inf])
p = trial.suggest_categorical('p', [1, 2, 4, float('inf')])
model = KNeighborsClassifier(n_neighbors=k, p=p, weights='distance')
scores_cv = cross_val_score(model, X_train_scaled, y_train, cv=folds, scoring='accuracy')
return scores_cv.mean()
```
%% Cell type:markdown id:0017-8f570a8c845c9b7351be9dc2ff5943af11f8ea2daf43c6e6946cae8935d tags:
### Tests zu d)
%% Cell type:code id:0018-8565d9b2658fda0d997f9c5e7b432ba8c45ae399d1222bad654c1e3608d tags:
%% Cell type:code id:0018-79487c80368ad85001b24281bc990d3a53e0e926e8d11a2d56ee7b43d52 tags:
```
study = optuna.create_study(direction='maximize', sampler=optuna.samplers.GPSampler(deterministic_objective=True)) # less duplicate trials
study.optimize(objective, n_trials=100, n_jobs=4)
optuna.visualization.plot_parallel_coordinate(study)
fig = optuna.visualization.plot_parallel_coordinate(study)
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment