Fügen Sie Firebase zu Ihrer TFLite-basierten iOS-App hinzu

1. Übersicht

Ziele

Mit Firebase ML können Sie Ihr Modell drahtlos bereitstellen. Dadurch können Sie die App-Größe klein halten und das ML-Modell nur bei Bedarf herunterladen, mit mehreren Modellen experimentieren oder Ihr ML-Modell aktualisieren, ohne die gesamte App erneut veröffentlichen zu müssen.

In diesem Codelab konvertieren Sie eine iOS-App, die ein statisches TFLite-Modell verwendet, in eine App, die ein dynamisch von Firebase bereitgestelltes Modell verwendet. Du wirst lernen wie:

  1. Stellen Sie TFLite-Modelle in Firebase ML bereit und greifen Sie über Ihre App darauf zu
  2. Protokollieren Sie modellbezogene Metriken mit Analytics
  3. Wählen Sie aus, welches Modell über Remote Config geladen wird
  4. A/B-Test verschiedener Modelle

Voraussetzungen

Bevor Sie mit diesem Codelab beginnen, stellen Sie sicher, dass Sie Folgendes installiert haben:

  • Xcode 11 (oder höher)
  • CocoaPods 1.9.1 (oder höher)

2. Erstellen Sie ein Firebase-Konsolenprojekt

Fügen Sie Firebase zum Projekt hinzu

  1. Gehen Sie zur Firebase-Konsole .
  2. Wählen Sie „Neues Projekt erstellen“ und nennen Sie Ihr Projekt „Firebase ML iOS Codelab“.

3. Holen Sie sich das Beispielprojekt

Laden Sie den Code herunter

Klonen Sie zunächst das Beispielprojekt und führen Sie pod update im Projektverzeichnis aus:

git clone https://github.com/FirebaseExtended/codelab-digitclassifier-ios.git
cd codelab-digitclassifier-ios
pod install --repo-update

Wenn Sie Git nicht installiert haben, können Sie das Beispielprojekt auch von der GitHub-Seite herunterladen oder auf diesen Link klicken. Nachdem Sie das Projekt heruntergeladen haben, führen Sie es in Xcode aus und experimentieren Sie mit dem Ziffernklassifizierer, um ein Gefühl dafür zu bekommen, wie es funktioniert.

Richten Sie Firebase ein

Befolgen Sie die Dokumentation , um ein neues Firebase-Projekt zu erstellen. Sobald Sie Ihr Projekt erhalten haben, laden Sie die Datei GoogleService-Info.plist Ihres Projekts von der Firebase-Konsole herunter und ziehen Sie sie in das Stammverzeichnis des Xcode-Projekts.

f06cb08d48de7e10.png

Fügen Sie Firebase zu Ihrer Pod-Datei hinzu und führen Sie die Pod-Installation aus.

pod 'FirebaseMLModelDownloader', '9.3.0-beta'

Importieren Sie Firebase in der didFinishLaunchingWithOptions -Methode Ihrer AppDelegate am Anfang der Datei

import FirebaseCore

Und fügen Sie einen Aufruf hinzu, um Firebase zu konfigurieren.

FirebaseApp.configure()

Führen Sie das Projekt erneut aus, um sicherzustellen, dass die App richtig konfiguriert ist und beim Start nicht abstürzt.

4. Stellen Sie ein Modell für Firebase ML bereit

Die Bereitstellung eines Modells in Firebase ML ist aus zwei Hauptgründen nützlich:

  1. Wir können die Installationsgröße der App klein halten und das Modell nur bei Bedarf herunterladen
  2. Das Modell kann regelmäßig und mit einem anderen Release-Zyklus als die gesamte App aktualisiert werden

Bevor wir das statische Modell in unserer App durch ein dynamisch heruntergeladenes Modell von Firebase ersetzen können, müssen wir es in Firebase ML bereitstellen. Das Modell kann entweder über die Konsole oder programmgesteuert mit dem Firebase Admin SDK bereitgestellt werden. In diesem Schritt führen wir die Bereitstellung über die Konsole durch.

Der Einfachheit halber verwenden wir das TensorFlow Lite-Modell, das bereits in unserer App enthalten ist. Öffnen Sie zunächst Firebase und klicken Sie im linken Navigationsbereich auf Machine Learning. Navigieren Sie dann zu „Benutzerdefiniert“ und klicken Sie auf die Schaltfläche „Modell hinzufügen“.

Wenn Sie dazu aufgefordert werden, geben Sie dem Modell einen beschreibenden Namen wie mnist_v1 und laden Sie die Datei aus dem Codelab-Projektverzeichnis hoch.

3c3c50e6ef12b3b.png

5. Laden Sie das Modell von Firebase ML herunter

Die Entscheidung, wann das Remote-Modell von Firebase in Ihre App heruntergeladen werden soll, kann schwierig sein, da TFLite-Modelle relativ groß werden können. Idealerweise möchten wir vermeiden, das Modell sofort beim Start der App zu laden, denn wenn unser Modell nur für eine Funktion verwendet wird und der Benutzer diese Funktion nie verwendet, haben wir ohne Grund eine erhebliche Datenmenge heruntergeladen. Wir können auch Download-Optionen festlegen, z. B. dass Modelle nur dann abgerufen werden, wenn eine WLAN-Verbindung besteht. Wenn Sie sicherstellen möchten, dass das Modell auch ohne Netzwerkverbindung verfügbar ist, sollten Sie das Modell auch als Backup in der App bündeln.

Der Einfachheit halber entfernen wir das standardmäßig gebündelte Modell und laden beim Start der App immer ein Modell von Firebase herunter. Auf diese Weise können Sie bei der Ausführung der Ziffernerkennung sicher sein, dass die Inferenz mit dem von Firebase bereitgestellten Modell ausgeführt wird.

Importieren Sie oben in ModelLoader.swift das Firebase-Modul.

import FirebaseCore
import FirebaseMLModelDownloader

Implementieren Sie dann die folgende Methode.

static func downloadModel(named name: String,
                          completion: @escaping (CustomModel?, DownloadError?) -> Void) {
  guard FirebaseApp.app() != nil else {
    completion(nil, .firebaseNotInitialized)
    return
  }
  guard success == nil && failure == nil else {
    completion(nil, .downloadInProgress)
    return
  }
  let conditions = ModelDownloadConditions(allowsCellularAccess: false)
  ModelDownloader.modelDownloader().getModel(name: name, downloadType: .localModelUpdateInBackground, conditions: conditions) { result in
          switch (result) {
          case .success(let customModel):
                  // Download complete.
                  // The CustomModel object contains the local path of the model file,
                  // which you can use to instantiate a TensorFlow Lite classifier.
                  return completion(customModel, nil)
          case .failure(let error):
              // Download was unsuccessful. Notify error message.
            completion(nil, .downloadFailed(underlyingError: error))
          }
  }
}

Ersetzen Sie in viewDidLoad von ViewController.swift den DigitClassifier-Initialisierungsaufruf durch unsere neue Modell-Download-Methode.

    // Download the model from Firebase
    print("Fetching model...")
    ModelLoader.downloadModel(named: "mnist_v1") { (customModel, error) in
      guard let customModel = customModel else {
        if let error = error {
          print(error)
        }
        return
      }

      print("Model download complete")
      
      // Initialize a DigitClassifier instance
      DigitClassifier.newInstance(modelPath: customModel.path) { result in
      switch result {
        case let .success(classifier):
          self.classifier = classifier
        case .error(_):
          self.resultLabel.text = "Failed to initialize."
        }
      }
    }

Führen Sie Ihre App erneut aus. Nach einigen Sekunden sollte in Xcode ein Protokoll angezeigt werden, das anzeigt, dass das Remote-Modell erfolgreich heruntergeladen wurde. Versuchen Sie, eine Ziffer zu zeichnen und stellen Sie sicher, dass sich das Verhalten der App nicht geändert hat.

6. Verfolgen Sie Benutzerfeedback und Konvertierung, um die Modellgenauigkeit zu messen

Wir werden die Genauigkeit des Modells messen, indem wir das Benutzerfeedback zu Modellvorhersagen verfolgen. Wenn ein Benutzer auf „Ja“ klickt, bedeutet dies, dass die Vorhersage korrekt war.

Wir können ein Analytics-Ereignis protokollieren, um die Genauigkeit unseres Modells zu verfolgen. Zuerst müssen wir Analytics zum Podfile hinzufügen, bevor es im Projekt verwendet werden kann:

pod 'FirebaseAnalytics'

Importieren Sie dann in ViewController.swift Firebase oben in der Datei

import FirebaseAnalytics

Und fügen Sie die folgende Codezeile in der Methode correctButtonPressed hinzu.

Analytics.logEvent("correct_inference", parameters: nil)

Führen Sie die App erneut aus und zeichnen Sie eine Ziffer. Drücken Sie mehrmals die Schaltfläche „Ja“, um eine Rückmeldung zu senden, dass die Schlussfolgerung korrekt war.

Debug-Analysen

Im Allgemeinen werden von Ihrer App protokollierte Ereignisse über einen Zeitraum von etwa einer Stunde gebündelt und zusammen hochgeladen. Dieser Ansatz schont den Akku der Endbenutzergeräte und reduziert die Netzwerkdatennutzung. Zum Zwecke der Validierung Ihrer Analyseimplementierung (und um Ihre Analysen im DebugView-Bericht anzuzeigen) können Sie jedoch den Debug-Modus auf Ihrem Entwicklungsgerät aktivieren, um Ereignisse mit minimaler Verzögerung hochzuladen.

Um den Analytics-Debug-Modus auf Ihrem Entwicklungsgerät zu aktivieren, geben Sie das folgende Befehlszeilenargument in Xcode an:

-FIRDebugEnabled

Führen Sie die App erneut aus und zeichnen Sie eine Ziffer. Drücken Sie mehrmals die Schaltfläche „Ja“, um eine Rückmeldung zu senden, dass die Schlussfolgerung korrekt war. Jetzt können Sie die Protokollereignisse nahezu in Echtzeit über die Debug-Ansicht in der Firebase-Konsole anzeigen. Klicken Sie in der linken Navigationsleiste auf Analytics > DebugView.

5276199a086721fd.png

7. Verfolgen Sie die Inferenzzeit mit Firebase Performance

Beim Testen Ihres Modells reichen die auf Entwicklungsgeräten erstellten Leistungsmetriken nicht aus, um zu erfassen, wie sich das Modell in den Händen Ihrer Benutzer verhält, da es schwierig ist zu sagen, auf welcher Hardware Benutzer Ihre App ausführen werden. Glücklicherweise können Sie die Leistung Ihres Modells auf den Geräten der Benutzer mit Firebase Performance messen, um ein besseres Bild von der Leistung Ihres Modells zu erhalten.

Um die Zeit zu messen, die zum Ausführen der Inferenz benötigt wird, importieren Sie zunächst Firebase in DigitClassifier.swift:

import FirebasePerformance

Starten Sie dann eine Leistungsverfolgung in der Klassifizierungsmethode und stoppen Sie die Verfolgung, wenn die Inferenz abgeschlossen ist. Stellen Sie sicher, dass Sie die folgenden Codezeilen innerhalb des DispatchQueue.global.async-Abschlusses und nicht direkt unter der Methodendeklaration hinzufügen.

let inferenceTrace = Performance.startTrace(name: "tflite inference")
defer {
  inferenceTrace?.stop()
}

Wenn Sie neugierig sind, können Sie die Debug-Protokollierung über die Anweisungen hier aktivieren, um zu bestätigen, dass Ihre Leistungsspuren protokolliert werden. Nach einer Weile werden die Leistungsspuren auch in der Firebase Console sichtbar sein.

8. Stellen Sie ein zweites Modell für Firebase ML bereit

Wenn wir eine neue Version Ihres Modells entwickeln, beispielsweise eine mit einer besseren Modellarchitektur oder eine, die auf einem größeren oder aktualisierten Datensatz trainiert wurde, könnten wir versucht sein, unser aktuelles Modell durch die neue Version zu ersetzen. Allerdings schneidet ein Modell, das beim Testen gut abschneidet, nicht zwangsläufig auch in der Produktion gleich gut ab. Führen wir daher A/B-Tests in der Produktion durch, um unser ursprüngliches Modell mit dem neuen zu vergleichen.

Aktivieren Sie die Firebase Model Management API

In diesem Schritt aktivieren wir die Firebase Model Management API, um eine neue Version unseres TensorFlow Lite-Modells mithilfe von Python-Code bereitzustellen.

Erstellen Sie einen Bucket zum Speichern Ihrer ML-Modelle

Gehen Sie in Ihrer Firebase-Konsole zu „Speicher“ und klicken Sie auf „Erste Schritte“. fbbea78f0eb3dc9f.png

Folgen Sie dem Dialog, um Ihren Eimer einzurichten.

19517c0d6d2aa14d.png

Aktivieren Sie die Firebase ML-API

Gehen Sie zur Seite „Firebase ML API“ in der Google Cloud Console und klicken Sie auf „Aktivieren“.

2414fd5cced6c984.png Wählen Sie die Digit Classifier-App aus, wenn Sie dazu aufgefordert werden.

Jetzt trainieren wir eine neue Version des Modells mithilfe eines größeren Datensatzes und stellen sie dann mithilfe des Firebase Admin SDK programmgesteuert direkt aus dem Trainingsnotizbuch bereit.

Laden Sie den privaten Schlüssel für das Dienstkonto herunter

Bevor wir das Firebase Admin SDK verwenden können, müssen wir ein Dienstkonto erstellen. Öffnen Sie den Bereich „Dienstkonten“ der Firebase-Konsole, indem Sie auf diesen Link klicken und auf die Schaltfläche klicken, um ein neues Dienstkonto für das Firebase Admin SDK zu erstellen. Wenn Sie dazu aufgefordert werden, klicken Sie auf die Schaltfläche „Neuen privaten Schlüssel generieren“. Wir verwenden den Dienstkontoschlüssel zur Authentifizierung unserer Anfragen aus dem Colab-Notizbuch.

c3b95de1e5508516.png

Jetzt können wir das neue Modell trainieren und bereitstellen.

  1. Öffnen Sie dieses Colab-Notizbuch und erstellen Sie eine Kopie davon in Ihrem eigenen Laufwerk.
  2. Führen Sie die erste Zelle „Trainieren Sie ein verbessertes TensorFlow Lite-Modell“ aus, indem Sie links daneben auf die Wiedergabeschaltfläche klicken. Dies trainiert ein neues Modell und kann einige Zeit dauern.
  3. Wenn Sie die zweite Zelle ausführen, wird eine Aufforderung zum Hochladen einer Datei erstellt. Laden Sie die JSON-Datei hoch, die Sie beim Erstellen Ihres Dienstkontos von der Firebase Console heruntergeladen haben.

71e847c6a85423b3.png

  1. Führen Sie die letzten beiden Zellen aus.

Nachdem Sie das Colab-Notebook ausgeführt haben, sollten Sie in der Firebase-Konsole ein zweites Modell sehen. Stellen Sie sicher, dass das zweite Modell den Namen mnist_v2 trägt.

c316683bb4d75d57.png

9. Wählen Sie über Remote Config ein Modell aus

Da wir nun über zwei separate Modelle verfügen, fügen wir einen Parameter hinzu, um auszuwählen, welches Modell zur Laufzeit heruntergeladen werden soll. Der Wert des Parameters, den der Client empfängt, bestimmt, welches Modell der Client herunterlädt. Öffnen Sie zunächst die Firebase-Konsole und klicken Sie im linken Navigationsmenü auf die Schaltfläche „Remote-Konfiguration“. Klicken Sie dann auf die Schaltfläche „Parameter hinzufügen“.

Benennen Sie den neuen Parameter model_name und geben Sie ihm den Standardwert mnist_v1 . Klicken Sie auf Änderungen veröffentlichen , um die Aktualisierungen anzuwenden. Indem wir den Namen des Modells in den Remote-Konfigurationsparameter einfügen, können wir mehrere Modelle testen, ohne für jedes Modell, das wir testen möchten, einen neuen Parameter hinzuzufügen.

Nachdem Sie den Parameter hinzugefügt haben, sollten Sie ihn in der Konsole sehen:

699b3fd32acce887.png

In unserem Code müssen wir beim Laden des Remote-Modells eine Prüfung hinzufügen. Wenn wir den Parameter von Remote Config erhalten, rufen wir das Remote-Modell mit dem entsprechenden Namen ab; Andernfalls versuchen wir, mnist_v1 zu laden. Bevor wir Remote Config verwenden können, müssen wir es zu unserem Projekt hinzufügen, indem wir es als Abhängigkeit im Podfile angeben:

pod 'FirebaseRemoteConfig'

Führen Sie pod install aus und öffnen Sie das Xcode-Projekt erneut. Implementieren Sie in ModelLoader.swift die Methode fetchParameterizedModel .

static func fetchParameterizedModel(completion: @escaping (CustomModel?, DownloadError?) -> Void) {
  RemoteConfig.remoteConfig().fetchAndActivate { (status, error) in
    DispatchQueue.main.async {
      if let error = error {
        let compositeError = DownloadError.downloadFailed(underlyingError: error)
        completion(nil, compositeError)
        return
      }

      let modelName: String
      if let name = RemoteConfig.remoteConfig().configValue(forKey: "model_name").stringValue {
        modelName = name
      } else {
        let defaultName = "mnist_v1"
        print("Unable to fetch model name from config, falling back to default \(defaultName)")
        modelName = defaultName
      }
      downloadModel(named: modelName, completion: completion)
    }
  }
}

Ersetzen Sie schließlich in ViewController.swift den downloadModel Aufruf durch die neue Methode, die wir gerade implementiert haben.

// Download the model from Firebase
print("Fetching model...")
ModelLoader.fetchParameterizedModel { (customModel, error) in
  guard let customModel = customModel else {
    if let error = error {
      print(error)
    }
    return
  }

  print("Model download complete")
  
  // Initialize a DigitClassifier instance
  DigitClassifier.newInstance(modelPath: customModel.path) { result in
  switch result {
    case let .success(classifier):
      self.classifier = classifier
    case .error(_):
      self.resultLabel.text = "Failed to initialize."
    }
  }
}

Führen Sie die App erneut aus und stellen Sie sicher, dass das Modell weiterhin korrekt geladen wird.

10. A/B-Test der beiden Modelle

Schließlich können wir das integrierte A/B-Testverhalten von Firebase nutzen, um zu sehen, welches unserer beiden Modelle besser abschneidet. Gehen Sie in der Firebase-Konsole zu Analytics -> Ereignisse. Wenn das Ereignis correct_inference angezeigt wird, markieren Sie es als „Conversion-Ereignis“. Wenn nicht, können Sie zu Analytics -> Conversion-Ereignisse gehen, auf „Neues Conversion-Ereignis erstellen“ klicken und correct_inference.

Gehen Sie nun zu „Remote Config“ in der Firebase-Konsole und wählen Sie die Schaltfläche „A/B-Test“ aus dem Menü „Weitere Optionen“ für den Parameter „model_name“, den wir gerade hinzugefügt haben.

fad5ea36969d2aeb.png

Übernehmen Sie im folgenden Menü den Standardnamen.

d7c006669ace6e40.png

Wählen Sie im Dropdown-Menü Ihre App aus und ändern Sie die Targeting-Kriterien auf 50 % der aktiven Benutzer.

6246dd7c660b53fb.png

Wenn Sie das Ereignis correct_inference zuvor als Conversion festlegen konnten, verwenden Sie dieses Ereignis als primäre Metrik zum Verfolgen. Wenn Sie nicht warten möchten, bis das Ereignis in Analytics angezeigt wird, können Sie correct_inference auch manuell hinzufügen.

1ac9c94fb3159271.png

Stellen Sie schließlich auf dem Bildschirm „Varianten“ Ihre Kontrollgruppenvariante auf die Verwendung mnist_v1 und Ihre Variante-A-Gruppe auf die Verwendung von mnist_v2 ein.

e4510434f8da31b6.png

Klicken Sie unten rechts auf die Schaltfläche „Überprüfen“.

Herzlichen Glückwunsch, Sie haben erfolgreich einen A/B-Test für Ihre beiden separaten Modelle erstellt! Der A/B-Test befindet sich derzeit im Entwurfsstadium und kann jederzeit durch Klicken auf die Schaltfläche „Experiment starten“ gestartet werden.

Weitere Informationen zu A/B-Tests finden Sie in der Dokumentation zu A/B-Tests .

11. Fazit

In diesem Codelab haben Sie gelernt, wie Sie ein statisch gebündeltes TFLite-Asset in Ihrer App durch ein dynamisch geladenes TFLite-Modell von Firebase ersetzen. Um mehr über TFLite und Firebase zu erfahren, werfen Sie einen Blick auf andere TFLite-Beispiele und die Firebase-Einführungsleitfäden.

Eine Frage haben?

Probleme melden