Ajoutez Firebase à votre application iOS basée sur TFLite

1. Vue d'ensemble

Objectifs

Firebase ML vous permet de déployer votre modèle en direct. Cela vous permet de conserver une petite taille d'application et de télécharger le modèle ML uniquement lorsque cela est nécessaire, d'expérimenter plusieurs modèles ou de mettre à jour votre modèle ML sans avoir à republier l'intégralité de l'application.

Dans cet atelier de programmation, vous allez convertir une application iOS utilisant un modèle TFLite statique en une application utilisant un modèle servi dynamiquement depuis Firebase. Vous apprendrez à :

  1. Déployez des modèles TFLite sur Firebase ML et accédez-y depuis votre application
  2. Consigner les métriques liées au modèle avec Analytics
  3. Sélectionnez quel modèle est chargé via Remote Config
  4. Testez A/B différents modèles

Conditions préalables

Avant de commencer cet atelier de programmation, assurez-vous d'avoir installé :

  • Xcode 11 (ou supérieur)
  • CocoaPods 1.9.1 (ou supérieur)

2. Créer un projet de console Firebase

Ajouter Firebase au projet

  1. Accédez à la console Firebase .
  2. Sélectionnez Créer un nouveau projet et nommez votre projet « Firebase ML iOS Codelab ».

3. Obtenez l'exemple de projet

Téléchargez le code

Commencez par cloner l'exemple de projet et exécutez pod update dans le répertoire du projet :

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

Si git n'est pas installé, vous pouvez également télécharger l'exemple de projet depuis sa page GitHub ou en cliquant sur ce lien . Une fois que vous avez téléchargé le projet, exécutez-le dans Xcode et jouez avec le classificateur de chiffres pour avoir une idée de son fonctionnement.

Configurer Firebase

Suivez la documentation pour créer un nouveau projet Firebase. Une fois que vous avez votre projet, téléchargez le fichier GoogleService-Info.plist de votre projet depuis la console Firebase et faites-le glisser vers la racine du projet Xcode.

f06cb08d48de7e10.png

Ajoutez Firebase à votre Podfile et exécutez l'installation du pod.

pod 'FirebaseMLModelDownloader', '9.3.0-beta'

Dans la méthode didFinishLaunchingWithOptions de votre AppDelegate , importez Firebase en haut du fichier

import FirebaseCore

Et ajoutez un appel pour configurer Firebase.

FirebaseApp.configure()

Exécutez à nouveau le projet pour vous assurer que l'application est correctement configurée et ne plante pas au lancement.

4. Déployer un modèle sur Firebase ML

Le déploiement d'un modèle sur Firebase ML est utile pour deux raisons principales :

  1. Nous pouvons garder la taille d'installation de l'application petite et télécharger le modèle uniquement si nécessaire
  2. Le modèle peut être mis à jour régulièrement et avec un cycle de publication différent de celui de l'ensemble de l'application

Avant de pouvoir remplacer le modèle statique de notre application par un modèle téléchargé dynamiquement depuis Firebase, nous devons le déployer sur Firebase ML. Le modèle peut être déployé via la console ou par programme, à l'aide du SDK d'administration Firebase. Dans cette étape, nous allons déployer via la console.

Pour simplifier les choses, nous utiliserons le modèle TensorFlow Lite déjà présent dans notre application. Tout d’abord, ouvrez Firebase et cliquez sur Machine Learning dans le panneau de navigation de gauche. Accédez ensuite à « Personnalisé » et cliquez sur le bouton « Ajouter un modèle ».

Lorsque vous y êtes invité, attribuez au modèle un nom descriptif tel que mnist_v1 et importez le fichier à partir du répertoire du projet de l'atelier de programmation.

3c3c50e6ef12b3b.png

5. Téléchargez le modèle depuis Firebase ML

Choisir quand télécharger le modèle distant de Firebase dans votre application peut être délicat car les modèles TFLite peuvent devenir relativement volumineux. Idéalement, nous voulons éviter de charger le modèle immédiatement au lancement de l'application, car si notre modèle est utilisé pour une seule fonctionnalité et que l'utilisateur n'utilise jamais cette fonctionnalité, nous aurons téléchargé une quantité importante de données sans raison. Nous pouvons également définir des options de téléchargement telles que la récupération des modèles uniquement lorsque vous êtes connecté au wifi. Si vous souhaitez vous assurer que le modèle est disponible même sans connexion réseau, vous devez également regrouper le modèle dans l'application en tant que sauvegarde.

Par souci de simplicité, nous supprimerons le modèle fourni par défaut et téléchargerons toujours un modèle depuis Firebase au démarrage de l'application. De cette façon, lors de l'exécution de la reconnaissance numérique, vous pouvez être sûr que l'inférence s'exécute avec le modèle fourni par Firebase.

En haut de ModelLoader.swift , importez le module Firebase.

import FirebaseCore
import FirebaseMLModelDownloader

Implémentez ensuite la méthode suivante.

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))
          }
  }
}

Dans ViewController.swift 's viewDidLoad , remplacez l'appel d'initialisation DigitClassifier par notre nouvelle méthode de téléchargement de modèle.

    // 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."
        }
      }
    }

Réexécutez votre application. Après quelques secondes, vous devriez voir un journal dans Xcode indiquant que le modèle distant a été téléchargé avec succès. Essayez de dessiner un chiffre et confirmez que le comportement de l'application n'a pas changé.

6. Suivez les commentaires des utilisateurs et la conversion pour mesurer la précision du modèle

Nous mesurerons la précision du modèle en suivant les commentaires des utilisateurs sur les prédictions du modèle. Si un utilisateur clique sur « oui », cela indiquera que la prédiction était exacte.

Nous pouvons enregistrer un événement Analytics pour suivre l'exactitude de notre modèle. Tout d'abord, nous devons ajouter Analytics au Podfile avant qu'il puisse être utilisé dans le projet :

pod 'FirebaseAnalytics'

Puis dans ViewController.swift importez Firebase en haut du fichier

import FirebaseAnalytics

Et ajoutez la ligne de code suivante dans la méthode correctButtonPressed .

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

Exécutez à nouveau l'application et dessinez un chiffre. Appuyez plusieurs fois sur le bouton « Oui » pour envoyer un retour indiquant que l'inférence était exacte.

Analyses de débogage

Généralement, les événements enregistrés par votre application sont regroupés sur une période d'environ une heure et téléchargés ensemble. Cette approche préserve la batterie des appareils des utilisateurs finaux et réduit l'utilisation des données du réseau. Cependant, dans le but de valider la mise en œuvre de votre analyse (et afin d'afficher vos analyses dans le rapport DebugView), vous pouvez activer le mode Débogage sur votre appareil de développement pour télécharger les événements dans un délai minimal.

Pour activer le mode Analytics Debug sur votre appareil de développement, spécifiez l'argument de ligne de commande suivant dans Xcode :

-FIRDebugEnabled

Exécutez à nouveau l'application et dessinez un chiffre. Appuyez plusieurs fois sur le bouton « Oui » pour envoyer un retour indiquant que l'inférence était exacte. Vous pouvez désormais afficher les événements du journal en temps quasi réel via la vue de débogage de la console Firebase. Cliquez sur Analytics > DebugView dans la barre de navigation de gauche.

5276199a086721fd.png

7. Suivez le temps d'inférence avec Firebase Performance

Lorsque vous testez votre modèle, les mesures de performances effectuées sur les appareils de développement ne suffisent pas à capturer les performances du modèle entre les mains de vos utilisateurs, car il est difficile de savoir sur quel matériel les utilisateurs exécuteront votre application. Heureusement, vous pouvez mesurer les performances de votre modèle sur les appareils des utilisateurs avec Firebase Performance pour avoir une meilleure idée des performances de votre modèle.

Pour mesurer le temps nécessaire à l'exécution de l'inférence, importez d'abord Firebase dans DigitClassifier.swift :

import FirebasePerformance

Démarrez ensuite une trace de performances dans la méthode classify et arrêtez la trace une fois l'inférence terminée. Assurez-vous d'ajouter les lignes de code suivantes à l'intérieur de la fermeture DispatchQueue.global.async et non directement sous la déclaration de méthode.

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

Si vous êtes curieux, vous pouvez activer la journalisation du débogage via les instructions ici pour confirmer que vos traces de performances sont enregistrées. Après un certain temps, les traces de performances seront également visibles dans la console Firebase.

8. Déployez un deuxième modèle sur Firebase ML

Lorsque nous proposons une nouvelle version de votre modèle, par exemple une version avec une meilleure architecture de modèle ou une version formée sur un ensemble de données plus grand ou mis à jour, nous pouvons être tentés de remplacer notre modèle actuel par la nouvelle version. Cependant, un modèle performant lors des tests ne fonctionne pas nécessairement aussi bien en production. Faisons donc des tests A/B en production pour comparer notre modèle d'origine et le nouveau.

Activer l'API de gestion des modèles Firebase

Dans cette étape, nous allons permettre à l'API Firebase Model Management de déployer une nouvelle version de notre modèle TensorFlow Lite à l'aide du code Python.

Créez un bucket pour stocker vos modèles ML

Dans votre console Firebase, accédez à Stockage et cliquez sur Commencer. fbbea78f0eb3dc9f.png

Suivez la boîte de dialogue pour configurer votre bucket.

19517c0d6d2aa14d.png

Activer l'API Firebase ML

Accédez à la page API Firebase ML sur Google Cloud Console et cliquez sur Activer.

2414fd5cced6c984.png Sélectionnez l'application Digit Classifier lorsque vous y êtes invité.

Nous allons maintenant former une nouvelle version du modèle en utilisant un ensemble de données plus grand, puis nous le déploierons par programmation directement à partir du bloc-notes de formation à l'aide du SDK Firebase Admin.

Téléchargez la clé privée du compte de service

Avant de pouvoir utiliser le SDK Firebase Admin, nous devrons créer un compte de service. Ouvrez le panneau Comptes de service de la console Firebase en cliquant sur ce lien et cliquez sur le bouton pour créer un nouveau compte de service pour le SDK d'administration Firebase. Lorsque vous y êtes invité, cliquez sur le bouton Générer une nouvelle clé privée. Nous utiliserons la clé du compte de service pour authentifier nos demandes à partir du notebook Colab.

c3b95de1e5508516.png

Nous pouvons désormais former et déployer le nouveau modèle.

  1. Ouvrez ce notebook Colab et faites-en une copie sous votre propre Drive.
  2. Exécutez la première cellule « Former un modèle TensorFlow Lite amélioré » en cliquant sur le bouton de lecture à gauche de celle-ci. Cela entraînera la formation d'un nouveau modèle et peut prendre un certain temps.
  3. L'exécution de la deuxième cellule créera une invite de téléchargement de fichier. Téléchargez le fichier json que vous avez téléchargé depuis la console Firebase lors de la création de votre compte de service.

71e847c6a85423b3.png

  1. Exécutez les deux dernières cellules.

Après avoir exécuté le notebook Colab, vous devriez voir un deuxième modèle dans la console Firebase. Assurez-vous que le deuxième modèle est nommé mnist_v2 .

c316683bb4d75d57.png

9. Sélectionnez un modèle via Remote Config

Maintenant que nous avons deux modèles distincts, nous allons ajouter un paramètre permettant de sélectionner le modèle à télécharger au moment de l'exécution. La valeur du paramètre que le client reçoit déterminera le modèle que le client téléchargera. Tout d’abord, ouvrez la console Firebase et cliquez sur le bouton Remote Config dans le menu de navigation de gauche. Cliquez ensuite sur le bouton "Ajouter un paramètre".

Nommez le nouveau paramètre model_name et donnez-lui une valeur par défaut de mnist_v1 . Cliquez sur Publier les modifications pour appliquer les mises à jour. En mettant le nom du modèle dans le paramètre de configuration distant, nous pouvons tester plusieurs modèles sans ajouter de nouveau paramètre pour chaque modèle que nous voulons tester.

Après avoir ajouté le paramètre, vous devriez le voir dans la console :

699b3fd32acce887.png

Dans notre code, nous devrons ajouter une vérification lors du chargement du modèle distant. Lorsque nous recevrons le paramètre de Remote Config, nous récupérerons le modèle distant avec le nom correspondant ; sinon nous tenterons de charger mnist_v1 . Avant de pouvoir utiliser Remote Config, nous devons l'ajouter à notre projet en le spécifiant comme dépendance dans le Podfile :

pod 'FirebaseRemoteConfig'

Exécutez l'installation du pod et rouvrez le projet Xcode. Dans ModelLoader.swift , implémentez la méthode 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)
    }
  }
}

Enfin, dans ViewController.swift , remplacez l'appel downloadModel par la nouvelle méthode que nous venons d'implémenter.

// 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."
    }
  }
}

Réexécutez l'application et assurez-vous qu'elle charge toujours correctement le modèle.

10. A/B Testez les deux modèles

Enfin, nous pouvons utiliser le comportement de test A/B intégré de Firebase pour voir lequel de nos deux modèles est le plus performant. Accédez à Analytics -> Événements dans la console Firebase. Si l'événement correct_inference s'affiche, marquez-le comme "Événement de conversion", sinon, vous pouvez accéder à Analytics -> Événements de conversion et cliquer sur "Créer un nouvel événement de conversion" et inscrire correct_inference.

Allez maintenant dans "Remote Config dans la console Firebase, sélectionnez le bouton "A/B test" dans le menu Plus d'options sur le paramètre "model_name" que nous venons d'ajouter.

fad5ea36969d2aeb.png

Dans le menu qui suit, acceptez le nom par défaut.

d7c006669ace6e40.png

Sélectionnez votre application dans la liste déroulante et modifiez les critères de ciblage sur 50 % d'utilisateurs actifs.

6246dd7c660b53fb.png

Si vous avez pu définir l'événement correct_inference comme conversion plus tôt, utilisez cet événement comme métrique principale à suivre. Sinon, si vous ne souhaitez pas attendre que l'événement apparaisse dans Analytics, vous pouvez ajouter correct_inference manuellement.

1ac9c94fb3159271.png

Enfin, sur l'écran Variantes, définissez la variante de votre groupe de contrôle pour utiliser mnist_v1 et votre groupe Variante A pour utiliser mnist_v2 .

e4510434f8da31b6.png

Cliquez sur le bouton Réviser dans le coin inférieur droit.

Félicitations, vous avez réussi à créer un test A/B pour vos deux modèles distincts ! Le test A/B est actuellement à l'état de brouillon et peut être démarré à tout moment en cliquant sur le bouton « Démarrer l'expérience ».

Pour un examen plus approfondi des tests A/B, consultez la documentation sur les tests A/B .

11. Conclusion

Dans cet atelier de programmation, vous avez appris à remplacer un élément tflite regroupé de manière statique dans votre application par un modèle TFLite chargé dynamiquement à partir de Firebase. Pour en savoir plus sur TFLite et Firebase, consultez d'autres exemples TFLite et les guides de démarrage de Firebase.

Avoir une question?

Signaler des problèmes