From 95a6309a1b18a86a8776902270c7e86b8b8e5c38 Mon Sep 17 00:00:00 2001 From: nullpunktTUD Date: Tue, 21 Apr 2020 11:06:48 +0200 Subject: [PATCH] Final version for SS 2020 --- .../Klassifikation von Wein.ipynb | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Classification/Wine-Quality/Klassifikation von Wein.ipynb b/Classification/Wine-Quality/Klassifikation von Wein.ipynb index 7fcd9f1..2693ac9 100644 --- a/Classification/Wine-Quality/Klassifikation von Wein.ipynb +++ b/Classification/Wine-Quality/Klassifikation von Wein.ipynb @@ -56,6 +56,8 @@ " \n", "\n", "\n", + "**Hinweis:** In diesem Notebook sind einige Stellen enthalten, an denen Zufallszahlen zum Einsatz kommen (z.B. die Initialisierung des neuralen Netzes oder die Einteilung in Trainings- und Testset). Dadurch kann es passieren, dass manche Ergebnisse für Sie nicht exakt reproduzierbar sind und das relative Ranking der verschiedenen Klassifikatoren bei Ihnen etwas anders aussieht. Das ändert allerdings nichts an der generellen Vorgehensweise oder den Programmiermustern. \n", + "\n", "---\n" ] }, @@ -215,7 +217,7 @@ "2. Alle Merkmale sind rein numerisch. Wir müssen also auch keine Daten konvertieren!\n", "3. Die Daten sind sehr unterschiedlich skaliert, da die Mittelwerte (__```mean```__) und Standardabweichungen (__```std```__) über mehrere Größenordnungen hinweg streuen.\n", "\n", - "Daher bietet es sich an, die Spalten zunächst einzeln zu standardisieren, so dass sie jeweils einen Mittelwert von 0 und eine Standardabweichung von 1 haben (auch $z$-Score Normalisierung genannt). Dadurch sind werden also alle Merkmale in die gleiche Größenordnung gebracht, ohne die relative Verteilung zu vereinfachen.\n", + "Daher bietet es sich an, die Spalten zunächst einzeln zu standardisieren, so dass sie jeweils einen Mittelwert von 0 und eine Standardabweichung von 1 haben (auch $z$-Score Normalisierung genannt). Dadurch werden also alle Merkmale in die gleiche Größenordnung gebracht, ohne die relative Verteilung zu vereinfachen.\n", "\n", "Unser Fahrplan für die Säuberung der Daten ist also klar:\n", "- Kein konvertieren oder auffüllen nötig\n", @@ -263,7 +265,7 @@ "editable": false }, "source": [ - "Nun kommt der eigentliche Split in Train- und Testset, den wir mit Hilfe der Funktion [```traint_test_split()```](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) aus ```scikit-learn``` vornehmen wollen." + "Nun kommt der eigentliche Split in Train- und Testset, den wir mit Hilfe der Funktion [```train_test_split()```](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) aus ```scikit-learn``` vornehmen wollen." ] }, { @@ -301,7 +303,7 @@ "# Instanziieren Sie ein Objekt StandardScaler()\n", "stdScaler = \n", "\n", - "# Berechnen Sie die Standardisierungsparametr auf dem Trainingsset (!) X_train mit Hilfe der Funktion \"fit()\"\n", + "# Berechnen Sie die Standardisierungsparameter auf dem Trainingsset (!) X_train mit Hilfe der Funktion \"fit()\"\n", "\n", "# Wenden Sie die **selbe** Standardisierung mit Hilfe der Methode transform() auf die Trainings- und Testdaten an\n", "X_train = \n", @@ -444,7 +446,7 @@ "# Testgenauigkeit (in Prozent)\n", "test_score_knn = knn_model.score(X_test, y_test)*100\n", "# Ausgabe der Performancemaße\n", - "print(\"Standard KNN - Training: {:.2f} % Test: {:.2f} %\".format(train_score, test_score))" + "print(\"Standard KNN - Training: {:.2f} % Test: {:.2f} %\".format(train_score_knn, test_score_knn))" ] }, { @@ -464,7 +466,7 @@ "\n", "**Es empfiehlt sich sehr, die Hyperparameteroptimierung auf einem parallen Rechner auszuführen!*** Da jede Hyperparameterkonfiguration und jede Kreuzvalidierung unabhängig voneinander berechnet werden können, ist hier ein nahezu perfekter paralleler [Speedup](https://de.wikipedia.org/wiki/Speedup) möglich. Ein einfaches Beispiel:\n", "\n", - "Sie wollen prüfen, welche Zahl zwischen 1 und 10 die beste Zahl von Nachbarn in dem $k$ Nächste Nachbarn Klassifikator darstellt. Dazu müssen Sie also 10 Modelle mit 10 verschiedenen Werten für $k$ berechnen und diese miteinander vergleichen. Zum Vergleich wollen Sie jedes Modell mit 4 Folds validieren. Dazu müssen Sie also für jeden der 10 Werte von $k$ schon 4 Modell berechnen, also insgesamt 40 Trainingsvorgänge. Auf einem Single-CPU Rechner dauert dies dann zum Beispiel eine Minute. Da alle Berechnungen getrennt voneinander gemacht werden könne, kann das exakt gleiche Training auf einem Parallelrechner mit z.B. 20 CPUs in 1/20 der Zeit gerechnet werden, also in diesem Beispiel in nur 3 Sekunden. Wenn noch weitere Hyperparameter optimiert oder mehr Werte ausprobiert werden sollen, explodiert der Rechenaufwand entsprechend durch die kombinatorische Vielfalt des Gitters. Parallele Ausführung ist hier also enorm wichtig. ***Wir empfehlen daher nachdrücklich das Arbeiten auf dem HPC (siehe [Einführung ins Praktikum](https://bildungsportal.sachsen.de/opal/auth/RepositoryEntry/23165501449/CourseNode/101490883666782))!***\n" + "Sie wollen prüfen, welche Zahl zwischen 1 und 10 die beste Zahl von Nachbarn in dem $k$ Nächste Nachbarn Klassifikator darstellt. Dazu müssen Sie also 10 Modelle mit 10 verschiedenen Werten für $k$ berechnen und diese miteinander vergleichen. Zum Vergleich wollen Sie jedes Modell mit 4 Folds validieren. Dazu müssen Sie also für jeden der 10 Werte von $k$ schon 4 Modell berechnen, also insgesamt 40 Trainingsvorgänge. Auf einem Single-CPU Rechner dauert dies dann zum Beispiel eine Minute. Da alle Berechnungen getrennt voneinander gemacht werden können, kann das exakt gleiche Training auf einem Parallelrechner mit z.B. 20 CPUs in 1/20 der Zeit gerechnet werden, also in diesem Beispiel in nur 3 Sekunden. Wenn noch weitere Hyperparameter optimiert oder mehr Werte ausprobiert werden sollen, explodiert der Rechenaufwand entsprechend durch die kombinatorische Vielfalt des Gitters. Parallele Ausführung ist hier also enorm wichtig. ***Wir empfehlen daher nachdrücklich das Arbeiten auf dem HPC (siehe [Einführung ins Praktikum](https://bildungsportal.sachsen.de/opal/auth/RepositoryEntry/23165501449/CourseNode/101490883666782))!***\n" ] }, { @@ -534,7 +536,7 @@ "source": [ "train_score_knn = \n", "test_score_knn = \n", - "print(\"Tuned KNN - Training: {:.2f} % Test: {:.2f} %\".format(train_score, test_score))" + "print(\"Tuned KNN - Training: {:.2f} % Test: {:.2f} %\".format(train_score_knn, test_score_knn))" ] }, { @@ -577,7 +579,9 @@ "editable": false }, "source": [ - "Die Performance der unoptimierten SVM entspricht also ungefähr der des optimierten KNN. Aber auch Support Vector Machines haben Hyperparameter, die Sie optimieren sollten. Insbesondere die Wahl des Kernels und des Parameters $C$ (siehe Vorlesung)." + "Die Performance der unoptimierten SVM entspricht also ungefähr der des unoptimierten KNN. Aber auch Support Vector Machines haben Hyperparameter, die Sie optimieren sollten. Insbesondere die Wahl des Kernels und des Parameters $C$ (siehe Vorlesung).\n", + "\n", + "**Achtung:** Die Dauer des Trainings ist stark abhängig von der Größe des Parameters $C$. Für kleine Werte von $C$ kann das Training schon nach wenigen Sekunden abgeschlossen sein, während es bei großen Werten durchaus mehrere Minuten dauern kann. Wundern Sie sich also nicht, wenn die Kreuzvalidierung zwischendurch \"eingefroren\" erscheint." ] }, { @@ -762,7 +766,7 @@ "editable": false }, "source": [ - "Wir stellen fest, dass das Ranking der Klassifikatoren sich etwas verändert hat: Zwar ist der Nächste Nachbarn-Klassifikator noch immer der beste, aber das MLP ist nun leicht hinter der SVM gelandet. Die Fehlvorhersagen des MLP liegen also offenbar öfter weiter daneben, als die der SVM.\n", + "Wir stellen fest, dass das Ranking der Klassifikatoren sich etwas verändert hat: Zwar ist der Nächste Nachbarn-Klassifikator noch immer der beste, aber das MLP ist nun leicht hinter der SVM gelandet. Die falschen Vorhersagen des MLP liegen also offenbar öfter weiter daneben, als die der SVM.\n", "\n", "**Wichtig:** Wir haben bei dieser Vorgehensweise nun ganz am Ende unser Gütekriterium verändert. Sinnvoller wäre es, bereits im Training die \"One-Off Accuracy\" zur Bewertung der Modell zu verwenden. Dazu müssten Sie nur eine Funktion ```one_off_accuracy(model, X, y)``` definieren, und diese bei der Instanziierung des ```GridSearchCV```-Objekts im Parameter ```scoring``` übergeben. Funktionen sind in Python ganz normale Objekte und können daher genau wie jedes andere Objekt einfach durch ihren Namen übergeben werden. Probieren Sie es doch einfach mal aus!" ] @@ -796,7 +800,7 @@ "# Gittersuche durchführen\n", "\n", "# Ausgabe der Performance\n", - "print(\"Tuned KNN: {:.2f} %\".format(one_off_accuracy(knn_model, X_test, y_test)*100))" + "print(\"Tuned KNN: {:.2f} %\".format(one_off_accuracy(knn_model, X_test, y_test)))" ] }, { @@ -811,7 +815,7 @@ "# Gittersuche durchführen\n", "\n", "# Ausgabe der Performance\n", - "print(\"Tuned SVM: {:.2f} %\".format(one_off_accuracy(svm_model, X_test, y_test)*100))" + "print(\"Tuned SVM: {:.2f} %\".format(one_off_accuracy(svm_model, X_test, y_test)))" ] }, { @@ -827,7 +831,7 @@ "\n", "# Ausgabe der Performance\n", "\n", - "print(\"Tuned MLP: {:.2f} %\".format(one_off_accuracy(mlp_model, X_test, y_test)*100))" + "print(\"Tuned MLP: {:.2f} %\".format(one_off_accuracy(mlp_model, X_test, y_test)))" ] }, {