Maschinelles Lernen mit Tensorflow

21.03.2018 - DevBoost

Einen Schwerpunkt des letzten DevBoost Developer Camps bildete die Evaluierung von TensorFlow – Googles plattformunabhängiger Programmbibliothek für maschinelles Lernen. In diesem Artikel haben wir nun kurz und knapp zusammengefasst, was wir gemacht und gelernt haben:

 

Kein maschinelles Lernen ohne großen Datensatz.

 

Anhand der verfügbaren Tutorials bekommt man recht schnell einen ersten Eindruck davon, wie TensorFlow funktioniert. Das Herz eines jeden Projektes zum maschinellen Lernen sind künstliche, neuronale Netze bestehend aus Graphen mit Knoten und Kanten. Diese beinhalten die Regeln für den Umgang mit verschiedenen Eingabeparametern. Da es unmöglich ist, ohne einen hinreichend großen Datensatz sinnvolle Ergebnisse zu erzielen, bestand die erste Aufgabe darin einen geeigneten Datenpool zu schaffen.

 

Wenn wir bei DevBoost etwas in Hülle und Fülle haben, dann sind es Softwaretests. Daher kam schnell die Idee auf, aus dem existierenden Pool an Testcode einen Datensatz zu erzeugen. Konkret nutzen wir alle im Repository auffindbaren natürlichsprachlichen Sätze unserer automatisierten Akzeptanztests. Die Sätze wurden mit einem von uns entwickeltem ATDD Werkzeug geschrieben und darüber auch mit dem zugehörigen Testcode verbunden. Somit fiel es uns leicht eine Liste aller Sätze sowie ein Mapping aller enthaltenen Wörter zu den zu erwarteten Parametertypen zu generieren. 

Wie zu erwarten, sind wesentlich mehr StaticWord-Parameter zu finden als alle anderen Parameterarten (linker Graph). Die Sätze waren dabei meist zwischen 2 und 20 Wörter lang (rechter Graph).

 

 

 

Ziel war es nun, mittels TensorFlow vorherzusagen, welche Wörter in einem Satz Parameter für die jeweilige Testfunktion sein können. So soll beispielsweise aus dem Satz “Assert 32 is a number” eine Testfunktion generiert werden, welche einen „Integer“ Parameter erfordert und diesen mit der Nummer „32“ belegt.

 

Trainieren und Validieren

 

Nachdem der Datenpool geschaffen ist, gilt es in einem nächsten Schritt das neuronale Netzwerk bestmöglich auf die bevorstehende Problemlösung zu trainieren. Dafür ist die Verwendung von zwei verschiedenen Datensätzen unabdingbar. Der größere Datensatz („Training Set“) enthält die Daten, welche zum Trainieren des Netzes benötigt werden. Mit einem Vergleich zwischen den realen und den erwarteten Outputdaten lässt sich das neuronale Netzwerk trainieren und auf Fehlfunktionen testen. Der kleinere Datensatz dient der Validierung, dass das neuronale Netz auch für Daten genutzten werden kann, welche es nicht kennt. Wird diese Validierung nicht vorgenommen, ist es möglich, dass das neurale Netzwerk auf Basis der bekannten Daten einwandfrei arbeitet – bei jedem anderen Datensatz aber Fehler macht.

 

Füttern des Netzes

 

Neuronale Netze verarbeiten Zahlen, d.h. wir mussten in unserem Fall die Sätze und Wörter auf Zahlen abbilden. Dies ist eine prinzipiell nicht zu unterschätzende Herausforderung im Umgang mit neuronalen Netzen, welche aktuell noch Experten und Wissenschaftler gleichermaßen beschäftigt. Anstatt also Wörter und Sätze als direkten Input zu verwenden, haben wir daraus so genannte „Features“ errechnet:

 

  • Length (Länge des Wortes)
  • Uppercase (Wort enthält Großbuchstaben)
  • Special character (Wort enthält Sonderzeichen wie bspw.  /.,*,+,§,$)
  • Position (Position des Wortes in einem Satz)
  • Type (Typ (string, int, float, boolean))
  • NLP Tag (Art des Wortes (u.a. Verb, Adjektiv, Nomen))
  • Index (Index in der Liste aller Wörter des Datensatzes)

 

TensorFlow ist eine mächtige Bibliothek mit vielen hilfreichen Abstraktionen (z.B. „Estimators“), mittels welcher schnell erste Ergebnisse geschaffen werden, ohne die Implementierung im Detail zu kennen. Schwieriger zu entscheiden ist eher die Frage, welche der bereitgestellten Estimators für die jeweilige Aufgabe die passenden sind. Für unseren Anwendungsfall entschieden wir uns für den „DNNClassifier“. Bzgl. der Konfiguration haben wir uns vom Getting Started inspirieren lassen.

 

Kombinieren von Features

 

Nach den ersten Tests, einigem Finetuning und dem Einbezug all unserer Features kamen wir bereits auf eine beachtliche Treffgenauigkeit („Accuracy“) von 92,5%. Daraufhin analysierten wir den Einfluss der Kombination verschiedener Features auf die Treffgenauigkeit. In Summe ergaben sich 127 verschiedene Kombinationen. Deren Vergleich gelingt mit TensorFlow leicht, da es alle neuronalen Netze speichert. Somit konnten wir die Netze jeweils einmal trainieren und nutzen, um die Sätze im Anschluss manuell zu klassifizieren ohne das Netz nochmals zu trainieren.

 

 

 

Es wird anhand der Tabelle deutlich, dass das „Index“ Feature die Treffgenauigkeit eher mindert. Einer der Gründe hierfür ist, das die verwendete Liste der Wörter nur jene enthält, die im Training des Netzes verwendet wurden. Der Datensatz zum Validieren enthält wahrscheinlich viele Wörter, welche nicht Teil dieser Liste sind. Den größten Einfluss haben die Features „Length“, „Type“ und „Uppercase“. Eine weitere Erkenntnis ist, dass eine höhere Anzahl verfügbarer Features für ein besseres Ergebnis sorgt.

 

Evaluation

 

Zu guter Letzt galt es die erreichten Ergebnisse zu evaluieren. Das von uns entwickelte ATDD Tool, aus welchem wir die Sätze extrahiert haben, besitzt bereits eine eingebaute Heuristik für die oben genannte Zielstellung. Dieser wesentlich einfachere Algorithmus sollte uns als Referenz zu den erreichten Ergebnissen mit TensorFlow dienen. Wir ließen also sowohl die Heuristik als auch das neuronale Netz den gleichen Pool von 5.000 Sätzen klassifizieren und extrahierten zwei Werte. Einerseits die Treffgenauigkeit mit der die beiden Ansätze ihre Vorhersagen trafen sowie andererseits ob eine falsche Vorhersage ein falsch positiver Fall war (Vorhersage eines Parameters, welcher keiner ist).

 

 


Wie in der Tabelle ersichtlich ist die Treffgenauigkeit beider Ansätze sehr hoch. Das neuronale Netz schneidet nur minimal besser ab, als der bestehende Algorithmus. Die weitaus interessante Statistik liefern die falsch positiven Vorhersagen. Das neuronale Netz scheint wesentlich besser im Vermeiden dieser Fehler. Knapp 50% der falschen Vorhersagen der Heuristik waren falsch positiv, während das neuronale Netz diesen Fehler auf circa 3% reduziert.

 

Abschließend wollen wir noch die Zeit betrachten, mit welcher die beiden Ansätze zu ihren Ergebnissen gekommen sind. Die Heuristik brauchte 0,0005 Sekunden für eine Antwort, TensorFlow dagegen 0,5 Sekunden. Dies stellt eine um den Faktor 1000 schnellere Antwortzeit der Heuristik dar. Sicherlich lässt sich das Netzwerk hier mittels geeigneter Konfiguration weiter optimieren, dies stand aber für uns nicht im Fokus.

Insgesamt betrachtet konnten wir in diesem recht kleinen Setup bereits einen sehr guten Einblick in das Framework und die damit verbundenen Tools und Workflows bekommen. Für den von uns gewählten Use Case konnte das neuronale Netz sofort bessere Ergebnisse liefern, jedoch war die damit verbundene Berechnungszeit auch wesentlich höher als bei unserer bestehenden Lösung. Im Sinne einer guten Usability müssen die Berechnungen für (Auto-) Vervollständigungen und Vorschläge in einer IDE sehr schnell ausgeführt werden. Hier gilt es anzusetzen, um das System im Produktivbetrieb einzusetzen. Die Arbeit mit der Technologie als solche ist in jedem Fall spannend und wird uns sicher in dem einen oder anderen Projekt zur Entwicklung individueller Softwarelösungen wieder begegnen.

Ihr Ansprechpartner