Wenn Ihre App benutzerdefinierte TensorFlow Lite- Modelle verwendet, können Sie Firebase ML zum Bereitstellen Ihrer Modelle verwenden. 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-Testing können Sie unterschiedliche Modelle dynamisch für verschiedene Benutzergruppen bereitstellen.
Voraussetzungen
- Die
MLModelDownloader
Bibliothek ist nur für Swift verfügbar. - TensorFlow Lite läuft nur auf Geräten mit iOS 9 und neuer.
TensorFlow Lite-Modelle
TensorFlow Lite-Modelle sind ML-Modelle, die für die Ausführung auf Mobilgeräten optimiert sind. So erhalten Sie ein TensorFlow Lite-Modell:
- Verwenden Sie ein vorgefertigtes Modell, beispielsweise eines der offiziellen TensorFlow Lite-Modelle .
- Konvertieren Sie ein TensorFlow-Modell, Keras-Modell oder eine konkrete Funktion in TensorFlow Lite.
Bevor Sie beginnen
Um TensorFlowLite mit Firebase zu verwenden, müssen Sie CocoaPods verwenden, da TensorFlowLite derzeit keine Installation mit Swift Package Manager unterstützt. Anweisungen zur Installation MLModelDownloader
finden Sie im CocoaPods-Installationshandbuch .
Importieren Sie nach der Installation Firebase und TensorFlowLite, um sie zu verwenden.
Schnell
import FirebaseMLModelDownloader
import TensorFlowLite
1. Stellen Sie Ihr Modell bereit
Stellen Sie Ihre benutzerdefinierten TensorFlow-Modelle entweder mit der Firebase-Konsole oder den Firebase Admin Python- und Node.js-SDKs bereit. Siehe Benutzerdefinierte Modelle bereitstellen und verwalten .
Nachdem Sie Ihrem Firebase-Projekt ein benutzerdefiniertes Modell hinzugefügt haben, können Sie in Ihren Apps unter dem von Ihnen angegebenen Namen auf das Modell verweisen. Sie können jederzeit ein neues TensorFlow Lite-Modell bereitstellen und das neue Modell auf die Geräte der Benutzer herunterladen, indem Sie getModel()
aufrufen (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, laden Sie zunächst mit dem Firebase ML SDK die neueste Version des Modells auf das Gerät herunter. Um den Modell-Download zu starten, rufen Sie die getModel()
-Methode des Modell-Downloaders auf. Geben Sie dabei den Namen an, den Sie dem Modell beim Hochladen zugewiesen haben, ob Sie immer das neueste Modell herunterladen möchten und die Bedingungen, unter denen Sie den Download zulassen möchten.
Sie können zwischen drei Download-Verhalten wählen:
Download-Typ | Beschreibung |
---|---|
localModel | Rufen Sie das lokale Modell vom Gerät ab. Wenn kein lokales Modell verfügbar ist, verhält sich dies wie latestModel . Verwenden Sie diesen Download-Typ, wenn Sie nicht daran interessiert sind, nach Modellaktualisierungen zu suchen. Sie verwenden beispielsweise Remote Config zum Abrufen von Modellnamen und laden Modelle immer unter neuen Namen hoch (empfohlen). |
localModelUpdateInBackground | Holen Sie sich das lokale Modell vom Gerät und beginnen Sie mit der Aktualisierung des Modells im Hintergrund. Wenn kein lokales Modell verfügbar ist, verhält sich dies wie latestModel . |
latestModel | Holen Sie sich das neueste Modell. Wenn das lokale Modell die neueste Version ist, wird das lokale Modell zurückgegeben. Andernfalls laden Sie das neueste Modell herunter. Dieses Verhalten wird blockiert, bis die neueste Version heruntergeladen wird (nicht empfohlen). Verwenden Sie dieses Verhalten nur in Fällen, in denen Sie ausdrücklich die neueste Version benötigen. |
Sie sollten modellbezogene Funktionen deaktivieren – zum Beispiel einen Teil Ihrer Benutzeroberfläche ausgrauen oder ausblenden –, bis Sie bestätigen, dass das Modell heruntergeladen wurde.
Schnell
let conditions = ModelDownloadConditions(allowsCellularAccess: false)
ModelDownloader.modelDownloader()
.getModel(name: "your_model",
downloadType: .localModelUpdateInBackground,
conditions: conditions) { result in
switch (result) {
case .success(let customModel):
do {
// 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.
let interpreter = try Interpreter(modelPath: customModel.path)
} catch {
// Error. Bad model file?
}
case .failure(let error):
// Download was unsuccessful. Don't enable ML features.
print(error)
}
}
Viele Apps starten die Download-Aufgabe in ihrem Initialisierungscode, Sie können dies jedoch jederzeit tun, bevor Sie das Modell verwenden müssen.
3. Führen Sie eine Inferenz auf Eingabedaten durch
Rufen Sie die Eingabe- und Ausgabeformen Ihres Modells ab
Der TensorFlow Lite-Modellinterpreter verwendet als Eingabe ein oder mehrere mehrdimensionale Arrays und erzeugt als Ausgabe. 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 Abmessungen („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 Eingabe 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 Interpreter aus
Nachdem Sie das Format der Eingabe und Ausgabe Ihres Modells bestimmt haben, rufen Sie Ihre Eingabedaten ab und führen Sie alle erforderlichen Transformationen an den Daten durch, um eine Eingabe mit der richtigen Form für Ihr Modell zu erhalten. Wenn Ihr Modell beispielsweise Bilder verarbeitet und Eingabeabmessungen von [1, 224, 224, 3]
Gleitkommawerten hat, müssen Sie möglicherweise die Farbwerte des Bildes wie im folgenden Beispiel auf einen Gleitkommabereich skalieren :
Schnell
let image: CGImage = // Your input image
guard let context = CGContext(
data: nil,
width: image.width, height: image.height,
bitsPerComponent: 8, bytesPerRow: image.width * 4,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
) else {
return false
}
context.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height))
guard let imageData = context.data else { return false }
var inputData = Data()
for row in 0 ..< 224 {
for col in 0 ..< 224 {
let offset = 4 * (row * context.width + col)
// (Ignore offset 0, the unused alpha channel)
let red = imageData.load(fromByteOffset: offset+1, as: UInt8.self)
let green = imageData.load(fromByteOffset: offset+2, as: UInt8.self)
let blue = imageData.load(fromByteOffset: offset+3, as: UInt8.self)
// Normalize channel values to [0.0, 1.0]. This requirement varies
// by model. For example, some models might require values to be
// normalized to the range [-1.0, 1.0] instead, and others might
// require fixed-point values or the original bytes.
var normalizedRed = Float32(red) / 255.0
var normalizedGreen = Float32(green) / 255.0
var normalizedBlue = Float32(blue) / 255.0
// Append normalized values to Data object in RGB order.
let elementSize = MemoryLayout.size(ofValue: normalizedRed)
var bytes = [UInt8](repeating: 0, count: elementSize)
memcpy(&bytes, &normalizedRed, elementSize)
inputData.append(&bytes, count: elementSize)
memcpy(&bytes, &normalizedGreen, elementSize)
inputData.append(&bytes, count: elementSize)
memcpy(&ammp;bytes, &normalizedBlue, elementSize)
inputData.append(&bytes, count: elementSize)
}
}
Kopieren Sie dann Ihre Eingabe NSData
in den Interpreter und führen Sie ihn aus:
Schnell
try interpreter.allocateTensors()
try interpreter.copy(inputData, toInputAt: 0)
try interpreter.invoke()
Sie können die Ausgabe des Modells erhalten, indem Sie die Methode output(at:)
des Interpreters aufrufen. 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 Beschriftungen zuordnen, die sie darstellen:
Schnell
let output = try interpreter.output(at: 0)
let probabilities =
UnsafeMutableBufferPointer<Float32>.allocate(capacity: 1000)
output.data.copyBytes(to: probabilities)
guard let labelPath = Bundle.main.path(forResource: "retrained_labels", ofType: "txt") else { return }
let fileContents = try? String(contentsOfFile: labelPath)
guard let labels = fileContents?.components(separatedBy: "\n") else { return }
for i in labels.indices {
print("\(labels[i]): \(probabilities[i])")
}
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 das, dass jeder Ihr Modell kopieren kann. In der Praxis sind die meisten Modelle jedoch so anwendungsspezifisch und durch Optimierungen verschleiert, dass das Risiko mit dem der Konkurrenz vergleichbar ist, die Ihren Code zerlegt und wiederverwendet. Dennoch sollten Sie sich dieses Risikos bewusst sein, bevor Sie ein benutzerdefiniertes Modell in Ihrer App verwenden.