Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

Verwenden Sie ein benutzerdefiniertes TensorFlow Lite-Modell auf Android

Wenn Ihre App benutzerdefinierte verwendet TensorFlow Lite Modelle, können Sie Firebase ML verwenden , um Ihre Modelle bereitstellen. Durch die Bereitstellung von Modellen mit Firebase können Sie die anfängliche Downloadgröße Ihrer App reduzieren und die ML-Modelle Ihrer App aktualisieren, ohne eine neue Version Ihrer App zu veröffentlichen. Und mit Remote Config und A/B-Tests können Sie verschiedene Modelle dynamisch für verschiedene Benutzergruppen bereitstellen.

TensorFlow Lite-Modelle

TensorFlow Lite-Modelle sind ML-Modelle, die für die Ausführung auf mobilen Geräten optimiert sind. So erhalten Sie ein TensorFlow Lite-Modell:

Bevor Sie beginnen

  1. Wenn Sie nicht bereits haben, fügen Sie Firebase zu dem Android - Projekt .
  2. Mit Hilfe der Firebase Android BoM , erklärt die Abhängigkeit für die Firebase ML Modell Downloader Android - Bibliothek in Ihrem Modul (app-Ebene) Gradle Datei ( in der Regel app/build.gradle ).

    Außerdem müssen Sie beim Einrichten des Firebase ML-Modell-Downloaders das TensorFlow Lite SDK zu Ihrer App hinzufügen.

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare the dependency for the Firebase ML model downloader library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-modeldownloader'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    Durch die Verwendung des Firebase Android BoM werden, Ihre App immer kompatible Versionen der Firebase Android - Bibliotheken verwenden.

    (Alternative) Deklarieren Firebase Bibliothek Abhängigkeiten , ohne die BoM mit

    Wenn Sie die Firebase-Stückliste nicht verwenden möchten, müssen Sie jede Firebase-Bibliotheksversion in ihrer Abhängigkeitszeile angeben.

    Beachten Sie, dass , wenn Sie mehrere Firebase Bibliotheken in Ihrer Anwendung verwenden wir mit der BoM empfehlen Bibliothek Versionen zu verwalten, die sicherstellt , dass alle Versionen kompatibel sind.

    dependencies {
        // Declare the dependency for the Firebase ML model downloader library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-modeldownloader:24.0.0'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare the dependency for the Firebase ML model downloader library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-modeldownloader-ktx'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    Durch die Verwendung des Firebase Android BoM werden, Ihre App immer kompatible Versionen der Firebase Android - Bibliotheken verwenden.

    (Alternative) Deklarieren Firebase Bibliothek Abhängigkeiten , ohne die BoM mit

    Wenn Sie die Firebase-Stückliste nicht verwenden möchten, müssen Sie jede Firebase-Bibliotheksversion in ihrer Abhängigkeitszeile angeben.

    Beachten Sie, dass , wenn Sie mehrere Firebase Bibliotheken in Ihrer Anwendung verwenden wir mit der BoM empfehlen Bibliothek Versionen zu verwalten, die sicherstellt , dass alle Versionen kompatibel sind.

    dependencies {
        // Declare the dependency for the Firebase ML model downloader library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-modeldownloader-ktx:24.0.0'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }
  3. In Ihrem App Manifest erklärt , dass INTERNET Genehmigung erforderlich ist:
    <uses-permission android:name="android.permission.INTERNET" />

1. Stellen Sie Ihr Modell bereit

Stellen Sie Ihre benutzerdefinierten TensorFlow-Modelle entweder über die Firebase-Konsole oder die Firebase Admin Python- und Node.js-SDKs bereit. Siehe Deploy und kundenspezifische Modelle verwalten .

Nachdem Sie Ihrem Firebase-Projekt ein benutzerdefiniertes Modell hinzugefügt haben, können Sie in Ihren Apps mit dem von Ihnen angegebenen Namen auf das Modell verweisen. Zu jeder Zeit können Sie ein neues TensorFlow Lite Modell einsetzen und das neue Modell auf den Geräten der Benutzer herunterladen durch den Aufruf getModel() (siehe unten).

2. Laden Sie das Modell auf das Gerät herunter und initialisieren Sie einen TensorFlow Lite-Interpreter

Um Ihr TensorFlow Lite-Modell in Ihrer App zu verwenden, verwenden Sie zuerst das Firebase ML SDK, um die neueste Version des Modells auf das Gerät herunterzuladen. Instanziieren Sie dann einen TensorFlow Lite-Interpreter mit dem Modell.

Um das Modell Download zu starten, rufen Sie die Modell - Downloader getModel() Methode, Angabe des Namens Sie das Modell zugewiesen , wenn Sie es hochgeladen, ob Sie wollen immer das neueste Modell herunterzuladen, und die Bedingungen , unter denen Sie das Herunterladen ermöglichen.

Sie können aus drei Download-Verhalten wählen:

Download-Typ Beschreibung
LOCAL_MODEL Rufen Sie das lokale Modell vom Gerät ab. Wenn es kein lokales Modell zur Verfügung, dies verhält sich wie LATEST_MODEL . Verwenden Sie diesen Downloadtyp, wenn Sie nicht nach Modellaktualisierungen suchen möchten. Sie verwenden beispielsweise Remote Config zum Abrufen von Modellnamen und laden Modelle immer unter neuen Namen hoch (empfohlen).
LOCAL_MODEL_UPDATE_IN_BACKGROUND Holen Sie sich das lokale Modell vom Gerät und starten Sie die Aktualisierung des Modells im Hintergrund. Wenn es kein lokales Modell zur Verfügung, dies verhält sich wie LATEST_MODEL .
NEUSTE MODELL Holen Sie sich das neueste Modell. Wenn das lokale Modell die neueste Version ist, wird das lokale Modell zurückgegeben. Laden Sie andernfalls das neueste Modell herunter. Dieses Verhalten wird blockiert, bis die neueste Version heruntergeladen wurde (nicht empfohlen). Verwenden Sie dieses Verhalten nur in Fällen, in denen Sie explizit die neueste Version benötigen.

Sie sollten modellbezogene Funktionen deaktivieren, z. B. einen Teil Ihrer Benutzeroberfläche ausblenden oder ausblenden, bis Sie bestätigen, dass das Modell heruntergeladen wurde.

Java

CustomModelDownloadConditions conditions = new CustomModelDownloadConditions.Builder()
    .requireWifi()  // Also possible: .requireCharging() and .requireDeviceIdle()
    .build();
FirebaseModelDownloader.getInstance()
    .getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND, conditions)
    .addOnSuccessListener(new OnSuccessListener<CustomModel>() {
      @Override
      public void onSuccess(CustomModel model) {
        // Download complete. Depending on your app, you could enable the ML
        // feature, or switch from the local model to the remote model, etc.

        // The CustomModel object contains the local path of the model file,
        // which you can use to instantiate a TensorFlow Lite interpreter.
        File modelFile = model.getFile();
        if (modelFile != null) {
            interpreter = new Interpreter(modelFile);
        }
      }
    });

Kotlin+KTX

val conditions = CustomModelDownloadConditions.Builder()
        .requireWifi()  // Also possible: .requireCharging() and .requireDeviceIdle()
        .build()
FirebaseModelDownloader.getInstance()
        .getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND,
            conditions)
        .addOnSuccessListener { model: CustomModel? ->
            // Download complete. Depending on your app, you could enable the ML
            // feature, or switch from the local model to the remote model, etc.

            // The CustomModel object contains the local path of the model file,
            // which you can use to instantiate a TensorFlow Lite interpreter.
            val modelFile = model?.file
            if (modelFile != null) {
                interpreter = Interpreter(modelFile)
            }
        }

Viele Apps starten die Download-Aufgabe in ihrem Initialisierungscode, aber Sie können dies jederzeit tun, bevor Sie das Modell verwenden müssen.

3. Inferenz auf Eingabedaten durchführen

Rufen Sie die Eingabe- und Ausgabeformen Ihres Modells ab

Der Modellinterpreter von TensorFlow Lite verwendet als Eingabe und erzeugt als Ausgabe ein oder mehrere mehrdimensionale Arrays. Diese Arrays enthalten entweder byte , int , long oder float Werte. Bevor Sie Daten an ein Modell übergeben oder dessen Ergebnis verwenden können, müssen Sie die Anzahl und Dimensionen ("Form") der von Ihrem Modell verwendeten Arrays kennen.

Wenn Sie das Modell selbst erstellt haben oder das Eingabe- und Ausgabeformat des Modells dokumentiert ist, verfügen Sie möglicherweise bereits über diese Informationen. Wenn Sie die Form und den Datentyp der Ein- und Ausgabe Ihres Modells nicht kennen, können Sie Ihr Modell mit dem TensorFlow Lite-Interpreter überprüfen. Zum Beispiel:

Python

import tensorflow as tf

interpreter = tf.lite.Interpreter(model_path="your_model.tflite")
interpreter.allocate_tensors()

# Print input shape and type
inputs = interpreter.get_input_details()
print('{} input(s):'.format(len(inputs)))
for i in range(0, len(inputs)):
    print('{} {}'.format(inputs[i]['shape'], inputs[i]['dtype']))

# Print output shape and type
outputs = interpreter.get_output_details()
print('\n{} output(s):'.format(len(outputs)))
for i in range(0, len(outputs)):
    print('{} {}'.format(outputs[i]['shape'], outputs[i]['dtype']))

Beispielausgabe:

1 input(s):
[  1 224 224   3] <class 'numpy.float32'>

1 output(s):
[1 1000] <class 'numpy.float32'>

Führen Sie den Dolmetscher aus

Nachdem Sie das Format der Eingabe und Ausgabe Ihres Modells bestimmt haben, rufen Sie Ihre Eingabedaten ab und führen Sie alle Transformationen an den Daten durch, die erforderlich sind, um eine Eingabe mit der richtigen Form für Ihr Modell zu erhalten.

Zum Beispiel, wenn man ein Bildklassifikationsmodell mit einer Eingangs Form haben [1 224 224 3] Gleitkommawerte, könnte man einen Eingangs erzeugen ByteBuffer von einem Bitmap - Objekt , wie im folgenden Beispiel gezeigt:

Java

Bitmap bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true);
ByteBuffer input = ByteBuffer.allocateDirect(224 * 224 * 3 * 4).order(ByteOrder.nativeOrder());
for (int y = 0; y < 224; y++) {
    for (int x = 0; x < 224; x++) {
        int px = bitmap.getPixel(x, y);

        // Get channel values from the pixel value.
        int r = Color.red(px);
        int g = Color.green(px);
        int b = Color.blue(px);

        // Normalize channel values to [-1.0, 1.0]. This requirement depends
        // on the model. For example, some models might require values to be
        // normalized to the range [0.0, 1.0] instead.
        float rf = (r - 127) / 255.0f;
        float gf = (g - 127) / 255.0f;
        float bf = (b - 127) / 255.0f;

        input.putFloat(rf);
        input.putFloat(gf);
        input.putFloat(bf);
    }
}

Kotlin+KTX

val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true)
val input = ByteBuffer.allocateDirect(224*224*3*4).order(ByteOrder.nativeOrder())
for (y in 0 until 224) {
    for (x in 0 until 224) {
        val px = bitmap.getPixel(x, y)

        // Get channel values from the pixel value.
        val r = Color.red(px)
        val g = Color.green(px)
        val b = Color.blue(px)

        // Normalize channel values to [-1.0, 1.0]. This requirement depends on the model.
        // For example, some models might require values to be normalized to the range
        // [0.0, 1.0] instead.
        val rf = (r - 127) / 255f
        val gf = (g - 127) / 255f
        val bf = (b - 127) / 255f

        input.putFloat(rf)
        input.putFloat(gf)
        input.putFloat(bf)
    }
}

Dann weisen Sie einen ByteBuffer groß genug , um die Ausgabe des Modells zu enthalten , und die Eingangspuffer und der Ausgangspuffer an den TensorFlow Lite Interpreter Pass run() Methode. Zum Beispiel für eine Ausgabeform [1 1000] Gleitkommawerte:

Java

int bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE;
ByteBuffer modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder());
interpreter.run(input, modelOutput);

Kotlin+KTX

val bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE
val modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder())
interpreter?.run(input, modelOutput)

Wie Sie die Ausgabe verwenden, hängt vom verwendeten Modell ab.

Wenn Sie beispielsweise eine Klassifizierung durchführen, können Sie im nächsten Schritt die Indizes des Ergebnisses den Bezeichnungen zuordnen, die sie darstellen:

Java

modelOutput.rewind();
FloatBuffer probabilities = modelOutput.asFloatBuffer();
try {
    BufferedReader reader = new BufferedReader(
            new InputStreamReader(getAssets().open("custom_labels.txt")));
    for (int i = 0; i < probabilities.capacity(); i++) {
        String label = reader.readLine();
        float probability = probabilities.get(i);
        Log.i(TAG, String.format("%s: %1.4f", label, probability));
    }
} catch (IOException e) {
    // File not found?
}

Kotlin+KTX

modelOutput.rewind()
val probabilities = modelOutput.asFloatBuffer()
try {
    val reader = BufferedReader(
            InputStreamReader(assets.open("custom_labels.txt")))
    for (i in probabilities.capacity()) {
        val label: String = reader.readLine()
        val probability = probabilities.get(i)
        println("$label: $probability")
    }
} catch (e: IOException) {
    // File not found?
}

Anhang: Modellsicherheit

Unabhängig davon, wie Sie Ihre TensorFlow Lite-Modelle für Firebase ML verfügbar machen, speichert Firebase ML sie im standardmäßigen serialisierten Protobuf-Format im lokalen Speicher.

Theoretisch bedeutet dies, dass jeder Ihr Modell kopieren kann. In der Praxis sind die meisten Modelle jedoch so anwendungsspezifisch und durch Optimierungen verschleiert, dass das Risiko ähnlich ist wie bei Konkurrenten, die Ihren Code zerlegen und wiederverwenden. Sie sollten sich dieses Risikos jedoch bewusst sein, bevor Sie ein benutzerdefiniertes Modell in Ihrer App verwenden.

Auf Android - API - Ebene 21 (Lollipop) und neuere, wird das Modell in ein Verzeichnis heruntergeladen, das wird von den automatischen Sicherung ausgeschlossen .

Auf Android - API - Ebene 20 und älter, wird das Modell auf ein Verzeichnis mit dem Namen heruntergeladen com.google.firebase.ml.custom.models in app-privaten internem Speicher. Wenn Sie Datei - Backup mit aktiviert BackupAgent , könnten Sie mit diesem Verzeichnis auszuschließen.