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:
- Stellen Sie TFLite-Modelle in Firebase ML bereit und greifen Sie über Ihre App darauf zu
- Protokollieren Sie modellbezogene Metriken mit Analytics
- Wählen Sie aus, welches Modell über Remote Config geladen wird
- 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
- Gehen Sie zur Firebase-Konsole .
- 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.
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:
- Wir können die Installationsgröße der App klein halten und das Modell nur bei Bedarf herunterladen
- 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.
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.
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“.
Folgen Sie dem Dialog, um Ihren Eimer einzurichten.
Aktivieren Sie die Firebase ML-API
Gehen Sie zur Seite „Firebase ML API“ in der Google Cloud Console und klicken Sie auf „Aktivieren“.
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.
Jetzt können wir das neue Modell trainieren und bereitstellen.
- Öffnen Sie dieses Colab-Notizbuch und erstellen Sie eine Kopie davon in Ihrem eigenen Laufwerk.
- 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.
- 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.
- 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.
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:
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.
Übernehmen Sie im folgenden Menü den Standardnamen.
Wählen Sie im Dropdown-Menü Ihre App aus und ändern Sie die Targeting-Kriterien auf 50 % der aktiven Benutzer.
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.
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.
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.
- Dokumentation zu Firebase Machine Learning
- TensorFlow Lite-Dokumentation
- A/B-Testmodelle mit Firebase