In diesem PoC wird anhand von Beispiel Daten der Federated Learning Ansatz aufgezeigt. Die Beispieldaten stammen von der Kaggle Santander Product Recommendation Competition.
Hier ein Auszug von der Kaggle Website
In this competition, you are provided with 1.5 years of customers behavior data from Santander bank to predict what new products customers will purchase. The data starts at 2015-01-28 and has monthly records of products a customer has, such as "credit card", "savings account", etc. You will predict what additional products a customer will get in the last month, 2016-06-28, in addition to what they already have at 2016-05-28. These products are the columns named:ind_(xyz)_ult1, which are the columns #25 - #48 in the training data. You will predict what a customer will buy in addition to what they already had at 2016-05-28.
Was ist Federated Learning?
Define
$N$ data owners${F1, ...FN }$ , all of whom wish to train a machine learning model by consolidating their respective data${D1, ...DN }$ . A conventional method is to put all data together and use$D = D1 ∪ ... ∪ DN$ to train a model$M_{SUM}$ . A federated learning system is a learning process in which the data owners collaboratively train a model$M_{FED}$ , in which process any data owner$F_i$ does not expose its data$D_i$ to others. In addition, the accuracy of$M_{FED}$ , denoted as$V_{FED}$ should be very close to the performance of$M_{SUM}$ ,$V_{SUM}$ . Formally, let$\delta$ be a non-negative real number, if$$| V_{FED} − V_{SUM} | < \delta$$ we say the federated learning algorithm has$\delta$ -accuracy loss. Yang, Federated Machine Learning:Concept and Applications (2019)
Grundsätzlich gibt es 3 Arten von Federated Learning.
Ein Produktion Ready Federated Learning System müsste wie folgt aussehen. Doch das vorrangige Ziel ist es zu beweisen, dass wir bessere Ergebnisse erzielen, wenn Modelle gemeinsam trainiert werden, ohne dass ein Daten Austausch kommt. Deshalb wird in diesem PoC Federated Learning wie Distributed Maschine Learning Problem behandelt mit unterschiedlichen Data Owner.

Für die Umsetzung von Federated Learning verwenden wir XGBoost bzw. LightGBM. Beide sind Gradient Boosting Trees. Für all jene die einen refresher benötigen findet ihr hier ein paar sehr informative Youtube Videos. Im Wesentlichen besteht XGBoost aus einer Serie von Decision Trees. Dabei ist jeder Tree in Reihe geschaltet und versucht die Residuen vom vorherigen Tree zu minimieren. Stark vereinfacht funktioniert XGBoost wie folgt:
- berechne den Weighted Quantile Sketch:
- Hierzu wird lokal (in unserem Fall) die Distribution von jedem Feature berechnet und an den Parameterserver gesendet.
- Dieser wiederum approximiert die globale Distribution von jedem Feature und gibt, vor welche Splits geprüft werden müssen.
- berechnen der Splits: Loakal werden nun die verschiedenen Splits berechnet für die verschiedenen Features. Die Resultate werden an den Parameterserver gesendet
- globales Modell: Nun wird anhand der Resultate ein globales Model aufgebaut und an die lokalen Nodes verteilt.
- nun wird mit Schritt 1 wieder begonnen.
Wie weiter oben beschrieben ist das Ziel die zusätzlich gekauften Produkte im Monat vom 2016-06-28 zu bestimmen. Die Daten beinhalten Monatsdaten von 2015-01-28 - 2016-05-28 (ca. 1.5 Jahre). Nun gäbe es mehrere Möglichkeiten das ML Problem zu formulieren:
- wir versuchen immer die gekauften Produkte des nächsten Monats zu bestimmen
- wir versuchen immer die gekauften Produkte für den Juni jeweils anhand des Vormonats zu bestimmen (ignorieren alle anderen Monate).
- wir trainieren ein Recommender System mit allen Daten der Produkte und versuchen den letzten Monat vorherzusagen.
In den Notebooks 01_data_preprocess.ipynb und 02_data_Cleaning.ipynb werden die Daten aufbereitet. Da dieses Datenset recht gross ist, werden zuerst alle Daten in integer umgewandelt. Das Ziel ist es Floats- und Character Daten möglichst zu vermeiden, da diese den DataFrame unnötig aufblähen. Im Notebook 02 wird noch bei einzelnen Features die Nans ein wenig "smarter" bereinigt.
Das Notebook 03_features.ipynb macht mehrere Dinge.
- Zielvariablen: Das ML Problem lautet vorherzusagen, welche Produkte von einem Kunden im nächsten Monat zusätzlich erworben werden. Um dies festzustellen muss der aktuelle Monat mit dem Vormonat verglichen werden, um zu sehen ob ein neues Produkt erworben wurd.
- Produkt Features: Neben den vorhandenen Features, macht es natürlich Sinn auch die Produkte selbst als Features zu definieren. Z.B. Kreditkarte Vormonat: hatte der Kunde im Vormonat eine Kreditkarte ist das eine wichtige Info.
- reverse Dummy Variable: Es ist natürlich möglich, für jedes Produkt einen Boosting Tree zu trainieren. Allerdings ist das nicht effizient. Im Prinzip handelt es sich um eine Classification-Problem. Wir wollen die Top 7 Produkte vorhersagen, wenn wir für jedes Produkt einen Boosting Tree entwerfen fehlt die Vergleichbarkeit und wir können keine Rangordnung festlegen. Darum wurden alle Produkte in einer Zielvariable
ygespeichert. Wenn nun ein Kunde 2 Produkte erworben hat in einem Monat, so hat dieser zwei Zeilen in diesem Monat anstatt vorher eine Zeile. - entfernen der Daten ohne neuem Produkt: Ziel ist es die Top 7 Produkte vorzuschlagen. Daher macht es aus meiner Sicht keinen Sinn Einträge, ohne neuen Produkten, zu berücksichtigen zumal unsere Erfolg auch mit APK gemessen wird.
- Train Test Split:
Das Ziel dieser Kaggle Challenge ist es die neuen Produkte für die Periode 2016-06-28 vorherzusagen. Dazu haben sie das Datenset in ein Testset (Grunddaten von der Periode 2016-06-28) und Trainingset (Daten von 2015-01-28 bis 2016-05-28) aufgeteilt. Leider kennen wir die wahren Werte von dem Testset der Periode 2016-06-28 nicht, weshalb wir diesen Datenpunkt ignorieren werden und Train und Testset wie folgt aufteilen werden.

In diesem Notebook wird ein Basismodel bestimmt und evaluiert.
-
Trainieren: Hierzu wird ein Standard XGBoost Model hergenommen und trainiert. Die erzielten Resultate lassen sich mit denen auf Kaggle vergleichen.
-
Evaluierung vom Testset:
Für die Evaluierung wird der Mean Average Precision @ 7 (MAP@7) hergenommen. Die untenstehenden Formel haben wir uns von jturkewitz ausgeliehen. Hier noch eine gute Erklärung.
-
Aufteilen der Daten Um die Daten möglichst konsistent zu teilen, werden wir für jede Kundenid den ursprünglichen Wohnort ermitteln. Wenn nun ein Kunde die Region in dem Untersuchungszeitraum wechselt, so wird nur der ursprüngliche Wohnort ausgewertet. So können wir sicherstellen, dass wir keine Daten durch die Aufteilung verlieren. In dem Bild weiter unten sind die verschiedenen Regionen zu sehen. Wir werden versuchen Spanien in nördliche und südliche Regionen aufzuteilen.

-
Berechnung von einem Ensemble: Nachdem wir die Daten in einen Region-Süd und in eine Region-Nord aufgeteilt haben. Trainieren wir jeweils ein Model mit den jeweiligen Daten.
Hierfür baute ich einen Cluster aus drei Cotnainern welche mittels OpenMPI (Message Passing Library) miteinander kommunzieren. Hierfür musste LightGBM (MPI Version kompiliert werden). Der Cluster besteht aus 1 Head Node und 2 Compute Nodes. Der eine Node bekam die Daten von Region Süd und der andere von der Region Nord.
Wir konnten feststellen, dass moderne Algorithmen wie XGBoost und LightGBM geeignet sind für Federated Learning. In der einfachsten Umstzung als Distributed Learning Algorithmen ergab sich jedoch kein eindeutiger Mehrwert. Dennoch bin ich überzeugt, das bei gewissen ML Modellen es durchaus Sinn macht die Daten zu teilen und einen Federated Learning Ansatz (Distributet Learning) zu wählen.
Obwohl in diesem Beispiel der Mehrwert nicht eindeutig ist, könnte ich mir einen Mehrwert bei Customer Churn vorstellen. Hierzu wäre z.B. https://www.kaggle.com/c/kkbox-churn-prediction-challenge/data oder https://www.kaggle.com/blastchar/telco-customer-churn.
import pandas as pd
df = pd.read_csv('data/final/results_df.csv', index_col=0)
df.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
| model_south | model_north | model_all | model_south_north_combine | distributed_lgbm_training | |
|---|---|---|---|---|---|
| test_south | 0.026727 | 0.026502 | 0.026690 | 0.026649 | 0.026444 |
| test_north | 0.017951 | 0.018017 | 0.017983 | 0.018006 | 0.017836 |
| test | 0.023006 | 0.022904 | 0.022998 | 0.022984 | 0.022794 |
In order to test it do the following:
- (optional) I strongly recommend to create an environment with virtualenv or conda
- Clone this repo
- run
python setup.py installto install all needed libraries - next you can run the
jupyter notebookand call the displayed URL


