Dieser Artikel ist der Artikel zum 20. Tag von TensorFlow 2.0 Adventskalender 2019. Ich denke, die wichtigste Änderung in TensorFlow 2.0 ist, dass EagerExecution zum Standard geworden ist, sodass Sie in einer zwingenden Sprache schreiben und freier im pythonischen Stil schreiben können. Auf der anderen Seite gibt es jedoch das Problem, dass Leistung und Portabilität beeinträchtigt werden, aber um es so zu lösen, dass Sie sowohl vom Grafikmodus in 1.x als auch vom Eager-Modus in 2.x profitieren können. Eingeführt in tf.function
. In diesem Artikel möchte ich Ihnen die Verwendung von "tf.function" und Punkte vorstellen, die Sie bei der Verwendung beachten sollten. Grundsätzlich handelt es sich um eine Zusammenfassung von Official Site. Wenn Sie also mehr wissen möchten, lesen Sie bitte auch diese.
Es ist einfach zu bedienen. Sie können der Funktion, die die zu optimierende Verarbeitung beschreibt, einen Kollator mit "@ tf.function" hinzufügen oder eine Funktion definieren und der Methode "tf.function" zuweisen, um eine Funktion für den Grafikmodus separat hinzuzufügen. Es ist eine Methode zum Erstellen.
function_test.py
import tensorflow as tf
@tf.function
def f(x,y):
return x + y
#Oder
def g(x,y):
return x * y
h = tf.function(g)
Wenn Sie eine andere Funktion in "@ tf.function" aufrufen, erstreckt sich der Bereich auch auf diese Funktion, sodass Sie nicht alle Funktionen überprüfen und "@ tf.function" hinzufügen müssen (oder besser gesagt, wir empfehlen es). Sinn). Daher scheint es, dass Sie leicht vom Grafikmodus profitieren können, indem Sie ihn vorerst dem schweren Verarbeitungsteil hinzufügen. Wenn es sich jedoch um einen einfachen Schreibstil wie den im Tutorial handelt, ist dies keine große Sache. Wenn Sie jedoch versuchen, etwas Kompliziertes zu tun, werden Sie nicht glauben, dass Sie die Spezifikation von "tf.function" nicht kennen. Sie müssen vorsichtig sein, weil Sie es tun. Am Anfang von Offizielle Website steht die folgende Beschreibung.
Es gibt einige Punkte, die schwer zu interpretieren sind, aber ich denke, es ist einfacher zu verstehen, wenn Sie sich ein konkretes Beispiel ansehen. Schauen wir uns das an.
Bereiten Sie der Einfachheit halber zunächst die folgende einfache Funktion vor.
tracing_test.py
import tensorflow as tf
@tf.function
def double(a):
print("Tracing with, {}".format(a) )
return a + a
Es ist eine einfache Funktion, die das Eingabeargument verdoppelt und zurückgibt und auch das Drucken des Eingabearguments umfasst. Das Argument funktioniert mit ganzen Zahlen, reellen Zahlen und Zeichenfolgen. Lassen Sie uns dies mit einigen Mustern tun.
tracing_test.py
print(double(3))
print()
print(double(2))
print()
print(double(tf.constant(1.1)))
print()
print(double(tf.constant('a')))
print()
print(double(tf.constant('b')))
Das Ergebnis ist wie folgt.
Tracing with, 3
tf.Tensor(6, shape=(), dtype=int32)
Tracing with, 2
tf.Tensor(4, shape=(), dtype=int32)
Tracing with, Tensor("a:0", shape=(), dtype=float32)
tf.Tensor(2.2, shape=(), dtype=float32)
Tracing with, Tensor("a:0", shape=(), dtype=string)
tf.Tensor(b'aa', shape=(), dtype=string)
tf.Tensor(b'bb', shape=(), dtype=string)
Das Ergebnis ist etwas seltsam. Die print-Anweisung wird nicht nur ausgeführt, wenn die letzte "tf.constant (" b ")" als Argument ausgeführt wird. Wenn Sie versuchen, das obige Programm erneut auszuführen, erhalten Sie noch seltsamere Ergebnisse.
tracing_test.py
print(double(3))
print()
print(double(2))
print()
print(double(tf.constant(1.1)))
print()
print(double(tf.constant('a')))
print()
print(double(tf.constant('b')))
Das Ergebnis ist wie folgt.
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(4, shape=(), dtype=int32)
tf.Tensor(2.2, shape=(), dtype=float32)
tf.Tensor(b'aa', shape=(), dtype=string)
tf.Tensor(b'bb', shape=(), dtype=string)
Der korrekte Wert wird zurückgegeben, aber die in der Mitte geschriebene Druckanweisung wird überhaupt nicht ausgeführt. Was bedeutet das?
Tracing
Tatsächlich beinhaltet dieses seltsame Verhalten einen Prozess namens Tracing, wenn "tf.function" eine Funktion in einem Rechengraphen erstellt und optimiert. tf.function
konvertiert eine Funktion, die nicht nur die von TensorFlow abgeleitete, sondern auch die Python-spezifische Verarbeitung beschreibt, in einen Rechengraphen. Außerdem wird die Python-spezifische Verarbeitung (in diesem Fall die Druckanweisung) weggelassen, die nicht mit der Ausführung des Berechnungsdiagramms zusammenhängt. Aber warum wurde es zuerst gemacht? Das liegt daran, dass ein Prozess namens Tracing ausgeführt wird, wenn tf.function
eine Funktion in einen Rechengraphen konvertiert. In Python geschriebene Funktionen haben keinen expliziten Typ in ihren Argumenten. Während es praktisch ist, verschiedene Werte eingeben zu können, ist es daher ein Problem von der Seite "tf.function", ein optimales Berechnungsdiagramm zu erstellen. Wenn daher ein Wert oder Typ eingegeben wird, der nicht in das Argument eingegeben wurde, und die Funktion zum ersten Mal aufgerufen wird, wird ein Prozess namens Tracing ausgeführt, um die gesamte Python-spezifische Verarbeitung in der Funktion auszuführen. Ich sagte "Werte und Typen, die nie in das Argument aufgenommen wurden", aber genau genommen lauten die Kriterien wie folgt.
Daher ist das seltsame Verhalten des vorherigen wie folgt.
tracing_test.py
print(double(3)) #Rückverfolgung, weil es der Wert ist, den ich zum ersten Mal sehe
print()
print(double(2)) #Rückverfolgung, weil es der Wert ist, den ich zum ersten Mal sehe
print()
print(double(tf.constant(1.1))) #Rückverfolgung, weil es der Wert ist, den ich zum ersten Mal sehe
print()
print(double(tf.constant('a'))) #Verfolgung, weil es die erste Form ist, die man sieht
print()
print(double(tf.constant('b'))) #Optimierte Diagrammausführung, da es sich um die zuvor gesehene Typform handelt
Sobald Sie Tracing ausführen, speichert TensorFlow das resultierende Berechnungsdiagramm intern. Wenn dann das nächste Mal ein zuvor verfolgter Wert oder ein Typ / Form-Argument eingegeben wird, wird das optimierte Berechnungsdiagramm ausgeführt. Daher wurde im obigen Programm die Python-Druckanweisung beim letzten Aufruf nicht ausgeführt, und alle Druckanweisungen wurden nicht ausgeführt, als sie erneut ausgeführt wurden.
Also werde ich zum Anfang zurückkehren,
Es bedeutet das. Es ist früher drucken, aber wenn Sie es stattdessen in "tf.print" schreiben, wird es jedes Mal ausgeführt. Sie können auch seltsames Verhalten verhindern, indem Sie von TensorFlow abgeleitete Funktionen vollständig nutzen, z. B. "tf.summary" oder "tf.Variable", wenn Sie verschiedene Werte in einer Funktion aktualisieren möchten. Es verbessert auch die Leistung. Bitte beachten Sie jedoch, dass wir nicht sagen, dass wir keine Python-spezifische Verarbeitung einbeziehen sollten. Der Vorteil, flexibler programmieren zu können, indem man es zusammen mit pythonischem Schreiben verwenden kann, ist groß. Beachten Sie jedoch, dass sich eine Funktion seltsam verhält, wenn Sie sie definieren, ohne an irgendetwas zu denken, und "tf.function" hinzufügen.
Es ist schön, TensorFlow 2.0 zu haben und sowohl vom Graph- als auch vom Eager-Modus profitieren zu können, aber es werden Funktionen erstellt, die zu stark von Python-spezifischen Funktionen abhängen, die nicht den oben genannten Fallstricken entsprechen. Sie können auf einen unerwarteten Fehler treten. Wenn Sie TensorFlow verwenden, verwenden Sie so oft wie möglich von TensorFlow abgeleitete Methoden. Wenn Sie Python-spezifische Funktionen verwenden, sollten Sie das AutoGraph-Verhalten und die Ablaufverfolgung berücksichtigen. Auf der offiziellen Website müssen Sie noch viele andere Dinge beachten und wie Sie diese Verhaltensweisen steuern können. Wenn Sie von nun an Ihr eigenes Modell implementieren und tf.function
verwenden müssen, lesen Sie es bitte.
Recommended Posts