Mit ML Kit können Sie On-Device-Inferenzen mit einem TensorFlow Lite-Modell ausführen.
Für diese API ist das Android SDK-Level 16 (Jelly Bean) oder höher erforderlich.
Hinweis
- Falls noch nicht geschehen, Fügen Sie Firebase zu Ihrem Android-Projekt hinzu.
- Abhängigkeiten für die ML Kit-Android-Bibliotheken zu Ihrem Modul hinzufügen
Gradle-Datei auf App-Ebene (in der Regel
app/build.gradle
):apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' dependencies { // ... implementation 'com.google.firebase:firebase-ml-model-interpreter:22.0.3' }
- Konvertieren Sie das gewünschte TensorFlow-Modell in das TensorFlow Lite-Format. Weitere Informationen finden Sie unter TOCO: TensorFlow Lite Optimization Converter.
Modell hosten oder bündeln
Bevor Sie ein TensorFlow Lite-Modell für Inferenzen in Ihrer App verwenden können, müssen Sie muss das Modell für ML Kit verfügbar gemacht werden. ML Kit kann TensorFlow Lite-Modelle verwenden, die mit Firebase aus der Ferne gehostet, im App-Binärcode gebündelt oder beides sind.
Wenn Sie ein Modell auf Firebase hosten, können Sie es aktualisieren, ohne ein neue App-Version und du kannst Remote Config und A/B Testing für Folgendes verwenden: verschiedenen Gruppen von Nutzern dynamisch verschiedene Modelle bereitstellen.
Wenn Sie das Modell nur durch das Hosting mit Firebase und nicht mit Ihrer App bündeln, können Sie die anfängliche Downloadgröße Ihrer App reduzieren. Wenn das Modell nicht in Ihrer App enthalten ist, modellbezogene Funktionen sind erst verfügbar, wenn Ihre App die um ein neues Modell zu erstellen.
Wenn Sie Ihr Modell mit Ihrer App bündeln, können Sie dafür sorgen, dass die ML-Features Ihrer App funktionieren auch, wenn das von Firebase gehostete Modell nicht verfügbar ist.
Modelle in Firebase hosten
So hosten Sie Ihr TensorFlow Lite-Modell in Firebase:
- Klicken Sie in der Firebase-Konsole im Abschnitt ML Kit auf den Tab Benutzerdefiniert aus.
- Klicken Sie auf Benutzerdefiniertes Modell hinzufügen oder Weitere Modelle hinzufügen.
- Geben Sie einen Namen an, mit dem das Modell in Firebase identifiziert wird
und laden Sie dann die TensorFlow Lite-Modelldatei hoch, die in der Regel auf
.tflite
oder.lite
). - Deklarieren Sie im Manifest Ihrer App, dass die Berechtigung INTERNET erforderlich ist:
<uses-permission android:name="android.permission.INTERNET" />
Nachdem Sie Ihrem Firebase-Projekt ein benutzerdefiniertes Modell hinzugefügt haben, können Sie in Ihren Apps auf das Modell mit dem angegebenen Namen verweisen. Sie können jederzeit ein neues TensorFlow Lite-Modell hochladen. Ihre App lädt das neue Modell herunter und verwendet es beim nächsten Neustart der App. Sie können festlegen, Bedingungen erfüllt, damit Ihre App versucht, das Modell zu aktualisieren (siehe unten).
Modelle mit einer App bündeln
Um Ihr TensorFlow Lite-Modell mit Ihrer App zu bündeln, kopieren Sie die Modelldatei (in der Regel
mit den Endziffern .tflite
oder .lite
) in den Ordner assets/
Ihrer App verschieben. (Möglicherweise benötigen Sie
um den Ordner zu erstellen, indem Sie mit der rechten Maustaste auf den Ordner app/
klicken und dann
Neu > Ordner > Asset-Ordner.
Fügen Sie dann der Datei build.gradle
Ihrer App Folgendes hinzu, damit Gradle funktioniert.
werden die Modelle beim Erstellen der App nicht komprimiert:
android {
// ...
aaptOptions {
noCompress "tflite" // Your model's file extension: "tflite", "lite", etc.
}
}
Die Modelldatei ist im App-Paket enthalten und für ML Kit verfügbar als unbearbeitetes Asset.
Modell laden
Um Ihr TensorFlow Lite-Modell in Ihrer App zu verwenden, konfigurieren Sie zuerst ML Kit mit Standorte, an denen Ihr Modell verfügbar ist: remote mit Firebase, in lokalen Speicher oder beides. Wenn Sie sowohl ein lokales als auch ein Remote-Modell angeben, können Sie das Remote-Modell verwenden, falls verfügbar, und auf das lokal gespeichertes Modell verwenden, wenn das Remote-Modell nicht verfügbar ist.Ein von Firebase gehostetes Modell konfigurieren
Wenn Sie Ihr Modell bei Firebase gehostet haben, erstellen Sie eine FirebaseCustomRemoteModel
und geben Sie den Namen an, den Sie dem Modell beim Hochladen zugewiesen haben:
Java
FirebaseCustomRemoteModel remoteModel =
new FirebaseCustomRemoteModel.Builder("your_model").build();
Kotlin+KTX
val remoteModel = FirebaseCustomRemoteModel.Builder("your_model").build()
Starten Sie dann den Modelldownload und geben Sie die Bedingungen an, unter denen Sie den Download erlauben möchten. Wenn das Modell nicht auf dem Gerät installiert ist oder ein neueres Modell Version des Modells verfügbar ist, lädt die Aufgabe asynchron das aus Firebase verwenden:
Java
FirebaseModelDownloadConditions conditions = new FirebaseModelDownloadConditions.Builder()
.requireWifi()
.build();
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
// Success.
}
});
Kotlin+KTX
val conditions = FirebaseModelDownloadConditions.Builder()
.requireWifi()
.build()
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnCompleteListener {
// Success.
}
Viele Apps starten die Download-Aufgabe im Initialisierungscode, aber Sie können bevor Sie das Modell verwenden.
Lokales Modell konfigurieren
Wenn Sie das Modell mit Ihrer App gebündelt haben, erstellen Sie eine FirebaseCustomLocalModel
.
-Objekt und geben Sie den Dateinamen des TensorFlow Lite-Modells an:
Java
FirebaseCustomLocalModel localModel = new FirebaseCustomLocalModel.Builder()
.setAssetFilePath("your_model.tflite")
.build();
Kotlin+KTX
val localModel = FirebaseCustomLocalModel.Builder()
.setAssetFilePath("your_model.tflite")
.build()
Interpreter aus Ihrem Modell erstellen
Nachdem Sie die Modellquellen konfiguriert haben, erstellen Sie eine FirebaseModelInterpreter
Objekt aus einem von ihnen.
Wenn Sie nur ein lokal gebündeltes Modell haben, erstellen Sie einfach einen Dolmetscher in Ihrem
Objekt FirebaseCustomLocalModel
:
Java
FirebaseModelInterpreter interpreter;
try {
FirebaseModelInterpreterOptions options =
new FirebaseModelInterpreterOptions.Builder(localModel).build();
interpreter = FirebaseModelInterpreter.getInstance(options);
} catch (FirebaseMLException e) {
// ...
}
Kotlin+KTX
val options = FirebaseModelInterpreterOptions.Builder(localModel).build()
val interpreter = FirebaseModelInterpreter.getInstance(options)
Wenn Sie ein extern gehostetes Modell haben, müssen Sie prüfen,
die Sie vor der Ausführung heruntergeladen haben. Sie können den Status des Modelldownloads
mit der Methode isModelDownloaded()
des Modellmanagers.
Sie müssen dies nur vor der Ausführung des Dolmetschers bestätigen. Wenn Sie ein remote gehostetes und ein lokal gebündeltes Modell haben, sinnvoll, diese Prüfung beim Instanziieren des Modellinterpreters durchzuführen: Interpreter aus dem Remote-Modell, falls es heruntergeladen wurde, und aus dem modellieren.
Java
FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
.addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean isDownloaded) {
FirebaseModelInterpreterOptions options;
if (isDownloaded) {
options = new FirebaseModelInterpreterOptions.Builder(remoteModel).build();
} else {
options = new FirebaseModelInterpreterOptions.Builder(localModel).build();
}
FirebaseModelInterpreter interpreter = FirebaseModelInterpreter.getInstance(options);
// ...
}
});
Kotlin+KTX
FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
.addOnSuccessListener { isDownloaded ->
val options =
if (isDownloaded) {
FirebaseModelInterpreterOptions.Builder(remoteModel).build()
} else {
FirebaseModelInterpreterOptions.Builder(localModel).build()
}
val interpreter = FirebaseModelInterpreter.getInstance(options)
}
Wenn Sie nur ein remote gehostetes Modell haben, sollten Sie die modellbezogenen
wie z. B. das Ausgrauen oder Ausblenden eines Teils der Benutzeroberfläche, bis
bestätigen Sie, dass das Modell heruntergeladen wurde. Hängen Sie hierzu einen Listener an.
zur download()
-Methode des Modellmanagers hinzu:
Java
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
// Download complete. Depending on your app, you could enable
// the ML feature, or switch from the local model to the remote
// model, etc.
}
});
Kotlin+KTX
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnCompleteListener {
// Download complete. Depending on your app, you could enable the ML
// feature, or switch from the local model to the remote model, etc.
}
Eingabe und Ausgabe des Modells angeben
Konfigurieren Sie als Nächstes die Ein- und Ausgabeformate des Modellinterpreters.
Ein TensorFlow Lite-Modell übernimmt als Eingabe und erzeugt als Ausgabe eine oder mehrere
multidimensionale Arrays. Diese Arrays enthalten entweder byte
,
int
-, long
- oder float
-Werte. Sie müssen ML Kit mit der Anzahl und den Dimensionen („Form“) der Arrays konfigurieren, die in Ihrem Modell verwendet werden.
Wenn Sie die Form und den Datentyp der Eingabe und Ausgabe Ihres Modells nicht kennen, können Sie Ihr Modell mit dem Python-Interpreter von TensorFlow Lite überprüfen. Beispiel:
import tensorflow as tf interpreter = tf.lite.Interpreter(model_path="my_model.tflite") interpreter.allocate_tensors() # Print input shape and type print(interpreter.get_input_details()[0]['shape']) # Example: [1 224 224 3] print(interpreter.get_input_details()[0]['dtype']) # Example: <class 'numpy.float32'> # Print output shape and type print(interpreter.get_output_details()[0]['shape']) # Example: [1 1000] print(interpreter.get_output_details()[0]['dtype']) # Example: <class 'numpy.float32'>
Nachdem Sie das Format der Ein- und Ausgabe Ihres Modells bestimmt haben, können Sie
den Modellinterpreter Ihrer App konfigurieren, indem Sie einen
FirebaseModelInputOutputOptions
-Objekt.
Ein Gleitkomma-Bildklassifizierungsmodell kann beispielsweise
Nx224x224x3-Array mit float
-Werten, die eine Gruppe von
N 224 x 224 Drei-Kanal-Bilder (RGB) und produzieren als Ausgabe eine Liste mit
1.000 float
-Werte, die jeweils die Wahrscheinlichkeit darstellen, zu der das Bild gehört
einer der 1.000 Kategorien,
die das Modell vorhersagt.
Für ein solches Modell konfigurieren Sie die Eingabe und Ausgabe des Modellinterpreters wie unten gezeigt:
Java
FirebaseModelInputOutputOptions inputOutputOptions = new FirebaseModelInputOutputOptions.Builder() .setInputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 224, 224, 3}) .setOutputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 5}) .build();
Kotlin+KTX
val inputOutputOptions = FirebaseModelInputOutputOptions.Builder() .setInputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 224, 224, 3)) .setOutputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 5)) .build()
Inferenzen auf Eingabedaten durchführen
Um schließlich Inferenzen mit dem Modell durchzuführen, rufen Sie Ihre Eingabedaten ab und führen Sie alle Transformationen an den Daten durch, die erforderlich sind, um ein Eingabearray der richtigen Form für Ihr Modell zu erhalten.Wenn Sie z. B. ein Bildklassifizierungsmodell mit der Eingabeform
[1 224 224 3] Gleitkommazahlen ist, könnten Sie ein Eingabearray aus einer
Bitmap
-Objekt, wie im folgenden Beispiel gezeigt:
Java
Bitmap bitmap = getYourInputImage(); bitmap = Bitmap.createScaledBitmap(bitmap, 224, 224, true); int batchNum = 0; float[][][][] input = new float[1][224][224][3]; for (int x = 0; x < 224; x++) { for (int y = 0; y < 224; y++) { int pixel = bitmap.getPixel(x, y); // Normalize channel values to [-1.0, 1.0]. This requirement varies by // model. For example, some models might require values to be normalized // to the range [0.0, 1.0] instead. input[batchNum][x][y][0] = (Color.red(pixel) - 127) / 128.0f; input[batchNum][x][y][1] = (Color.green(pixel) - 127) / 128.0f; input[batchNum][x][y][2] = (Color.blue(pixel) - 127) / 128.0f; } }
Kotlin+KTX
val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true) val batchNum = 0 val input = Array(1) { Array(224) { Array(224) { FloatArray(3) } } } for (x in 0..223) { for (y in 0..223) { val pixel = bitmap.getPixel(x, y) // Normalize channel values to [-1.0, 1.0]. This requirement varies by // model. For example, some models might require values to be normalized // to the range [0.0, 1.0] instead. input[batchNum][x][y][0] = (Color.red(pixel) - 127) / 255.0f input[batchNum][x][y][1] = (Color.green(pixel) - 127) / 255.0f input[batchNum][x][y][2] = (Color.blue(pixel) - 127) / 255.0f } }
Erstellen Sie dann ein FirebaseModelInputs
-Objekt mit Ihrem
Eingabedaten an und übergeben Sie diese sowie die Eingabe- und Ausgabespezifikation des Modells an den
Methode des Modellinterpretersrun
:
Java
FirebaseModelInputs inputs = new FirebaseModelInputs.Builder() .add(input) // add() as many input arrays as your model requires .build(); firebaseInterpreter.run(inputs, inputOutputOptions) .addOnSuccessListener( new OnSuccessListener<FirebaseModelOutputs>() { @Override public void onSuccess(FirebaseModelOutputs result) { // ... } }) .addOnFailureListener( new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
Kotlin+KTX
val inputs = FirebaseModelInputs.Builder() .add(input) // add() as many input arrays as your model requires .build() firebaseInterpreter.run(inputs, inputOutputOptions) .addOnSuccessListener { result -> // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
Wenn der Aufruf erfolgreich ist, können Sie die Ausgabe abrufen, indem Sie die Methode getOutput()
aufrufen.
des Objekts, das an den Erfolgs-Listener übergeben wird. Beispiel:
Java
float[][] output = result.getOutput(0); float[] probabilities = output[0];
Kotlin+KTX
val output = result.getOutput<Array<FloatArray>>(0) val probabilities = output[0]
Wie Sie die Ausgabe verwenden, hängt vom verwendeten Modell ab.
Bei der Klassifizierung könnten Sie als nächsten Schritt ordnen Sie die Indexe des Ergebnisses den von ihnen dargestellten Labels zu:
Java
BufferedReader reader = new BufferedReader( new InputStreamReader(getAssets().open("retrained_labels.txt"))); for (int i = 0; i < probabilities.length; i++) { String label = reader.readLine(); Log.i("MLKit", String.format("%s: %1.4f", label, probabilities[i])); }
Kotlin+KTX
val reader = BufferedReader( InputStreamReader(assets.open("retrained_labels.txt"))) for (i in probabilities.indices) { val label = reader.readLine() Log.i("MLKit", String.format("%s: %1.4f", label, probabilities[i])) }
Anhang: Modellsicherheit
Unabhängig davon, wie Sie Ihre TensorFlow Lite-Modelle für ML Kit speichert sie im standardisierten, serialisierten protobuf-Format lokalen Speicher.
Theoretisch bedeutet dies, dass jeder Ihr Modell kopieren kann. Sie können jedoch in der Praxis sind die meisten Modelle so anwendungsspezifisch Optimierungen vorzunehmen, bei denen das Risiko dem der Konkurrenz beim Auseinanderbauen und Ihren Code wiederverwenden. Sie sollten sich jedoch über dieses Risiko im Klaren sein, bevor Sie ein benutzerdefiniertes Modell in Ihrer App erstellen.
Unter Android API-Level 21 (Lollipop) und höher wird das Modell Verzeichnis, das ist aus der automatischen Sicherung ausgeschlossen werden.
Unter Android API-Level 20 und älter wird das Modell in ein Verzeichnis heruntergeladen
namens com.google.firebase.ml.custom.models
in app-private
internen Speicher. Wenn Sie die Dateisicherung mit BackupAgent
aktiviert haben, können Sie dieses Verzeichnis ausschließen.