Evolution im Machine Learning: TensorFlow 2.0

TensorFlow spielt eine bedeutende Rolle im Bereich Machine Learning. Version 2.0 des Frameworks verspricht einen verbesserten Workflow und aufgeräumte APIs.

Werkzeuge  –  11 Kommentare

Die Methoden des Machine Learning (ML) haben vor allem dank zahlreicher quelloffener Frameworks den Weg aus der Forschung in die Industrie gefunden. Ob in der Verarbeitung natürlicher Sprache oder in der Objekterkennung – Machine- und Deep-Learning-Modelle sind kaum mehr wegzudenken. Zu den Platzhirschen unter den ML-Frameworks gehört TensorFlow, das seit 2015 existiert. Seitdem hat sich viel getan.

Anfang Juni hat Google die Beta von TensorFlow 2.0 freigegeben, und seit Kurzem ist der erste Release Candidate verfügbar. Die Neuerungen können sich durchaus sehen lassen. Die aufgeräumte API verzichtet auf globale Namespaces und erklärt Eager Execution zur direkten Codeausführung zum Standard. Mit der Annotation tf.function und AutoGraph lassen sich aus Eager-Code heraus automatisch TensorFlow-Graphen erstellen. Damit können Entwickler Modelle imperativ mit Python-Boardmitteln einfach und schnell entwickeln und anschließend optimiert in Graphenform exportieren. Außerdem erhalten sie ein Migrationstool an die Hand, das dabei hilft, alte Implementierungen mit wenig Anpassungen auf TensorFlow 2.0 umzustellen.

Aufräumen bei der API

Google hat die teils inkonsistente API einer grundlegenden Frischzellenkur unterzogen. Das Hauptziel ist, neue Namespaces zu schaffen, die bestehende Module besser beschreiben oder Platz für neue bieten. TensorFlow 2 verzichtet auf tf.contrib, und Operationen wie tf.round, die aktuell noch im Root liegen, wandern in den neuen Namespace tf.math. Dasselbe gilt für Operationen mit Präfixen im Namen wie tf.string\_strip, die ab jetzt in tf.strings zu finden sind.

Die größte Änderung gibt es bei den Modulen tf.layers, tf.losses und tf.metrics, die nun im tf.keras-Namespace angesiedelt sind. Damit wird die Keras-Schnittstelle für Layers, Losses und Metriken die neue Standard-API zur Modellierung von Deep Learning Modellen.

Globalisierungsgegner bei den Graphen

Bei der Graphdefinition setzt TensorFlow 1.x auf globale Namespaces. Der Aufruf von tf.constant(...) in folgendem Codebeausschnitt fügt dem Standardgraphen eine Konstante hinzu, die beim Löschen der eigentlichen Python-Variable erhalten bleibt:

# TensorFlow 1.x
v1 = tf.constant(1., name="v")
v2 = tf.constant(2., name="v")
del v1, v2
tf.get_default_graph().get_operations()

Ein Aufruf von tf.get\_default\_graph().get\_operations() zeigt, dass die Konstanten v1 und v2 weiterhin im Graphen enthalten sind. Schwierig ist es in dem Fall, dass die Referenz zur Konstante beziehungsweise Variable verloren geht. In dem Fall erfolgt der einzige Zugriff auf den Wert über den Namen innerhalb des Graphen. Dieses Vorgehen ist unnötig komplex und fehleranfällig. Daher verzichtet TensorFlow 2 komplett auf globale Namespaces. Das gilt ebenso für Mechanismen, um Variablen zu finden wie tf.get\_default\_graph() oder tf.get_variable(...). Entwickler müssen entweder auf die Keras-Layer-API zurückgreifen oder die Variablen im Code verwalten. Das Aufräumen übernimmt der Garbage Collector.

Dienstbeflissen bei der Ausführung

Die nächste Hauptversion des Frameworks bringt nicht nur neue Funktionen, sondern verleiht einigen bekannten deutlich mehr Gewicht: Der Eager-Execution-Modus kam Anfang 2018 mit TensorFlow 1.5 hinzu und wird in der neuen Version zum Standard. Statt einen Graphen zu bauen, evaluiert das Framework Operationen im Eager-Modus zur Laufzeit und gibt deren Werte aus wie in folgendem Beispiel:

import tensorflow as tf ew
x = [[2.]]
m = tf.matmul(x, x)
print("{}".format(m))

Der kurze Code zeigt gleich mehrere Vorteile. Da Tensoren im Eager-Modus konkrete Werte referenzieren, sind sie erheblich leichter zu untersuchen – wahlweise durch Ausgabe der Werte oder unter Nutzung eines Debuggers. Außerdem ändert weder die Evaluierung noch die Ausgabe etwas an dem Code zur Gradientenberechnung.

Weiterhin bietet die Eager Execution das von Numpy-Arrays bekannte Broadcasting von Tensoren. Das Framework passt dabei Tensor Shapes dynamisch an, damit sie kompatibel zu mathematischen Operationen sind. Auf die Weise lassen sich Tensoren mit unterschiedlichen Dimensionen kombinieren:

a = tf.constant([[1, 2], [3, 4]])
b = a + tf.constant([1])
print(b)

# Ausgabe
>> tf.Tensor([[2 3][4 5]], shape=(2, 2), dtype=int32)