Agregue Firebase a su aplicación iOS con tecnología TFLite

1. Información general

Objetivos

Firebase ML le permite implementar su modelo de forma inalámbrica. Esto le permite mantener el tamaño de la aplicación pequeño y solo descargar el modelo ML cuando sea necesario, experimentar con varios modelos o actualizar su modelo ML sin tener que volver a publicar la aplicación completa.

En este laboratorio de código, convertirá una aplicación de iOS usando un modelo TFLite estático en una aplicación usando un modelo servido dinámicamente desde Firebase. Aprenderás a:

  1. Implemente modelos TFLite en Firebase ML y acceda a ellos desde su aplicación
  2. Registrar métricas relacionadas con el modelo con Analytics
  3. Seleccione qué modelo se carga a través de Remote Config
  4. Prueba A/B diferentes modelos

requisitos previos

Antes de comenzar este codelab, asegúrese de haber instalado:

  • Xcode 11 (o superior)
  • CocoaPods 1.9.1 (o superior)

2. Crear proyecto de consola de Firebase

Agregar Firebase al proyecto

  1. Ve a la consola de Firebase .
  2. Seleccione Crear nuevo proyecto y nombre su proyecto "Firebase ML iOS Codelab".

3. Obtenga el proyecto de muestra

Descarga el Código

Comience clonando el proyecto de muestra y ejecutando pod update en el directorio del proyecto:

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

Si no tiene git instalado, también puede descargar el proyecto de muestra desde su página de GitHub o haciendo clic en este enlace . Una vez que haya descargado el proyecto, ejecútelo en Xcode y juegue con el clasificador de dígitos para tener una idea de cómo funciona.

Configurar base de fuego

Siga la documentación para crear un nuevo proyecto de Firebase. Una vez que tenga su proyecto, descargue el archivo GoogleService-Info.plist de su proyecto desde la consola Firebase y arrástrelo a la raíz del proyecto Xcode.

f06cb08d48de7e10.png

Agregue Firebase a su Podfile y ejecute pod install.

pod 'FirebaseMLModelDownloader', '9.3.0-beta'

En el método didFinishLaunchingWithOptions de su AppDelegate , importe Firebase en la parte superior del archivo

import FirebaseCore

Y agregue una llamada para configurar Firebase.

FirebaseApp.configure()

Vuelva a ejecutar el proyecto para asegurarse de que la aplicación esté configurada correctamente y no se bloquee al iniciarse.

4. Implementar un modelo en Firebase ML

La implementación de un modelo en Firebase ML es útil por dos razones principales:

  1. Podemos mantener el tamaño de instalación de la aplicación pequeño y solo descargar el modelo si es necesario
  2. El modelo se puede actualizar regularmente y con un ciclo de lanzamiento diferente al de toda la aplicación.

Antes de que podamos reemplazar el modelo estático en nuestra aplicación con un modelo descargado dinámicamente de Firebase, debemos implementarlo en Firebase ML. El modelo se puede implementar a través de la consola o mediante programación, usando el SDK de administración de Firebase. En este paso, implementaremos a través de la consola.

Para simplificar las cosas, usaremos el modelo TensorFlow Lite que ya está en nuestra aplicación. Primero, abra Firebase y haga clic en Machine Learning en el panel de navegación izquierdo. Luego navegue hasta "Personalizado" y haga clic en el botón "Agregar modelo".

Cuando se le solicite, asigne al modelo un nombre descriptivo como mnist_v1 y cargue el archivo desde el directorio del proyecto codelab.

3c3c50e6ef12b3b.png

5. Descargar modelo de Firebase ML

Elegir cuándo descargar el modelo remoto de Firebase a su aplicación puede ser complicado, ya que los modelos TFLite pueden crecer relativamente. Idealmente, queremos evitar cargar el modelo inmediatamente cuando se inicia la aplicación, ya que si nuestro modelo se usa solo para una función y el usuario nunca usa esa función, habremos descargado una cantidad significativa de datos sin ningún motivo. También podemos configurar opciones de descarga, como solo buscar modelos cuando está conectado a wifi. Si desea asegurarse de que el modelo esté disponible incluso sin una conexión de red, también debe agrupar el modelo como parte de la aplicación como respaldo.

En aras de la simplicidad, eliminaremos el modelo incluido predeterminado y siempre descargaremos un modelo de Firebase cuando se inicie la aplicación. De esta manera, al ejecutar el reconocimiento de dígitos, puede estar seguro de que la inferencia se ejecuta con el modelo proporcionado por Firebase.

En la parte superior de ModelLoader.swift , importe el módulo Firebase.

import FirebaseCore
import FirebaseMLModelDownloader

Luego implemente el siguiente método.

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

En viewDidLoad de ViewController.swift , reemplace la llamada de inicialización de DigitClassifier con nuestro nuevo método de descarga de modelo.

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

Vuelva a ejecutar su aplicación. Después de unos segundos, debería ver un inicio de sesión en Xcode que indica que el modelo remoto se ha descargado correctamente. Intente dibujar un dígito y confirme que el comportamiento de la aplicación no ha cambiado.

6. Realice un seguimiento de los comentarios y la conversión de los usuarios para medir la precisión del modelo

Mediremos la precisión del modelo mediante el seguimiento de los comentarios de los usuarios sobre las predicciones del modelo. Si un usuario hace clic en "sí", indicará que la predicción fue precisa.

Podemos registrar un evento de Analytics para rastrear la precisión de nuestro modelo. Primero, debemos agregar Analytics al Podfile antes de que pueda usarse en el proyecto:

pod 'FirebaseAnalytics'

Luego, en ViewController.swift importe Firebase en la parte superior del archivo

import FirebaseAnalytics

Y agregue la siguiente línea de código en el método correctButtonPressed .

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

Vuelva a ejecutar la aplicación y dibuje un dígito. Presione el botón "Sí" un par de veces para enviar comentarios de que la inferencia fue precisa.

Análisis de depuración

Por lo general, los eventos registrados por su aplicación se agrupan durante un período de aproximadamente una hora y se cargan juntos. Este enfoque conserva la batería de los dispositivos de los usuarios finales y reduce el uso de datos de la red. Sin embargo, con el fin de validar su implementación de análisis (y para ver sus análisis en el informe DebugView), puede habilitar el modo de depuración en su dispositivo de desarrollo para cargar eventos con un retraso mínimo.

Para habilitar el modo de depuración de Analytics en su dispositivo de desarrollo, especifique el siguiente argumento de línea de comando en Xcode:

-FIRDebugEnabled

Vuelva a ejecutar la aplicación y dibuje un dígito. Presione el botón "Sí" un par de veces para enviar comentarios de que la inferencia fue precisa. Ahora puede ver los eventos de registro casi en tiempo real a través de la vista de depuración en la consola de Firebase. Haga clic en Analytics > DebugView en la barra de navegación izquierda.

5276199a086721fd.png

7. Realice un seguimiento del tiempo de inferencia con Firebase Performance

Al probar su modelo, las métricas de rendimiento realizadas en los dispositivos de desarrollo no son suficientes para capturar el rendimiento del modelo en las manos de sus usuarios, ya que es difícil saber en qué hardware ejecutarán su aplicación los usuarios. Afortunadamente, puede medir el rendimiento de su modelo en los dispositivos de los usuarios con Firebase Performance para obtener una mejor imagen del rendimiento de su modelo.

Para medir el tiempo que lleva ejecutar la inferencia, primero importa Firebase en DigitClassifier.swift:

import FirebasePerformance

A continuación, inicie un seguimiento del rendimiento en el método classify y deténgalo cuando se complete la inferencia. Asegúrese de agregar las siguientes líneas de código dentro del cierre DispatchQueue.global.async y no directamente debajo de la declaración del método.

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

Si tiene curiosidad, puede habilitar el registro de depuración a través de las instrucciones aquí para confirmar que se están registrando sus seguimientos de rendimiento. Después de un tiempo, los rastros de rendimiento también estarán visibles en Firebase Console.

8. Implementa un segundo modelo en Firebase ML

Cuando creamos una nueva versión de su modelo, como una con una mejor arquitectura de modelo o una entrenada en un conjunto de datos más grande o actualizado, podemos sentirnos tentados a reemplazar nuestro modelo actual con la nueva versión. Sin embargo, un modelo que funciona bien en las pruebas no necesariamente funciona igual de bien en la producción. Por lo tanto, hagamos pruebas A/B en producción para comparar nuestro modelo original y el nuevo.

Habilitar la API de administración de modelos de Firebase

En este paso, habilitaremos la API de administración de modelos de Firebase para implementar una nueva versión de nuestro modelo TensorFlow Lite mediante el código de Python.

Cree un depósito para almacenar sus modelos ML

En su Firebase Console, vaya a Almacenamiento y haga clic en Comenzar. fbbea78f0eb3dc9f.png

Siga el diálogo para configurar su balde.

19517c0d6d2aa14d.png

Habilitar la API de aprendizaje automático de Firebase

Vaya a la página de la API de Firebase ML en Google Cloud Console y haga clic en Habilitar.

2414fd5cced6c984.png Seleccione la aplicación Clasificador de dígitos cuando se le solicite.

Ahora entrenaremos una nueva versión del modelo usando un conjunto de datos más grande y luego lo implementaremos mediante programación directamente desde el cuaderno de entrenamiento usando Firebase Admin SDK.

Descargar la clave privada para la cuenta de servicio

Antes de que podamos usar el SDK de administración de Firebase, debemos crear una cuenta de servicio. Abra el panel Cuentas de servicio de la consola Firebase haciendo clic en este enlace y haga clic en el botón para crear una nueva cuenta de servicio para Firebase Admin SDK. Cuando se le solicite, haga clic en el botón Generar nueva clave privada. Usaremos la clave de la cuenta de servicio para autenticar nuestras solicitudes desde el cuaderno de colab.

c3b95de1e5508516.png

Ahora podemos entrenar e implementar el nuevo modelo.

  1. Abre este cuaderno de colaboración y haz una copia en tu propio Drive.
  2. Ejecute la primera celda "Entrenar un modelo TensorFlow Lite mejorado" haciendo clic en el botón de reproducción a la izquierda. Esto entrenará un nuevo modelo y puede llevar algún tiempo.
  3. Ejecutar la segunda celda creará un mensaje de carga de archivos. Cargue el archivo json que descargó de Firebase Console al crear su cuenta de servicio.

71e847c6a85423b3.png

  1. Ejecute las dos últimas celdas.

Después de ejecutar el cuaderno de colaboración, debería ver un segundo modelo en la consola de Firebase. Asegúrese de que el segundo modelo se llame mnist_v2 .

c316683bb4d75d57.png

9. Seleccione un modelo a través de Remote Config

Ahora que tenemos dos modelos separados, agregaremos un parámetro para seleccionar qué modelo descargar en tiempo de ejecución. El valor del parámetro que recibe el cliente determinará qué modelo descarga el cliente. Primero, abra la consola Firebase y haga clic en el botón Configuración remota en el menú de navegación izquierdo. Luego, haga clic en el botón "Agregar parámetro".

Nombre el nuevo parámetro model_name y asígnele un valor predeterminado de mnist_v1 . Haga clic en Publicar cambios para aplicar las actualizaciones. Al poner el nombre del modelo en el parámetro de configuración remota, podemos probar varios modelos sin agregar un nuevo parámetro para cada modelo que queremos probar.

Después de agregar el parámetro, debería verlo en la consola:

699b3fd32acce887.png

En nuestro código, necesitaremos agregar una marca al cargar el modelo remoto. Cuando recibamos el parámetro de Remote Config, buscaremos el modelo remoto con el nombre correspondiente; de lo contrario, intentaremos cargar mnist_v1 . Antes de que podamos usar Remote Config, debemos agregarlo a nuestro proyecto especificándolo como una dependencia en el Podfile:

pod 'FirebaseRemoteConfig'

Ejecute pod install y vuelva a abrir el proyecto Xcode. En ModelLoader.swift , implemente el método 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)
    }
  }
}

Finalmente, en ViewController.swift , reemplace la llamada downloadModel con el nuevo método que acabamos de implementar.

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

Vuelva a ejecutar la aplicación y asegúrese de que todavía carga el modelo correctamente.

10. Prueba A/B de los dos modelos

Finalmente, podemos usar el comportamiento de prueba A/B integrado de Firebase para ver cuál de nuestros dos modelos funciona mejor. Vaya a Analytics -> Eventos en la consola de Firebase. Si se muestra el evento correct_inference , márquelo como un "evento de conversión". De lo contrario, puede ir a Analytics -> Eventos de conversión y hacer clic en "Crear un nuevo evento de conversión" y colocar correct_inference.

Ahora vaya a "Configuración remota en la consola de Firebase, seleccione el botón "Prueba A/B" en el menú de más opciones en el parámetro "nombre_del_modelo" que acabamos de agregar.

fad5ea36969d2aeb.png

En el menú que sigue, acepte el nombre predeterminado.

d7c006669ace6e40.png

Seleccione su aplicación en el menú desplegable y cambie los criterios de orientación al 50 % de los usuarios activos.

6246dd7c660b53fb.png

Si pudo configurar el evento correct_inference como una conversión anteriormente, use este evento como la métrica principal para realizar un seguimiento. De lo contrario, si no desea esperar a que aparezca el evento en Analytics, puede agregar correct_inference manualmente.

1ac9c94fb3159271.png

Finalmente, en la pantalla Variantes, configure su variante de grupo de control para usar mnist_v1 y su grupo Variante A para usar mnist_v2 .

e4510434f8da31b6.png

Haga clic en el botón Revisar en la esquina inferior derecha.

¡Felicitaciones, ha creado con éxito una prueba A/B para sus dos modelos separados! La prueba A/B se encuentra actualmente en estado de borrador y se puede iniciar en cualquier momento haciendo clic en el botón "Iniciar experimento".

Para ver más de cerca las pruebas A/B, consulte la documentación de las pruebas A/B .

11. Conclusión

En este laboratorio de código, aprendió a reemplazar un activo tflite empaquetado estáticamente en su aplicación con un modelo TFLite cargado dinámicamente de Firebase. Para obtener más información sobre TFLite y Firebase, eche un vistazo a otras muestras de TFLite y las guías de inicio de Firebase.

¿Tengo una pregunta?

Informar problemas