Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

TensorFlow Lite Inferenz

Der Begriff Inferenz bezieht sich auf den Prozess der Ausführung eines TensorFlow Lite-Modells auf dem Gerät, um Vorhersagen basierend auf Eingabedaten zu treffen. Um eine Inferenz mit einem TensorFlow Lite-Modell durchzuführen, müssen Sie es über einen Interpreter ausführen. Der TensorFlow Lite-Interpreter ist schlank und schnell. Der Interpreter verwendet eine statische Diagrammreihenfolge und einen benutzerdefinierten (weniger dynamischen) Speicherzuweiser, um eine minimale Lade-, Initialisierungs- und Ausführungslatenz sicherzustellen.

Auf dieser Seite wird beschrieben, wie Sie auf den TensorFlow Lite-Interpreter zugreifen und eine Inferenz mit C ++, Java und Python durchführen sowie Links zu anderen Ressourcen für jede unterstützte Plattform .

Wichtige Konzepte

Die TensorFlow Lite-Inferenz folgt normalerweise den folgenden Schritten:

  1. Laden eines Modells

    Sie müssen das .tflite Modell in den Speicher laden, der das Ausführungsdiagramm des Modells enthält.

  2. Daten transformieren

    Rohe Eingabedaten für das Modell stimmen im Allgemeinen nicht mit dem vom Modell erwarteten Eingabedatenformat überein. Beispielsweise müssen Sie möglicherweise die Größe eines Bilds ändern oder das Bildformat ändern, um mit dem Modell kompatibel zu sein.

  3. Laufende Inferenz

    In diesem Schritt wird das Modell mithilfe der TensorFlow Lite-API ausgeführt. Es umfasst einige Schritte wie das Erstellen des Interpreters und das Zuweisen von Tensoren, wie in den folgenden Abschnitten beschrieben.

  4. Ausgabe interpretieren

    Wenn Sie Ergebnisse aus der Modellinferenz erhalten, müssen Sie die Tensoren auf eine sinnvolle Weise interpretieren, die für Ihre Anwendung nützlich ist.

    Beispielsweise kann ein Modell nur eine Liste von Wahrscheinlichkeiten zurückgeben. Es liegt an Ihnen, die Wahrscheinlichkeiten relevanten Kategorien zuzuordnen und sie Ihrem Endbenutzer zu präsentieren.

Unterstützte Plattformen

TensorFlow-Inferenz-APIs werden für die meisten gängigen mobilen / eingebetteten Plattformen wie Android , iOS und Linux in mehreren Programmiersprachen bereitgestellt.

In den meisten Fällen spiegelt das API-Design die Präferenz für Leistung gegenüber Benutzerfreundlichkeit wider. TensorFlow Lite wurde für den schnellen Rückschluss auf kleine Geräte entwickelt. Daher sollte es nicht überraschen, dass die APIs versuchen, unnötige Kopien auf Kosten der Benutzerfreundlichkeit zu vermeiden. Ebenso war die Konsistenz mit TensorFlow-APIs kein explizites Ziel, und es ist mit Abweichungen zwischen den Sprachen zu rechnen.

Über alle Bibliotheken hinweg können Sie mit der TensorFlow Lite-API Modelle laden, Eingaben füttern und Inferenzausgaben abrufen.

Android-Plattform

Unter Android kann die TensorFlow Lite-Inferenz entweder mit Java- oder C ++ - APIs durchgeführt werden. Die Java-APIs bieten Komfort und können direkt in Ihren Android-Aktivitätsklassen verwendet werden. Die C ++ - APIs bieten mehr Flexibilität und Geschwindigkeit, erfordern jedoch möglicherweise das Schreiben von JNI-Wrappern, um Daten zwischen Java- und C ++ - Ebenen zu verschieben.

Weitere Informationen zur Verwendung von C ++ und Java finden Sie weiter unten. Im Android-Schnellstart finden Sie ein Tutorial und einen Beispielcode.

TensorFlow Lite Android Wrapper Code Generator

Für das mit Metadaten erweiterte TensorFlow Lite-Modell können Entwickler den TensorFlow Lite-Android-Wrapper-Codegenerator verwenden, um plattformspezifischen Wrapper-Code zu erstellen. Der Wrapper-Code macht die direkte Interaktion mit ByteBuffer unter Android ByteBuffer . Stattdessen können Entwickler mit dem TensorFlow Lite-Modell mit typisierten Objekten wie Bitmap und Rect interagieren. Weitere Informationen finden Sie im TensorFlow Lite Android Wrapper Code Generator .

iOS-Plattform

Unter iOS ist TensorFlow Lite mit nativen iOS-Bibliotheken verfügbar, die in Swift und Objective-C geschrieben sind . Sie können die C-API auch direkt in Objective-C-Codes verwenden.

Im Folgenden finden Sie Details zur Verwendung von Swift , Objective-C und der C-API . Im iOS-Schnellstart finden Sie ein Tutorial und einen Beispielcode.

Linux-Plattform

Auf Linux-Plattformen (einschließlich Raspberry Pi ) können Sie mithilfe der in C ++ und Python verfügbaren TensorFlow Lite-APIs Inferenzen ausführen, wie in den folgenden Abschnitten gezeigt.

Ein Modell ausführen

Das Ausführen eines TensorFlow Lite-Modells umfasst einige einfache Schritte:

  1. Laden Sie das Modell in den Speicher.
  2. Erstellen Sie einen Interpreter basierend auf einem vorhandenen Modell.
  3. Stellen Sie die Eingangstensorwerte ein. (Ändern Sie optional die Größe der Eingangstensoren, wenn die vordefinierten Größen nicht gewünscht werden.)
  4. Inferenz aufrufen.
  5. Lesen Sie die Ausgangstensorwerte.

In den folgenden Abschnitten wird beschrieben, wie diese Schritte in jeder Sprache ausgeführt werden können.

Laden Sie ein Modell und führen Sie es in Java aus

Plattform: Android

Die Java-API zum Ausführen einer Inferenz mit TensorFlow Lite wurde hauptsächlich für die Verwendung mit Android entwickelt. Sie ist daher als Android-Bibliotheksabhängigkeit verfügbar: org.tensorflow:tensorflow-lite .

In Java verwenden Sie die Interpreter Klasse, um ein Modell zu laden und die Modellinferenz zu steuern. In vielen Fällen ist dies möglicherweise die einzige API, die Sie benötigen.

Sie können einen Interpreter mithilfe einer .tflite Datei initialisieren:

public Interpreter(@NotNull File modelFile);

Oder mit einem MappedByteBuffer :

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

In beiden Fällen müssen Sie ein gültiges TensorFlow Lite-Modell IllegalArgumentException oder die API IllegalArgumentException . Wenn Sie einen Interpreter mit MappedByteBuffer initialisieren, muss dieser für die gesamte Lebensdauer des Interpreter unverändert bleiben.

Um dann eine Inferenz mit dem Modell durchzuführen, rufen Sie einfach Interpreter.run() . Beispielsweise:

try (Interpreter interpreter = new Interpreter(file_of_a_tensorflowlite_model)) {
  interpreter.run(input, output);
}

Die run() -Methode akzeptiert nur eine Eingabe und gibt nur eine Ausgabe zurück. Wenn Ihr Modell also mehrere Eingänge oder mehrere Ausgänge hat, verwenden Sie stattdessen:

interpreter.runForMultipleInputsOutputs(inputs, map_of_indices_to_outputs);

In diesem Fall entspricht jeder Eintrag in inputs einem Eingangstensor, und map_of_indices_to_outputs ordnet Indizes von Ausgangstensoren den entsprechenden Ausgangsdaten zu.

In beiden Fällen sollten die Tensorindizes den Werten entsprechen, die Sie dem TensorFlow Lite Converter beim Erstellen des Modells gegeben haben. Beachten Sie, dass die Reihenfolge der input Tensoren mit der Reihenfolge des TensorFlow Lite-Konverters übereinstimmen muss.

Die Interpreter Klasse bietet außerdem praktische Funktionen, mit denen Sie den Index aller Modelleingaben oder -ausgaben unter Verwendung eines Operationsnamens abrufen können:

public int getInputIndex(String opName);
public int getOutputIndex(String opName);

Wenn opName keine gültige Operation im Modell ist, wird eine IllegalArgumentException .

Beachten Sie auch, dass der Interpreter Ressourcen besitzt. Um Speicherverluste zu vermeiden, müssen die Ressourcen nach der Verwendung freigegeben werden durch:

interpreter.close();

Ein Beispielprojekt mit Java finden Sie im Beispiel für die Klassifizierung von Android-Bildern .

Unterstützte Datentypen (in Java)

Um TensorFlow Lite verwenden zu können, müssen die Datentypen der Eingabe- und Ausgabe-Tensoren einer der folgenden primitiven Typen sein:

  • float
  • int
  • long
  • byte

String werden ebenfalls unterstützt, sie werden jedoch anders als die primitiven Typen codiert. Insbesondere bestimmt die Form eines String-Tensors die Anzahl und Anordnung der Strings im Tensor, wobei jedes Element selbst ein String mit variabler Länge ist. In diesem Sinne kann die (Byte-) Größe des Tensors nicht allein aus Form und Typ berechnet werden, und folglich können Zeichenfolgen nicht als einzelnes, flaches ByteBuffer Argument ByteBuffer .

Wenn andere Datentypen verwendet werden, einschließlich Box-Typen wie Integer und Float , wird eine IllegalArgumentException ausgelöst.

Eingänge

Jede Eingabe sollte ein Array oder ein mehrdimensionales Array der unterstützten primitiven Typen oder ein roher ByteBuffer der entsprechenden Größe sein. Wenn die Eingabe ein Array oder ein mehrdimensionales Array ist, wird der zugehörige Eingangstensor zum Inferenzzeitpunkt implizit auf die Abmessungen des Arrays angepasst. Wenn die Eingabe ein ByteBuffer ist, sollte der Aufrufer zuerst die Größe des zugeordneten Eingabetensors manuell ändern (über Interpreter.resizeInput() ), bevor er die Inferenz ausführt.

Verwenden ByteBuffer Verwendung von ByteBuffer lieber direkte ByteBuffer , da der Interpreter unnötige Kopien vermeiden kann. Wenn der ByteBuffer ein direkter ByteBuffer ist, muss seine Reihenfolge ByteOrder.nativeOrder() . Nachdem es für eine Modellinferenz verwendet wurde, muss es unverändert bleiben, bis die Modellinferenz beendet ist.

Ausgänge

Jede Ausgabe sollte ein Array oder ein mehrdimensionales Array der unterstützten primitiven Typen oder ein ByteBuffer der entsprechenden Größe sein. Beachten Sie, dass einige Modelle dynamische Ausgänge haben, bei denen die Form der Ausgangstensoren je nach Eingang variieren kann. Es gibt keine einfache Möglichkeit, dies mit der vorhandenen Java-Inferenz-API zu handhaben, aber geplante Erweiterungen werden dies ermöglichen.

Laden Sie ein Modell und führen Sie es in Swift aus

Plattform: iOS

Die Swift-API ist in TensorFlowLiteSwift Pod von Cocoapods erhältlich.

Zunächst müssen Sie das TensorFlowLite Modul importieren.

import TensorFlowLite
// Getting model path
guard
  let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite")
else {
  // Error handling...
}

do {
  // Initialize an interpreter with the model.
  let interpreter = try Interpreter(modelPath: modelPath)

  // Allocate memory for the model's input `Tensor`s.
  try interpreter.allocateTensors()

  let inputData: Data  // Should be initialized

  // input data preparation...

  // Copy the input data to the input `Tensor`.
  try self.interpreter.copy(inputData, toInputAt: 0)

  // Run inference by invoking the `Interpreter`.
  try self.interpreter.invoke()

  // Get the output `Tensor`
  let outputTensor = try self.interpreter.output(at: 0)

  // Copy output to `Data` to process the inference results.
  let outputSize = outputTensor.shape.dimensions.reduce(1, {x, y in x * y})
  let outputData =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: outputSize)
  outputTensor.data.copyBytes(to: outputData)

  if (error != nil) { /* Error handling... */ }
} catch error {
  // Error handling...
}

Laden Sie ein Modell in Objective-C und führen Sie es aus

Plattform: iOS

Die Objective-C-API ist in TensorFlowLiteObjC Pod von Cocoapods verfügbar.

Zunächst müssen Sie das TensorFlowLite Modul importieren.

@import TensorFlowLite;
NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];
NSError *error;

// Initialize an interpreter with the model.
TFLInterpreter *interpreter = [[TFLInterpreter alloc] initWithModelPath:modelPath
                                                                  error:&error];
if (error != nil) { /* Error handling... */ }

// Allocate memory for the model's input `TFLTensor`s.
[interpreter allocateTensorsWithError:&error];
if (error != nil) { /* Error handling... */ }

NSMutableData *inputData;  // Should be initialized
// input data preparation...

// Copy the input data to the input `TFLTensor`.
[interpreter copyData:inputData toInputTensorAtIndex:0 error:&error];
if (error != nil) { /* Error handling... */ }

// Run inference by invoking the `TFLInterpreter`.
[interpreter invokeWithError:&error];
if (error != nil) { /* Error handling... */ }

// Get the output `TFLTensor`
TFLTensor *outputTensor = [interpreter outputTensorAtIndex:0 error:&error];
if (error != nil) { /* Error handling... */ }

// Copy output to `NSData` to process the inference results.
NSData *outputData = [outputTensor dataWithError:&amp;error];
if (error != nil) { /* Error handling... */ }

Verwenden der C-API im Objective-C-Code

Derzeit unterstützt die Objective-C-API keine Delegierten. Um Delegaten mit Objective-C-Code verwenden zu können, müssen Sie die zugrunde liegende C-API direkt aufrufen.

#include "tensorflow/lite/c/c_api.h"
TfLiteModel* model = TfLiteModelCreateFromFile([modelPath UTF8String]);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();

// Create the interpreter.
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);

// Allocate tensors and populate the input tensor data.
TfLiteInterpreterAllocateTensors(interpreter);
TfLiteTensor* input_tensor =
    TfLiteInterpreterGetInputTensor(interpreter, 0);
TfLiteTensorCopyFromBuffer(input_tensor, input.data(),
                           input.size() * sizeof(float));

// Execute inference.
TfLiteInterpreterInvoke(interpreter);

// Extract the output tensor data.
const TfLiteTensor* output_tensor =
    TfLiteInterpreterGetOutputTensor(interpreter, 0);
TfLiteTensorCopyToBuffer(output_tensor, output.data(),
                         output.size() * sizeof(float));

// Dispose of the model and interpreter objects.
TfLiteInterpreterDelete(interpreter);
TfLiteInterpreterOptionsDelete(options);
TfLiteModelDelete(model);

Laden Sie ein Modell und führen Sie es in C ++ aus

Plattformen: Android, iOS und Linux

In C ++ wird das Modell in der FlatBufferModel Klasse gespeichert. Es kapselt ein TensorFlow Lite-Modell und Sie können es auf verschiedene Arten erstellen, je nachdem, wo das Modell gespeichert ist:

class FlatBufferModel {
  // Build a model based on a file. Return a nullptr in case of failure.
  static std::unique_ptr<FlatBufferModel> BuildFromFile(
      const char* filename,
      ErrorReporter* error_reporter);

  // Build a model based on a pre-loaded flatbuffer. The caller retains
  // ownership of the buffer and should keep it alive until the returned object
  // is destroyed. Return a nullptr in case of failure.
  static std::unique_ptr<FlatBufferModel> BuildFromBuffer(
      const char* buffer,
      size_t buffer_size,
      ErrorReporter* error_reporter);
};

FlatBufferModel Sie das Modell als FlatBufferModel Objekt haben, können Sie es mit einem Interpreter ausführen. Ein einzelnes FlatBufferModel kann gleichzeitig von mehr als einem Interpreter .

Die wichtigen Teile der Interpreter API werden im folgenden Codeausschnitt gezeigt. Es sollte erwähnt werden, dass:

  • Tensoren werden durch Ganzzahlen dargestellt, um Zeichenfolgenvergleiche (und eine feste Abhängigkeit von Zeichenfolgenbibliotheken) zu vermeiden.
  • Auf einen Interpreter darf nicht über gleichzeitige Threads zugegriffen werden.
  • Die Speicherzuordnung für Eingangs- und Ausgangstensoren muss durch Aufrufen von AllocateTensors() direkt nach der Größenänderung der Tensoren ausgelöst werden.

Die einfachste Verwendung von TensorFlow Lite mit C ++ sieht folgendermaßen aus:

// Load the model
std::unique_ptr<tflite::FlatBufferModel> model =
    tflite::FlatBufferModel::BuildFromFile(filename);

// Build the interpreter
tflite::ops::builtin::BuiltinOpResolver resolver;
std::unique_ptr<tflite::Interpreter> interpreter;
tflite::InterpreterBuilder(*model, resolver)(&interpreter);

// Resize input tensors, if desired.
interpreter->AllocateTensors();

float* input = interpreter->typed_input_tensor<float>(0);
// Fill `input`.

interpreter->Invoke();

float* output = interpreter->typed_output_tensor<float>(0);

Weitere Beispielcodes finden Sie unter minimal.cc und label_image.cc .

Laden Sie ein Modell und führen Sie es in Python aus

Plattform: Linux

Die Python-API zum Ausführen einer Inferenz wird im Modul tf.lite bereitgestellt. Von diesem benötigen Sie meist nur tf.lite.Interpreter , um ein Modell zu laden und eine Inferenz auszuführen.

Das folgende Beispiel zeigt, wie Sie mit dem Python-Interpreter eine .tflite Datei laden und Inferenzen mit zufälligen Eingabedaten ausführen:

import numpy as np
import tensorflow as tf

# Load the TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_path="converted_model.tflite")
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# Test the model on random input data.
input_shape = input_details[0]['shape']
input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32)
interpreter.set_tensor(input_details[0]['index'], input_data)

interpreter.invoke()

# The function `get_tensor()` returns a copy of the tensor data.
# Use `tensor()` in order to get a pointer to the tensor.
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

Alternativ zum Laden des Modells als .tflite Datei können Sie Ihren Code mit der Python-API von TensorFlow Lite Converter ( tf.lite.TFLiteConverter ) tf.lite.TFLiteConverter und so Ihr TensorFlow-Modell in das TensorFlow Lite-Format konvertieren Inferenz ausführen:

import numpy as np
import tensorflow as tf

img = tf.placeholder(name="img", dtype=tf.float32, shape=(1, 64, 64, 3))
const = tf.constant([1., 2., 3.]) + tf.constant([1., 4., 4.])
val = img + const
out = tf.identity(val, name="out")

# Convert to TF Lite format
with tf.Session() as sess:
  converter = tf.lite.TFLiteConverter.from_session(sess, [img], [out])
  tflite_model = converter.convert()

# Load the TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_content=tflite_model)
interpreter.allocate_tensors()

# Continue to get tensors and so forth, as shown above...

Weitere Python-Beispielcodes finden Sie unter label_image.py .

Tipp: Führen Sie die help(tf.lite.Interpreter) im Python-Terminal aus, um eine detaillierte Dokumentation zum Interpreter zu erhalten.

Unterstützte Operationen

TensorFlow Lite unterstützt eine Teilmenge von TensorFlow-Vorgängen mit einigen Einschränkungen. Eine vollständige Liste der Vorgänge und Einschränkungen finden Sie auf der Seite TF Lite Ops .