Machine Learning Modelle - MrJaimba/Projektseminar Wiki

Ansprechpartner
Philipp Höppner

Für die Durchführung der Angebotspreisvorhersagen von Immobilien wurden im Verlauf des Projekts die Regressionsmodelle XGB Regressor, Gradient Boosting Regressor, Random Forrest Regressor und Voting Regressor ausgewählt. Dabei dienen die drei erst genannten Modelle als Basis für den Voting Regressor. Dieser bildet ein Ensemble und berechnet einen gewichteten Durchschnitt der Basismodelle, um noch genauere Vorhersagen durchführen zu können. Für die Umsetzung der Modelle wurden in erster Linie die Python Packages scikit-learn und xgboost verwendet. Außerdem kommt zur Speicherung der Modelle das Package pickle und zur Generierung von Grafiken das Package matplotlib.pyplot zum Einsatz. Folgende Ausführungen beziehen sich auf die Dateien machine_learning.py, sowie model_training.py und beschreiben die Machine Learning Pipeline des Projekts.

Modellinformationen

XG Boost ist eine Softwarebibliothek, die in den letzten Jahren im Rahmen von Machine Learning Projekten eine immer größere Bedeutung bekommen hat. Grund dafür ist zum einen die hohe Ausführungsgeschwindigkeit der unterliegenden Algorithmen zum Training von baumbasierten Machine Learning Modellen mittels Gradient Boosting (Erklärung zu Gradient Boosting s. Hausarbeit - Machine Learning Ansätze, S.17-18). Zum anderen ist die Model Performance im Vergleich zu anderen Modellen auf tabellarischen Datensätzen ausgesprochen gut. Hierbei dominiert XG Boost Klassifikations- oder Regressionsproblemen (s. machinelearningmastery). Aufgrund dieser Vorteile wurde sich beim vorliegenden Regressionsproblem für den XGB Regressor entschieden.

Der Gradient Boosting Regressor basiert auf demselben Konzept wie der XGB Regressor, dem Gradient Boosting. Dieser ist allerdings Teil der Funktionen von scikit-learn und kein eigenständiges Python Package. Weiterhin konnten in Tests mit diesem Regressor ähnlich gute Ergebnisse erzielt werden wie mit XG Boost. Die Vorhersagewerte für Immobilien verschiedener Art und Lage lagen in der Regel nicht weit auseinander. Daher wurde sich dazu entschieden, diesen bei der Ermittlung des finalen Vorhersagewertes durch den Voting Regressor mit aufzunehmen.

Der Random Forrest Regressor ist ebenfalls ein Teil von scikit-learn und ist ein Bagging Verfahren. Bagging (Bootstrap Aggregating) hat zum Ziel mehrere unabhängige Modelle zu kombinieren, um ein neues Modell zu trainieren, das robuster als die Modelle ist, aus denen es aufgebaut wird. Das heißt, dass die Variance reduziert werden soll. Dabei besteht zunächst das Problem, dass verschiedene Datensätze vorliegen müssten, um wirklich unabhängige Modelle zu trainieren. Dies wird gelöst, indem mit Hilfe von statistischen Verfahren aus dem ursprünglichen Datensatz einzelne Proben extrahiert werden, die eine ähnliche Datenverteilung aufweisen und repräsentativ sind. Mit diesen werden die einzelnen Modelle trainiert und aus dem Durschnitt der Vorhersagewerte wird das finale Vorhersagemodell berechnet. Random Forrest wendet dieses Verfahren auf Entscheidungsbäume zur Lösung von Klassifikations- oder Regressionsproblemen an (s. towardsdatascience). Dieses Modell liefert in Tests indiviuell betrachtet und den RMSE, sowie den R2-Score betreffend schlechtere Ergebnisse als die zuvor genannten Modelle. Allerdings wurde festgestellt, dass durch die Berücksichtigung dieses Modells der Vorhersagefehler des Voting Regressors verbessert werden kann.

Außerdem bestand noch die Idee einen Stacking Regressor zu verwenden und die drei Basismodelle aufeinander zu stapeln. Nach mehreren Tests, die zeigten, dass dieser Regressor auch durch Parameter Tuning keine Vorhersagefehlerverbesserung im Vergleich zum Voting Regressor zeigte, wurde sich dazu entschlossen den Stacking Regressor nicht ins finale Build mit einzubinden. Zudem brachte dieses Modell erhebliche Performanceeinbußen mit sich, da die Berechnung mehr als 20 Minuten dauerte. Der Code zu diesem Modell wurde zu Archivierungszwecken nur auskommentiert und nicht gelöscht.

Methode print_feature_importances(model, data, save_string)

Diese Methode dient der Visualisierung der modellspezifischen Feature Importances. Dabei werden die zehn einflussreichsten Features der Modelle selektiert und in einem Balkendiagramm dargestellt.

Die Feature Importance kann in den drei Maßen Gain, Cover und Weight abgebildet werden. Für die Abbildung wurde der Standardwert Weight ausgewählt, welcher beschreibt, wie oft eine Feature in Splits der Regressionsbäume des verwendeten Modells auftritt. Die resultierenden Grafiken werden in einem entsprechenden Ordner abgelegt (s. towardsdatascience). Die benötigte Grafik wird anschließend im User Interface abhängig vom ausgewählten Machine Learning Modell aus diesem Ordner geladen und angezeigt.

In der Methode werden die drei Parameter model, data und save_string übergeben. Der Parameter model ist das Machine Learning Modell, auf dessen Basis die Feature Importance Grafik erzeugt werden soll. Im Parameter data werden die Inputdaten übergeben, um die Spaltennamen für die Bezeichnung der Grafik zu erhalten. Abschließend erhält die Methode noch im Parameter save_string den Pfad, der auf den Ordner verweist, in welchem die erzeugte Grafik abgelegt werden soll.

Methode outlier_treatment(datacolumn) und outlier_drop(imputed_data)

Diese beiden Methoden dienen dem Aussortieren von Ausreißern aus dem Inputdatensatz. Der Methode outlier_treatment wird eine Spalte des Datensatzes übergeben, um anschließend die Werte für die obere und untere Wertgrenze der Spalte zu berechnen. Diese wurde zuvor vom Projektteam nach der EDA des Datensatzes festgelegt. In der Methode outlier_drop werden diese Werte genutzt, um die entsprechenden Zeilen, die unter bzw. über der Wertgrenze liegen, zu entfernen. Dazu wird der Methode der Inputdatensatz übergeben.

Methode boolean(imputed_data)

Dieser Methode wird der Inputdatensatz übergeben, um die Spalten des Inputdatensatzes mit binären Ausprägungen als 1 oder 0 zu codieren. Dieser Schritt muss erfolgen, um diese Spalten für das Training von Machine Learning Modellen verwenden zu können, da das Package scikit-learn dabei nur nummerische Werte akzeptiert.

Methode tr_te_spl(imputed_data)

Diese Methode führt den Train-Test-Split der Inputdaten aus. Dabei wird der ursprüngliche Datensatz in Trainings- und Testdaten aufgeteilt. Hier wurde sich auf eine Testgröße von 20% fesgelegt, um die Machine Learning Modelle auf einer möglichst großen Datenbasis zu trainieren. Die Trainingsdaten werden genutzt, um das jeweilige Modell zu trainieren. Mit den Testdaten erfolgt anschließend die Überprüfung der Güte des Modells anhand ausgewählter Fehlermaße. Die Methode gibt die Parameter x_test, x_train, y_test und y_train zurück. Mit dem Buchstaben x werden die Features gekennzeichnet, die zur Vorhersage des Angebotspreises verwendet werden. Der Buchstabe y kennzeichnet die zu vorhersagende Variable, den Angbotspreis.

Methode numeric(x_train, x_test), normalisation(x_train_num, x_val_num) und standardization(x_train_num, x_val_num)

Diese Methoden dienen der weiteren Bearbeitung der nummerischen Werte des Datensatzes. Zunächst werden in der Methode numeric die nummerischen Spalten der übergebenen Daten bestimmt. Dabei werden die zuvor bereits in der Methode boolean bearbeiteten Spalten nicht berücksichtigt. Diese müssen nicht weiter bearbeitet werden. Die Methode erhält die Trainings- und Testdaten der zur Vorhersage verwendeten Features und gibt nur die nummerischen Spalten zurück.

Die Methoden normalisation und standardization erhalten jeweils die Rückgabewerte der Methode numeric. Diese werden von den Methoden anschließend normalisiert oder standardisiert. Hierbei ist zu beachten, dass diese Methoden sich gegenseitig ausschließen. Ein Datenatz kann nicht gleichzeitig normalisiert und standardisiert werden. Die Ausführung erfolgt in der Methode training_pipeline(). Hier werden entweder die Normalisierung oder die Standardisierung der Daten auskommentiert.

Methode category(x_train, x_test) und target_encoding(x_train_cat, x_val_cat, y_train)

Diese Methoden dienen der Codierung der kategorischen Features mit mehr als zwei Ausprägungen. Dazu filtert die Methode category diese Features aus den übergebenen Datensätzen und gibt diese zurück. Die kategorischen Features werden anschließend der Methode target_encoding übergeben, um diese nach dem Prinzip des Target Encoding zu codieren. Es wurde sich für diese Methode entschieden, da diese in Tests die besten Ergebnisse liefert. Verfahren wie One-hot Encoding produzieren zu viele neue Spalten und vergrößern den Vorhersagefehler. Die Methode gibt den codierten Datensatz wieder zurück.

Im Zuge dessen besteht die Problematik, dass kategorische Features, die im User Interface von Nutzern eingegeben werden, mit denselben Werten codiert werden müssen, wie im Trainings- und Testdatensatz. Dazu werden in dieser Methode Referenztabellen angelegt, die die ursprüngliche Ausprägung der kategorischen Features und die Codierung speichern. So kann die Codierung im User Interface aus diesen Tabellen ausgelesen und die nicht-nummerischen Werte ersetzen.

Methode joint(x_train_num, x_train_target, x_val_num, x_val_target)

Dieser Methode werden die codierten nummerischen und kategorischen Datensätze übergeben. Diese werden nun wieder zu einem gesamten Datensatz zusammengeführt, der dann für das Training der Machine Learning Modelle verwendet werden kann.

Methode ml_tests(x_train, x_test, y_train, y_test, imputed_data)

Mit Hilfe dieser Methode werden die ausgewählten Machine Learning Modelle trainiert und im Ordner ML_Modelle gespeichert. Hierbei ist zu beachten, dass die Modelle teilweise eine Größe von über 250 MB erreichen, was das maximale Größenlimit einer Datei für den Upload auf GitHub überschreitet. Deshalb müssen die Modelle zunächst erzeugt werden, um diese in der Anwendung nutzen zu können. Dazu muss die Methode training_pipeline() einmal ausgeführt werden.

Den Modellen werden im Training Werte für die Parameter übergeben, die sich aus intensivem Parameter Tuning ergeben haben und die besten Ergebnisse liefern. Zusätzlich wird für jedes Modell der jeweilige R2-Score und RMSE berechnet, sowie ausgegeben. Diese werden am Schluss in einer separaten Grafik zusammengefasst, um ein Ranking der verschiedenen Modelle zu erstellen. Die Grafiken werden in diesem Ordner gespeichert und im User Interface abhängig vom ausgewählten Modell geladen und angezeigt. Außerdem wird für jedes Modell die jeweilige Feature Importances Grafik generiert.

Der Methode werden die fünf Parameter x_train, x_test, y_train, y_test und imputed_data übergeben. Die Trainings- und Testdaten haben sich aus den vorherigen Methoden ergeben und werden nun eingesetzt. Mit imputed_data werden die Inputdaten übergeben, um die Spaltennamen zur Bezeichnung der Feature Importances Grafiken zu erhalten.

Methode training_pipeline()

Diese Methode dient als übergreifende Funktion zur Ausführung der Machine Learning Pipeline. Zuerst wird mit der Methode setup_database eine sichere Verbindung zur Datenbank hergestellt, um benötigte Daten zu laden und angepasste Datensätze speichern zu können. Darauf folgt die Ausführung der zuvor unter dem Eintrag "Datenbearbeitung" beschriebenen Methoden zum Data Engineering und zur Data Imputation, sowie der in diesem Eintrag behandelten Funktionen. Dabei werden sich ausschließende Methoden auskommentiert. Außerdem werden in dieser Methode Testausgaben zur Überprüfung der Funktionalität vorgenommen. Nach Durchlauf der Methode wurden alle nötigen Modelle, Grafiken und Dateien zur Anwendung im User Interface erzeugt. Im nächsten Schritt kann dieses aufgerufen und begutachtet werden.

Ansprechpartner
Yanina Budnik

Feature Auswahl

Der Immobiliendatensatz nach der Datenbereinigung enthält folgende Features: angebotspreis, anzahl_badezimmer, anzahl_parkplatz, anzahl_zimmer, aufzug, barrierefrei, baujahr, energietyp, breitengrad, einwohner, energie_effizienzklasse, gaeste_wc, grundstuecksflaeche, heizung, immobilienart, immobilienzustand, laengengrad, plz, terrasse_balkon, unterkellert, vermietet, wohnflaeche. Für sie ergibt sich folgendes Korrelationsbild (PLZ und Baujahr sind hier kategorisch):

Mit dem Angebotspreis am stärksten korreliert ist die PLZ, die Wohnfläche und die Immobilienart, einen sehr schwachen Zusammenhang zeigen die Features vermietet, unterkellert, aufzug, barrierefrei und terrasse_balkon. Um die Auswirkungen der einzelnen Features auf MAE und RSME der ausgewählten Machine Learning Modelle zu untersuchen, wurden die Modelle zuerst lediglich mit den Features Anzahl Zimmer, Anzahl Parkplatz, Anzahl Badezimmer, Grundstücks- und Wohnfläche trainiert, danach wurden weitere Features einzeln hinzugefügt:

Bei allen drei Algorithmen fällt auf, die RSME- und die MAE-Werte stagnieren, wenn Features mit einem schwachen Korrelationswert hinzugefügt werden. Das Projektteam hat sich in Absprache mit den Betreuern jedoch gegen das Verwerfen dieser Features aus folgenden Gründen entschieden:

Die obigen Werte beziehen sich auf diesen Datensatz, der den Immobiliendatenbestand von Januar/Februar aufweist, kategorische Features sind als Dummys encodet. Die Algorithmen-Parameter können hier eingesehen werden. Weitere Werte der Feature-Tests finden sich hier (Tabelle 1).

Ausreißer Handling

Der Boxplot zeigt die Verteilung der Angebotspreise des aktuellen Immobiliendatenbestandes:

Anhand der Punkte, die als Ausreißer identifiziert wurden, erkennt man, dass die Preisspanne dieser ziemlich weit ist. Die Angebotspreise von 75% der 13.221 Dateneinträge liegen unter einem Wert von 750.000€ und bereits das obere 1% der Angebotspreise deckt einen Bereich ab, der sich zwischen 3.888.780€ und 30.000.000€ bewegt:

Den oberen Grafiken, in denen die Fehlerwertverläufe dargestellt sind, lässt sich gut entnehmen, dass diese Fehlerwerte sich deutlich reduzieren, wenn Ausreißer aus dem Datensatz werden. Zur Festlegung der Ober- und der Untergrenze des Ausreißerbereiches wurde die IQR Methode verwendet. IQR steht für Inter-Quartile Range und bildet die Differenz zwischen dem 75%-Quantil und dem 25%-Quantil. Für die Untergrenze wird der IQR-Wert multipliziert mit 1,5 vom Wert des 25%-Quantils abgezogen, für die Obergrenze zu 75%-Quantil hinzu addiert. Die Anwendung findet statt in der bereits beschriebenen Methode outlier_treatment. Für unsere Daten ist die Untergrenze negativ, trotz des niedrigen Angebotspreisminimums von 10.000€, die Obergrenze liegt bei etwa 1.400.000€.

Encoding

Als Encodingvarianten für die kategorischen Variablen wurden nur Dummys, Target Encoding, Targetencoding und Dummys (für JA/NEIN Variablen), CatBoost und One Hot Encoding getestet. LabelEncoding und OrdinalEncoding wurden als Varianten verworfen, da diese kategorischen Ausprägungen in diesen als Zahlen kodiert werden, die von den Modellen fälschlicherweise als Skalen interpretiert werden könnten (towardsdatascience.com , machinelearningmastery.com). Bis auf die Energieeffizienzklasse stehen die kategorischen Ausprägungen der Immobiliendaten (Immobilienart, Heizung, etc.) jedoch in keiner Beziehung zueinander. Die nachfolgende Tabelle zeigt die RSME-Werte der verschiedenen Encoding Varianten, die aus diesem Datensatz entstehen, der dem Immobiliendatenbestand vom März zeigt. Die Parametereinstellungen von Algorithmen etc. können unter diesem Link eingesehen werden.

Random Forest Gradient Boosting Regressor XGB Regressor
Dummy 140634 140428 158080
Target Encoding 157143 138588 153103
Target Encoding und Dummy 158052 141061 155700
CatBoost 157412 146498 157031
One Hot Encoding 140619 142344 157644

Gradient Boosting Regressor und XGB Regressor erreichen unter Target Encoding im Vergleich zu anderen Varianten leicht bessere RSME Werte, Random Forest dagegen erreicht seinen Bestwert auf Dummy-encodeten Daten bzw. mit One Hot Encoding. Dadurch ergibt sich jedoch eine lange Durchlaufzeit (ca. 1 Minute, wenn Target Encoding und >20 Minuten mit Dummys), weswegen sich auf bei Random Forest für die Verwendung von Target Encoding entschieden wurde.

Die nächste Tabelle zeigt die RSME Werte auf dem neuesten Datenbestand, hier zeigt sich wieder, dass Random Forest die besten Ergebnisse mit Dummys erreicht. Gradient Boosting Regressor erreicht den besten Wert unter Verwendung von CatBoost Encoding und der XGB Regressor unter Verwendung von One Hot Encoding. Da Ergebnisunterschiede zum einen marginal sind und One Hot Encoding mit einem Durchlaufzeitnachteil verbunden ist, wird weiterhin Target Encoding verwendet.

Random Forest Gradient Boosting Regressor XGB Regressor
Dummy 134907 136489 144935
Target Encoding 146184 135088 143933
Target Encoding und Dummy 146819 133724 143998
CatBoost 142477 133025 141955
One Hot Encoding 135135 133408 139113

Standardisierung und Normalisierung

Auf den Daten werden Normalisierung und Standardisierung angewendet. Unter Normalisierung versteht man das Skalieren der Werte, so dass sie zwischen 0 und 1 liegen, unter Standardisierung werden die Werte so transformiert, dass ihr Mittelwert 0 und die Standardabweichung 1 werden (analyticsvidhya.com). Unsere Modelle haben sich gegenüber diesen Techniken als unempfindlich gezeigt. Die nachfolgenden Tabellen zeigen die RSME Werte unter Target Encoding, für andere Encoding Varianten können die Werte hier eingesehen werden (Tabellenblatt IQR), die Notebooks finden sich hier.

Random Forest Gradient Boosting Regressor XGB Regressor
Target Encoding 157143 138588 153103
+Standardisierung 157132 139681 153083
Random Forest Gradient Boosting Regressor XGB Regressor
Target Encoding 139815 125661 142208
+Standardisierung 139799 127499 142171
Random Forest Gradient Boosting Regressor XGB Regressor
Target Encoding 146819 133724 143998
+Standardisierung 146155 135200 143940
Random Forest Gradient Boosting Regressor XGB Regressor
Target Encoding 157143 138588 153103
+Normalisierung 157131 139015 153103
Random Forest Gradient Boosting Regressor XGB Regressor
Target Encoding 139815 125661 142208
+Normalisierung 139767 127397 142216

aktueller Datenbestand und Normalisierung:

Random Forest Gradient Boosting Regressor XGB Regressor
Target Encoding 146819 133724 143998
+Standardisierung 146188 135809 143914

Logarithmierung

Der Immobiliendatensatz enthält zwei stetige Features, die Wohn- und die Grundstücksfläche, betrachtet man deren Verteilung, so fällt auf, dass diese rechtsschief ist. Vor allem die Grundstückswerte decken einen sehr weiten Bereich ab, 75% der Werte liegen jedoch unter knapp 900 Quadratmetern.

Wendet man Logarithmierung an, so werden die Abstände zwischen den Werten verringert, so dass sich die Verteilung einer Normalverteilung annähert:

Die nachfolgenden Tabellen zeigen wieder die RSME Werte für

Random Forest Gradient Boosting Regressor XGB Regressor
Target Encoding 157143 138588 153103
+Logarithmierung (Grundstück) 157265 140465 156245
+Logarithmierung (Wohnfläche) 157142 138651 153966
+Logarithmierung (Grundstück und Wohnfläche) 157164 139984 155136
Random Forest Gradient Boosting Regressor XGB Regressor
Target Encoding 146819 133724 143998
+Logarithmierung (Grundstück) 146154 133748 141535
+Logarithmierung (Wohnfläche) 146274 134833 144763
+Logarithmierung (Grundstück und Wohnfläche) 146061 134071 145523

Auch hier zeigt sich kein Verbesserungseffekt, die Notebooks für die Logarithmierung können hier eingesehen werden.

Ebenso wurde Logarithmierung auf dem Datenbestand Februar/März und Metadaten getestet, der Ausschnitt zeigt die RSME Werte:

Weitere Tests und Ideen

Weiterhin wurden folgende Tests durchgeführt, der Ausschnitt zeigt die RSME Werte:

Parameter-Tuning

Im letzten Schritt wurden die optimalen Parameter gesucht. Für Random Forest und Gradient Boosting Regressor kam für das Parameter-Tuning Grid Search zum Einsatz, folgende Parameter wurden damit optimiert:

Für die Parameteroptimierung des XGB Regressors wurde XGBoost API genutzt, die die Funktion xgb.cv (Kreuzvalidierung) und die Parameter num_boost_round und early_stopping_rounds enthält. Der Parameter num_boost_round definiert die Höchstanzahl der boosting Runden bei der Parametersuche. Mit jeder neuen Runde wird ein neuer RSME Wert ausgerechnet, mit early_stopping_rounds wird definiert nach wie vielen Runden ohne einen besseren RSME Wert die Parametersuche abgebrochen wird. Folgende Parameter werden damit optimiert:

Die Einzelheiten der Parameteroptimierung können hier eingesehen werden.