TensorFlow-RNN-Konvertierung in TensorFlow Lite

Überblick

TensorFlow Lite unterstützt die Konvertierung von TensorFlow-RNN-Modellen in fusionierte LSTM-Operationen von TensorFlow Lite. fusionierte Operationen dienen dazu, die Leistung der zugrunde liegenden Kernelimplementierungen zu maximieren und eine Oberfläche auf höherer Ebene bereitzustellen, um komplexe Transformationen wie Quantisierung zu definieren.

Da es in TensorFlow viele Varianten von RNN APIs gibt, verfolgen wir einen zweifachen Ansatz:

  1. Native Unterstützung für standardmäßige TensorFlow RNN APIs wie Keras LSTM bereitstellen Dies ist die empfohlene Option.
  2. Eine Schnittstelle zur Konvertierungsinfrastruktur für benutzerdefinierte RNN-Implementierungen bereitstellen, um in TensorFlow Lite konvertiert zu werden. Wir bieten einige sofort einsatzbereite Beispiele für eine solche Umwandlung mithilfe der RNN-Schnittstellen LSTMCellSimple und LayerNormalizedLSTMCellSimple von lingvo.

Converter API

Diese Funktion ist Bestandteil von TensorFlow 2.3. Sie ist auch über den tf-nightly-Pip oder von Head verfügbar.

Diese Konvertierungsfunktion ist verfügbar, wenn die Konvertierung in TensorFlow Lite über ein Memcache oder direkt über das Keras-Modell erfolgt. Anwendungsbeispiele ansehen.

Aus gespeichertem Modell

# build a saved model. Here concrete_function is the exported function
# corresponding to the TensorFlow model containing one or more
# Keras LSTM layers.
saved_model, saved_model_dir = build_saved_model_lstm(...)
saved_model.save(saved_model_dir, save_format="tf", signatures=concrete_func)

# Convert the model.
converter = TFLiteConverter.from_saved_model(saved_model_dir)
tflite_model = converter.convert()

Aus dem Keras-Modell

# build a Keras model
keras_model = build_keras_lstm(...)

# Convert the model.
converter = TFLiteConverter.from_keras_model(keras_model)
tflite_model = converter.convert()

Beispiel

Keras LSTM für TensorFlow Lite Colab veranschaulicht die End-to-End-Nutzung mit dem TensorFlow Lite-Interpreter.

Unterstützte TensorFlow-RNNs-APIs

Wir unterstützen die sofortige Konvertierung von Keras LSTM in TensorFlow Lite. Weitere Informationen zur Funktionsweise finden Sie auf der Keras LSTM-Schnittstelle und in der Conversion-Logik.

Außerdem ist es wichtig, den LSTM-Vertrag von TensorFlow Lite in Bezug auf die Keras-Vorgangsdefinition hervorzuheben:

  1. Die Dimension 0 des input-Tensors ist die Batchgröße.
  2. Die Dimension 0 des Tensors recurrent_weight ist die Anzahl der Ausgaben.
  3. Die Tensoren weight und recurrent_kernel werden transponiert.
  4. Die transponierten Gewichtungen, die transponierten Tensoren recurrent_kernel und bias werden entlang der Dimension 0 in vier gleich große Tensoren aufgeteilt. Diese entsprechen dem Eingabe-Gatter, dem Vergessen-Gatter, der Zelle und dem Ausgabe-Gatter.

Keras LSTM-Varianten

Hauptzeit

Die Nutzer können zwischen „Zeitwichtig“ und „Keine Zeit höher“ wählen. Keras LSTM fügt den Funktionsdef-Attributen ein Zeit-Hauptattribut hinzu. Bei der unidirektionalen Sequenz-LSTM können wir einfach dem Zeit-Hauptattribut von unidirecional_Sequence_lstm zuordnen.

BiDirectional LSTM

Bidirektionales LSTM kann mit zwei Keras LSTM-Schichten implementiert werden, einer für die Vorwärts- und einer für die Rückwärtsrichtung, siehe Beispiele. Sobald wir das Attribut go_backward sehen, erkennen wir es als „rückwärts LSTM“ und gruppieren dann „Forward und Backward LSTM“. Das ist zukünftige Arbeit. Dadurch werden derzeit zwei UnidirektionalSequenceLSTM-Vorgänge im TensorFlow Lite-Modell erstellt.

Benutzerdefinierte LSTM-Conversion-Beispiele

TensorFlow Lite bietet auch eine Möglichkeit, benutzerdefinierte LSTM-Implementierungen zu konvertieren. Hier wird der LSTM von Lingvo als Beispiel dafür verwendet, wie dies umgesetzt werden kann. Weitere Informationen finden Sie in der lingvo.LSTMCellSimple-Schnittstelle und in der Konvertierungslogik. Ein Beispiel für eine andere Lingvo-LSTM-Definitionen finden Sie in der lingvo.LayerNormalizedLSTMCellSimple-Schnittstelle und hier.

„Bring your own TensorFlow RNN“ zu TensorFlow Lite

Wenn sich die RNN-Schnittstelle eines Nutzers von der standardmäßig unterstützten Schnittstelle unterscheidet, gibt es mehrere Möglichkeiten:

Option 1: Schreiben Sie Adaptercode in TensorFlow Python, um die RNN-Schnittstelle an die Keras RNN-Schnittstelle anzupassen. Dies bedeutet, dass eine tf.function mit der Annotation tf_implements in der Funktion der generierten RNN-Schnittstelle identisch ist, die mit der von der Keras LSTM-Schicht generierten Funktion identisch ist. Danach funktioniert dieselbe Conversion API wie für Keras LSTM verwendet.

Option 2:Wenn dies nicht möglich ist (z.B. wenn Keras LSTM eine Funktionalität fehlt, die derzeit durch den fusionierten LSTM-Vorgang von TensorFlow Lite wie die Layer-Normalisierung verfügbar ist), erweitern Sie den TensorFlow Lite-Konverter durch Schreiben von benutzerdefiniertem Konvertierungscode und fügen Sie ihn hier in den MLIR-Pass zur Vorbereitung der zusammengesetzten Funktionen ein. Die Schnittstelle der Funktion sollte wie ein API-Vertrag behandelt werden und die Argumente zur Konvertierung in zusammengeführte TensorFlow Lite LSTM-Vorgänge enthalten, z.B. Eingabe, Verzerrung, Gewichtungen, Projektion, Ebenennormalisierung usw. Die Tensoren, die als Argumente an diese Funktion übergeben werden, sollten einen bekannten Rang haben (d.h. RankedTensorType in MLIR). Dadurch wird es viel einfacher, Konvertierungscode zu schreiben, der diese Tensoren als RankedTensorType annehmen kann und hilft, sie in eingestufte Tensoren zu transformieren, die den Operanden des zusammengeführten TensorFlow Lite-Operators entsprechen.

Ein vollständiges Beispiel für einen solchen Umwandlungsablauf ist die von Lingvo durchgeführte Konvertierung von LSTMCellSimple zu TensorFlow Lite.

Das LSTMCellSimple in Lingvo wird hier definiert. Mit dieser LSTM-Zelle trainierte Modelle können so in TensorFlow Lite konvertiert werden:

  1. Fassen Sie alle Verwendungen von LSTMCellSimple in einer tf.function mit einer tf_implements-Annotation zusammen, die entsprechend gekennzeichnet ist. Ein geeigneter Annotationsname wäre z. B. „lingvo.LSTMCellSimple“. Die generierte tf.function muss der Schnittstelle der Funktion entsprechen, die im Konvertierungscode erwartet wird. Dies ist ein Vertrag zwischen dem Modellautor, der die Annotation und den Conversion-Code hinzufügt.
  2. Erweitern Sie den Pass „Prepare-composite-Functions“, um eine benutzerdefinierte zusammengesetzte Operation in die Umwandlung von fusioniertem LSTM-Vorgang in TensorFlow Lite einzubinden. Siehe LSTMCellSimple-Conversion-Code.

    Der Conversion-Vertrag:

  3. Weight- und Projektion-Tensoren werden transponiert.

  4. Die Werte von {input, recurrent} an {cell, input gate, change gate, edition} werden durch Segmentieren des transponierten Gewichtungstensors extrahiert.

  5. Die {bias} zu {cell, Input Gate, Forget Gate, Ausgangsgatter} werden durch Segmentieren des Bias-Tensors extrahiert.

  6. Die Projektion wird durch Segmentieren des transponierten Projektionstensors extrahiert.

  7. Eine ähnliche Konvertierung wird für LayerNormalizedLSTMCellSimple geschrieben.

  8. Der Rest der TensorFlow Lite-Konvertierungsinfrastruktur, einschließlich aller definierten MLIR-Passagen und des endgültigen Exports in den TensorFlow Lite-Flatbuffer, kann wiederverwendet werden.

Bekannte Probleme/Einschränkungen

  1. Derzeit wird nur die Umwandlung zustandsloser Keras LSTM (Standardverhalten in Keras) unterstützt. Die zustandsorientierte Keras LSTM-Konvertierung ist eine zukünftige Arbeit.
  2. Es ist weiterhin möglich, eine zustandsorientierte Keras LSTM-Schicht mithilfe der zugrunde liegenden zustandslosen Keras LSTM-Ebene zu modellieren und den Zustand explizit im Nutzerprogramm zu verwalten. Ein solches TensorFlow-Programm kann mithilfe des hier beschriebenen Features trotzdem in TensorFlow Lite konvertiert werden.
  3. Bidirektionales LSTM wird derzeit in TensorFlow Lite als zwei UnidirektionalSequenceLSTM-Vorgänge modelliert. Dieser wird durch einen einzelnen BiDirectionSequenceLSTM-Vorgang ersetzt.