Tech Talk: "Vorhersage der Verpackungsgröße" mit Lilly Adlgasser & Michael Heininger von niceshops

Tech Talk: "Vorhersage der Verpackungsgröße" mit Lilly Adlgasser & Michael Heininger von niceshops

Ja cool, dann fange ich gleich an. Hi, servus! Ich bin die Lilly, ich bin da mit meinem Kollegen, dem Michi – frisch gebackener Diplomingenieur. Und der Michi erzählt euch heute ein bisschen über seine Masterarbeit, die er bei uns in der Firma geschrieben hat. Gleich einmal zur Info für euch: wir arbeiten beide bei der Firma niceshops, das ist ein e-commerce Unternehmen in der Südost-Steiermark. Und der Michi ist der Back End Entwickler und Experte in unserer eigens entwickelten Warenwirtschafts- und Lagersystemsoftware. Ich will gar nicht zu viel weiterreden, Michi, gehen wir gleich voll ins Theme rein – über was möchtest du heute genau reden?

Ich täte heute gerne meine Masterarbeit vorstellen. Generell ist das in einem Projekt im Unternehmen durchgeführt worden. Es handelt um die Vorhersage der Verpackungsgröße einer Lieferung – und das mittels Machine Learning. Im Detail würde ich auf drei verschiedene Punkte eingehen. Zum einen mal zur Entwicklung vom Vorhersagesystem. Dann vom Deployment vom Modell. Abschließend dann die Integration in die bestehende Lagersoftware.

Ja cool! Magst du gleich einmal erzählen wie du zu dem gekommen bist? Warum, was waren da so die Pain Points bei uns, dass du dir dieses Thema ausgesucht hast?

Also, wir versenden über 20.000 Pakete jeden Tag, an über 1 Million Kunden. Diese Pakete müssen da natürlich auch verpackt werden. Bei uns schaut das so aus – da ist das User Interface dargestellt. Im rechten Bereich befindet sich der Warenkorb mit den Produkten, die man dann verpacken muss. Hierbei relevant der linke Bereich – das sind die verschiedenen Verpackungsgrößen, die Typen, in die die Produkte dann verpackt werden können. Und mit einer Vorhersage der Verpackungsgröße kann man dann eben den Lagerarbeiter unterstützen, man kann ihm auch eine Submenge von 40 verschiedenen Größen geben. Und es ist ein Vorteil vom Prozess her. Weiters kann man, wenn man weiß welche Lieferungen man hat – in welcher Verpackungsgröße die Lieferung dann versendet wird – dann kann man pro Lieferdienst quasi das Transportvolumen bereits vorab bestimmen und dann die Anzahl der Fahrzeuge pro Lieferdienst bestimmen.

Cool! Du hast dich entschieden das mit Machine Learning zu machen, wie bist du auf das gekommen?

Generell haben wir uns für Machine Learning entschieden, weil die Daten im Unternehmen seit einiger Zeit schon aufgezeichnet worden sind. Das heißt man hat Daten von historischen Lieferungen, entsprechend der Verpackungsgröße. Machine Learning ist natürlich sehr gut im Erkennen von Zusammenhängen in großen Mengen von Daten. Deswegen haben wir uns für Machine Learning entschieden. Weiters sind im Unternehmen auch die Dimensionen der Produkte nicht oft hinterlegt – das heißt Verpackungsgröße nur auf Basis der Produktdimensionen auswählen ist nicht möglich.

Hast du vorher schon Erfahrung damit gehabt?

Nein, ich bin eigentlich Software Entwickler, habe Industrielogistik studiert, habe dann ein Interesse für Data Science, für Machine Learning entwickelt. Habe mich dann jetzt in den letzten Monaten im Rahmen der Masterarbeit damit beschäftigt. Habe natürlich – sagen wir mal so – nur an der Spitze des Eisberges gekratzt, was das ganze Feld betrifft. Dementsprechend ist dann der Fokus von dem Projekt dann auch auf der Integration – also einfaches Modell entwickeln und das dann in unsere bestehende Software zu integrieren.

Also mal so vom Anfang an, wie bist du dann das ganze Projekt angegangen?

Wir haben den Ablauf in drei Teile – kann man sagen – unterteilt. Zum einen zuerst war das Data Engineering, da haben wir die Daten erfasst. Wir haben ja verschiedene Shops, die eine eigene Datenbank haben. Die Daten haben wir dann über REST abgeholt, haben die Daten dann über Google Callup Notebook analysiert und dann auch aufbereitet. Mit Google Callup Notebook kann man Python Code im Browser schreiben und so schnell Daten analysieren.

Aus den aufbereiteten Daten haben wir dann Features ausgewählt, mit diesen Features dann die Modelle trainiert, die Modelle dann evaluiert und abschließend im Rahmen des Modell Deployments das Modell in die bestehende Software eingebunden. Dann ist es seit Kurzem im Einsatz im Lager.

Wir sehen hier viel von dem Modell, wie seit ihr die Entwicklung von dem angegangen?

Wir haben zuerst die Features einmal definieren müssen, mit denen wir dann das Modell trainiert haben. Da haben wir das Gewicht der Lieferung, die Anzahl der Produkte in der Lieferung ausgewählt. Zwei Flags – ein Flag, das angibt, ob es sich um eine Selbstabholung handelt, ein weiteres Flag, das angibt ob es sich um Kühlversand handelt. Und ein approximiertes Volumen. Mit diesen Features haben wir dann Modelle trainiert. Da haben wir Scikit Learn als Python Bibliothek verwendet, weil es für mich als Einsteiger sehr einfach war mit vorimplementierten Algorithmen verschiedene Modelle zu trainieren – unter anderem k-nearest neighbors Algorithmus ist da verwendet worden. Der Naive Bayes Algorithmus, Decision Trees und abschließend der Random Forest Algorithmus, mit dem wir die höchste Vorhersagegenauigkeit gehabt haben.

Wie war dann diese ganze Arbeit mit der Performance? Weil das hat ja sicherlich alles auf Anhieb immer supergut funktioniert!

Nein, auf Anhieb hat nicht alles funktioniert. Wir waren bei – bevor wir das approximierte Volumen gehabt haben – einer Vorhersagegenauigkeit von 50% bis 60%. Das war für den Einsatz im Lager zu wenig. Wir haben dann eben weiters noch Feature Engineering gemacht und sind dann auf die Idee des approximierten Volumens gekommen. Das haben wir uns ausgerechnet – das Paketvolumen ist bekannt, das Gewicht des Pakets ist bekannt. Dann haben wir uns das Volumsgewicht ausgerechnet. Das Gewicht des Produkts multipliziert mit dem Volumsgewicht ergibt dann eben ein approximiertes Volumen für das Produkt.

Ja cool. Ich gehe jetzt einmal davon aus, die Zahlen da oben, das ist quasi die „Endperformance“?

Genau, die Vorhersagegenauigkeit bei einer Größe gibt jetzt an, ob die tatsächliche Größe mit der vorhergesagten Größe übereinstimmt. Wir haben ja verschiedene Shops – das ist jetzt so ein Durchschnittswert über alle Shops hinweg. In manchen Shops funktioniert es besser, in manchen Shops funktioniert es schlechter.

Wir haben dann eine zweite Metrik definiert: die Vorhersagegenauigkeit bei 3 Größen. Die gibt an, ob die tatsächliche Größe unter den 3 wahrscheinlichsten Größen ist. Das ist für das Lager sehr relevant, weil man dem Lagerarbeiter eine Teilmenge – eben 3 Größen – aus über 40 verschiedenen Größen geben kann, was bei 95% schon sehr relevant ist.

Was waren dann die Next Steps? Das war jetzt das Modell, wie ist es dann weitergegangen?

Das Modell war jetzt trainiert in dem Fall. Jetzt haben wir dann das Modell auch in den Einsatz bringen müssen. Zuerst muss man dass hosten, damit man es anbinden kann. Wir haben uns für die Google AI Platform entschieden. Dort haben wir ein relativ neues, cooles Feature probiert, welches sich benutzerdefinierte Vorhersageroutine nennt. Der Vorteil von einer benutzerdefinierten Vorhersageroutine ist, dass man custom Python Code auf der Cloud ausführen kann. Man kann einen Predictor und einen Präprozessor definieren.

Zuerst einmal zum Präprozessor – der nimmt quasi die Vorhersageanfrage entgegen, also die Daten von einer Lieferung, bereitet die Daten dann auf. Zum Beispiel werden dann kategorische Werte in numerische Werte umgewandelt. Der Predictor – die zweite Python Klasse - ist das Hirn, die Steuereinheit mehr oder weniger, nimmt die Vorhersageanfrage entgegen, gibt es an den Präprozessor dann weiter und die aufbereiteten Daten werden dann weiter ans Modell gegeben und zusätzlich kann man dann wieder benutzerdefinierten Python Code definieren auf der Cloud, wie man dann reagiert, wenn ein Vorhersageergebnis vom Modell zurückkommt und das dann wieder zurückggibt.

Die zwei beiden Python Klassen werden dann zusammen zu einen Quelldistributionspaket zusammengeführt. Das ist im rechten oberen Teil des Codes dargestellt. Gemeinsam mit dem Modell wird das dann auf die Cloud gespielt. Wie man sehen kann ist es recht einfach – wir haben da die Interaktion zwischen Google Callup wiederum und der Google Cloud – der AI Platform – und über 4 Zellen in dem Fall, wo man Namen noch vergibt vom Modell und die Versionsnummer, kann man das eben aus Google Callup auf die Google Cloud spielen.

Ja voll cool! Wir arbeiten ja bei Niceshops relativ wenig mit Python, wie war da dann der Integrationsprozess?

Genau, also wir haben dann das Modell noch in unsere Lagersoftware integrieren müssen in unseren PHP Code. Wir haben uns da für die Google Machine Learning Engine für PHP entschieden. Es ist wie das Deployment von Google Callup aus – eigentlich war es sehr einfach und hat sehr gut, schnell funktioniert. Man kann sich eben von der Google AI Platform ein JSON Authentification File herunterladen, das den Dienstkonten Schlüssel beinhaltet. Mit dem Dienstkonten Schlüssel und dem File kann man dann einen authorisierten Service erstellen. Über den authorisierten Service das Modell abfragen. Auf das wird da jetzt nicht näher im Detail eingegangen, der Code, was hier dargestellt ist, ist eigentlich unsere zentrale Methode, wie wir ein Modell abfragen. Er hat zwei Parameter:

zum einen der Modellname, der den Pfad angibt zum Modell. Und ein Request-Array, das die Daten zu den Lieferungen in dem Fall, zu den Instanzen beinhalten, für die dann die Klasse abgefragt wird.

Wie man sieht – wichtig da die letzte Zeile eigentlich. Da hat man den authorisierten Service über projects->predict und mit den Modellnamen, dem Request-Array, kann man sehr einfach das Modell dann anbinden. Natürlich, man bekommt dann auch einen Response zurück, aus dem man die Daten dann auch auslesen muss.

Du hast gesagt – wenn ich mich richtig erinnere – das Modell ist schon im Einsatz, also live.

In einem Shop ist es zur Zeit im Einsatz. Wir testen das gerade, wie sich die Vorhersagegenauigkeit dann im tatsächlichen Einsatz verhält. Wir haben uns für den Shop VitalAbo entschieden, wie man da jetzt sehen kann im linken Bereich sind drei verschiedene Größen vorgeschlagen. Über ein config kann man dann definieren, ob die wahrscheinlichste Größe bereits vorausgewählt ist oder nicht. In dem Fall ist die wahrscheinlichste Größe Paket 2 bereits vorausgewählt. Der Mitarbeiter im Lager kann direkt damit beginnen, quasi die Produkte zu verpacken.

Wichtig vielleicht noch zu erwähnen ist, dass wir zwei verschiedene Arten – oder Möglichkeiten – hatten, wie oder wann wir die Anfrage ans Modell senden. Zum einen hätten wir es direkt machen können, wann der Verpackungsprozess gestartet wird. Oder bereits vorab, wann die Lieferungen erzeugt werden. Wir haben uns für Zweiteres entschieden, weil wir dadurch das ein bisschen zeitlich entkoppeln können. Wann der Mitarbeiter den Verpackungsprozess startet, dann will er nicht auf eine Vorhersage vom Modell dann warten. Also wir speichern dann die Vorhersageergebnisse vorab in die Datenbank und beim Start des Verpackungsprozesses werden die dann quasi aus der Datenbank sofort geladen und stehen zur Verfügung.

Cool! Also das ist jetzt der Live-Stand, gibt es schon Ideen für die Zukunft?

Es ist jetzt natürlich geplant, dass wir das in weiteren Shops integrieren. Natürlich muss man die Vorhersagegenauigkeit laufend überprüfen – schauen ob sie hoch genug ist. Natürlich auch die Vorhersagegenauigkeit verbessern – eventuell auch die Datengrundlage, dass man bessere Features sucht, die für einen Shop repräsentativ sind. Es sollen auch dadurch, dass laufend Daten generiert werden, die Modelle besser werden und die Vorhersagegenauigkeit auch besser werden.

Ein Projekt was noch spannend ist, welches ich schon erwähnt habe: die Bestimmung vom Transportvolumen, welches wir vorab machen können, auf Basis von dem Modell, welches wir da erstellt haben.

Ja und so im Nachhinein, Lessons learned? Sachen die man hätte anders machen können – gibt es da Erfahrungswerte?

Ja also das Daten Holen war sehr aufwändig, wie wir das jetzt gelöst haben. Wir müssen jeden Shop abfragen über REST, die Daten dann holen, raufladen auf einen Speicher, von dort mit Google Callup anbinden und dann die Modelle trainieren.

Cool wäre natürlich wenn wir das direkt synchronisieren würden – zum Beispiel über Google BigQuery –, dass wir dann automatisch die Daten ans Modell von dem Modell holen können, das Modell trainieren. Und es besteht zum Beispiel auch die Möglichkeit, dass die Ergebnisse, die man hat, zurückspielt, dann die Vorhersagegenauigkeit laufend überprüft. Wenn zum Beispiel die Vorhersagegenauigkeit dann schlechter wird, automatisch einen Trainings-Job anstartet.

Ja, das sind so die Pläne für die Zukunft, wie man das noch verbessern könnte.

Spannend, spannend! Sehr cool.

Ich bin derweil mal fragenlos, bzw. ich will auch nicht die Leute zu sehr langweilen. Falls es zu diesem Thema Fragen gibt, Anmerkungen, oder einfach nur interessante Gedanken, wir freuen uns voll über jeden Austausch! Unsere Türen stehen offen, für Graz oder für Saaz – und die Kaffeemaschine läuft sowieso immer heiß, also könnt ihr immer jederzeit gern vorbeikommen!

Ich verbleibe einfach mit einem Dank an den Michi fürs erzählen, danke an devjobs für das ganze organisieren und danke an euch daheim, die sich’s bis jetzt hoffentlich auch noch fertig anhören. Und ja, dann sage ich Danke und man sieht sich – stay nice!

Ciao!