TensorFlow-RNN-Konvertierung in LiteRT

Übersicht

LiteRT unterstützt die Konvertierung von TensorFlow-RNN-Modellen in LiteRT-Modelle kombinierten LSTM-Vorgängen. Es gibt zusammengeführte Operationen, um die Leistung eines deren zugrunde liegenden Kernel-Implementierungen und bieten eine höhere Ebene um komplexe Transformationen wie Quantisierung zu definieren.

Da es in TensorFlow viele Varianten der RNN APIs gibt, ist unser Ansatz Zweimal gefaltet:

  1. Native Unterstützung für standardmäßige TensorFlow RNN APIs wie Keras LSTM. Dies ist die empfohlene Option.
  2. Stellen Sie eine Schnittstelle zur Conversion-Infrastruktur bereit. benutzerdefinierten RNN-Implementierungen, die eingesteckt und in LiteRT Wir stellen einige Beispiele für solche Konvertierung mit Linvo's LSTMCellSimple und LayerNormalizedLSTMCellSimple RNN-Schnittstellen.

Converter-API

Die Funktion ist Teil der TensorFlow-Version 2.3. Sie ist auch über die tf-nightly-Pip oder from head.

Diese Konvertierungsfunktion ist verfügbar, wenn in LiteRT konvertiert wird oder direkt aus dem Keras-Modell abrufen. Anwendungsbeispiele ansehen.

Aus dem gespeicherten 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 zu LiteRT Colab veranschaulicht die End-to-End-Nutzung mit dem LiteRT-Interpreter.

Unterstützte RNNs APIs von TensorFlow

Wir unterstützen die sofortige Konvertierung von Keras LSTM in LiteRT. Für Einzelheiten zur Funktionsweise finden Sie in der Keras LSTM-Schnittstelle und die Conversion-Logik, hier.

Außerdem ist es wichtig, den LSTM-Vertrag von LiteRT im Hinblick auf zur Definition der Keras-Operation hinzufügen:

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

Keras LSTM-Varianten

Hauptzeit

Nutzer können wählen, ob sie eher zeitintensiv sind oder nicht. Keras LSTM sorgt dafür, in den Attributen der Funktionsdefinition. Für ein unidirektionales LSTM-Sequenzsystem lässt sich einfach dem Parameter wichtiges Attribut „time“.

Bidirektionales LSTM

Bidirektionales LSTM kann mit zwei Keras LSTM-Schichten implementiert werden, einer für vorwärts und 1 für rückwärts, siehe Beispiele hier. Das „go_backward“-Attribut erkennen wir als „abwärts LSTM“. gruppieren wir weiter und LSTM rückwärts durch. Das ist eine Zukunftsarbeit. Derzeit erstellt die Funktion zwei unidirektionale SequenceLSTM-Operationen in der LiteRT- Modell.

Benutzerdefinierte Beispiele für LSTM-Conversions

LiteRT bietet auch die Möglichkeit, benutzerdefiniertes LSTM zu konvertieren. Implementierungen. Hier verwenden wir das LSTM von Lingvo als Beispiel dafür, implementiert. Weitere Informationen finden Sie in der lingvo.LSTMCellSimple-Schnittstelle und die Conversion-Logik hier. Wir zeigen auch ein Beispiel für eine weitere LSTM-Definition von Lingvo in lingvo.LayerNormalizedLSTMCellSimple-Schnittstelle und die Konvertierungslogik hier.

„Bring your own TensorFlow RNN“ to LiteRT (Bring your own TensorFlow RNN)

Wenn sich die RNN-Schnittstelle eines Nutzers von den standardmäßig unterstützten Schnittstellen unterscheidet, wird sind zwei Optionen:

Option 1: Adaptercode in TensorFlow-Python schreiben, um die RNN-Schnittstelle anzupassen zur Keras-RNN-Schnittstelle ein. Das bedeutet eine tf.function mit tf_implementsannotation unter die Funktion der generierten RNN-Schnittstelle, die identisch mit der der Keras LSTM-Schicht. Danach wird dieselbe Konvertierungs-API, die auch für Keras LSTM verwendet wird, funktionieren.

Option 2:Wenn dies nicht möglich ist (z.B. fehlen im Keras LSTM einige Funktionen, die derzeit durch die kombinierte LSTM-Operation von LiteRT wie Ebenennormalisierung), erweitern Sie dann den LiteRT-Konverter durch Schreiben benutzerdefinierten Conversion-Code und fügen ihn in die MLIR-pass hier. Die Schnittstelle der Funktion sollte wie ein API-Vertrag behandelt werden die Argumente für die Konvertierung in fusionierte LiteRT LSTM enthalten Operationen wie Eingabe, Verzerrungen, Gewichtungen, Projektion, Ebenennormalisierung usw. ist besser geeignet, wenn die Tensoren, die als Argumente an diese Funktion übergeben werden, rank (d.h. RankedTensorType in MLIR). Das macht es viel einfacher, der diese Tensoren als RankedTensorType annehmen kann, sie in Rangfolge Tensoren transformieren, die dem zusammengeführten LiteRT entsprechen die Operanden des Operators.

Ein vollständiges Beispiel für einen solchen Conversion-Ablauf ist LSTMCellSimple LiteRT-Konvertierung

Definition von LSTMCellSimple in Lingvo hier. Mit dieser LSTM-Zelle trainierte Modelle können wie folgt in LiteRT konvertiert werden: folgt:

  1. Umschließen aller Verwendungen von LSTMCellSimple in einer tf.function mit einem tf_implements die entsprechend gekennzeichnet ist (z.B. wäre lingvo.LSTMCellSimple ein guten Anmerkungsnamen hier einfügen). Achten Sie darauf, dass die generierte tf.function entspricht der Oberfläche der Funktion, die im Conversion-Code erwartet wird. Dieses ist ein Vertrag zwischen dem Modellautor, das die Anmerkung hinzufügt und der Conversion-Code.
  2. Den Pass „prep-composite-functions“ erweitern, um einen benutzerdefinierten zusammengesetzten Vorgang zu verbinden in LiteRT fusionierte LSTM-Operationen umwandeln. Weitere Informationen finden Sie unter LSTMCellSimple Conversion-Code.

    Der Konvertierungsvertrag:

  3. Die Tensoren Weight und Projection sind transponiert.

  4. {input, recurrent} zu {cell, input gate, entgangenes Gate, Ausgabe gate} durch Schneiden des transponierten Gewichtungstensors extrahiert werden.

  5. Die {bias} bis {bias} sind durch Schneiden des Bias-Tensors extrahiert.

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

  7. Ähnliche Conversion wird erfasst für LayerNormalizedLSTMCellSimple entfernt.

  8. Die restliche LiteRT-Conversion-Infrastruktur, einschließlich aller MLIR-Pässe sowie der endgültige Export in den LiteRT-Flatbuffer wiederverwendet werden.

Bekannte Probleme/Einschränkungen

  1. Derzeit wird nur das Konvertieren zustandsloser Keras LSTM (Standardeinstellung Verhalten in Keras). Eine zustandsorientierte Keras LSTM-Konvertierung ist eine Zukunft.
  2. Es ist immer noch möglich, eine zustandsorientierte Keras LSTM-Schicht mithilfe der die zugrunde liegende zustandslose Keras LSTM-Schicht des Benutzerprogramms. Ein solches TensorFlow-Programm lässt sich LiteRT verwendet die hier beschriebene Funktion.
  3. Bidirektionales LSTM wird derzeit als zwei unidirektionale SequenceLSTM modelliert. Operationen in LiteRT an. Dies wird durch eine einzelne Bidirektionale SequenceLSTM-Operation.