Adicione o Firebase ao seu aplicativo iOS com tecnologia TFLite

1. Visão Geral

Metas

O Firebase ML permite implantar seu modelo over-the-air. Isso permite que você mantenha o tamanho do aplicativo pequeno e baixe o modelo de ML apenas quando necessário, experimente vários modelos ou atualize seu modelo de ML sem precisar republicar o aplicativo inteiro.

Neste codelab, você converterá um app iOS usando um modelo TFLite estático em um app usando um modelo veiculado dinamicamente pelo Firebase. Você vai aprender como:

  1. Implante modelos TFLite no Firebase ML e acesse-os no seu aplicativo
  2. Registrar métricas relacionadas ao modelo com o Analytics
  3. Selecione qual modelo será carregado por meio do Configuração remota
  4. Teste A/B em diferentes modelos

Pré-requisitos

Antes de iniciar este codelab, verifique se você instalou:

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

2. Crie um projeto de console do Firebase

Adicione o Firebase ao projeto

  1. Vá para o console do Firebase .
  2. Selecione Criar novo projeto e nomeie seu projeto como "Firebase ML iOS Codelab".

3. Obtenha o projeto de amostra

Baixe o código

Comece clonando o projeto de amostra e executando pod update no diretório do projeto:

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

Se você não tiver o git instalado, também poderá baixar o projeto de amostra na página do GitHub ou clicando neste link . Depois de baixar o projeto, execute-o no Xcode e experimente o classificador de dígitos para ter uma ideia de como ele funciona.

Configurar o Firebase

Siga a documentação para criar um novo projeto Firebase. Depois de obter seu projeto, baixe o arquivo GoogleService-Info.plist do console do Firebase e arraste-o para a raiz do projeto Xcode.

f06cb08d48de7e10.png

Adicione o Firebase ao seu Podfile e execute pod install.

pod 'FirebaseMLModelDownloader', '9.3.0-beta'

No método didFinishLaunchingWithOptions do seu AppDelegate , importe o Firebase na parte superior do arquivo

import FirebaseCore

E adicione uma chamada para configurar o Firebase.

FirebaseApp.configure()

Execute o projeto novamente para garantir que o aplicativo esteja configurado corretamente e não trave na inicialização.

4. Implante um modelo no Firebase ML

Implantar um modelo no Firebase ML é útil por dois motivos principais:

  1. Podemos manter o tamanho de instalação do aplicativo pequeno e baixar o modelo apenas se necessário
  2. O modelo pode ser atualizado regularmente e com um ciclo de lançamento diferente de todo o aplicativo

Antes de podermos substituir o modelo estático em nosso aplicativo por um modelo baixado dinamicamente do Firebase, precisamos implantá-lo no Firebase ML. O modelo pode ser implantado por meio do console ou de forma programática, usando o SDK Admin do Firebase. Nesta etapa iremos implantar por meio do console.

Para simplificar, usaremos o modelo TensorFlow Lite que já está em nosso aplicativo. Primeiro, abra o Firebase e clique em Machine Learning no painel de navegação esquerdo. Em seguida, navegue até “Personalizado” e clique no botão “Adicionar modelo”.

Quando solicitado, dê ao modelo um nome descritivo como mnist_v1 e faça upload do arquivo do diretório do projeto codelab.

3c3c50e6ef12b3b.png

5. Baixe o modelo do Firebase ML

Escolher quando fazer download do modelo remoto do Firebase para seu aplicativo pode ser complicado, pois os modelos TFLite podem crescer relativamente grandes. Idealmente, queremos evitar o carregamento do modelo imediatamente quando o aplicativo é iniciado, pois se nosso modelo for usado para apenas um recurso e o usuário nunca usar esse recurso, teremos baixado uma quantidade significativa de dados sem motivo. Também podemos definir opções de download, como buscar apenas modelos quando conectado ao wifi. Se quiser garantir que o modelo esteja disponível mesmo sem uma conexão de rede, você também deve agrupar o modelo como parte do aplicativo como backup.

Para simplificar, removeremos o modelo empacotado padrão e sempre baixaremos um modelo do Firebase quando o aplicativo for iniciado. Dessa forma, ao executar o reconhecimento de dígitos, você pode ter certeza de que a inferência está sendo executada com o modelo fornecido pelo Firebase.

Na parte superior de ModelLoader.swift , importe o módulo Firebase.

import FirebaseCore
import FirebaseMLModelDownloader

Em seguida, implemente o seguinte 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))
          }
  }
}

No viewDidLoad de ViewController.swift , substitua a chamada de inicialização DigitClassifier pelo nosso novo método de download 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."
        }
      }
    }

Execute novamente seu aplicativo. Após alguns segundos, você deverá ver um log no Xcode indicando que o modelo remoto foi baixado com sucesso. Tente desenhar um dígito e confirme se o comportamento do aplicativo não mudou.

6. Acompanhe o feedback do usuário e a conversão para medir a precisão do modelo

Mediremos a precisão do modelo rastreando o feedback do usuário sobre as previsões do modelo. Se um usuário clicar em “sim”, isso indicará que a previsão foi precisa.

Podemos registrar um evento do Analytics para rastrear a precisão do nosso modelo. Primeiro, devemos adicionar o Analytics ao Podfile antes que ele possa ser usado no projeto:

pod 'FirebaseAnalytics'

Em seguida, em ViewController.swift importe o Firebase na parte superior do arquivo

import FirebaseAnalytics

E adicione a seguinte linha de código no método correctButtonPressed .

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

Execute o aplicativo novamente e desenhe um dígito. Pressione o botão “Sim” algumas vezes para enviar um feedback de que a inferência foi precisa.

Análise de depuração

Geralmente, os eventos registrados pelo seu aplicativo são agrupados em lote durante um período de aproximadamente uma hora e carregados juntos. Essa abordagem conserva a bateria dos dispositivos dos usuários finais e reduz o uso de dados da rede. No entanto, para fins de validação de sua implementação de análise (e para visualizar suas análises no relatório DebugView), você pode ativar o modo de depuração em seu dispositivo de desenvolvimento para fazer upload de eventos com um atraso mínimo.

Para ativar o modo Analytics Debug em seu dispositivo de desenvolvimento, especifique o seguinte argumento de linha de comando no Xcode:

-FIRDebugEnabled

Execute o aplicativo novamente e desenhe um dígito. Pressione o botão “Sim” algumas vezes para enviar um feedback de que a inferência foi precisa. Agora você pode visualizar os eventos de registro quase em tempo real por meio da visualização de depuração no console do Firebase. Clique em Analytics > DebugView na barra de navegação esquerda.

5276199a086721fd.png

7. Acompanhe o tempo de inferência com o Firebase Performance

Ao testar seu modelo, as métricas de desempenho feitas em dispositivos de desenvolvimento não são suficientes para capturar o desempenho do modelo nas mãos dos usuários, pois é difícil dizer em qual hardware os usuários executarão seu aplicativo. Felizmente, você pode medir o desempenho do seu modelo nos dispositivos dos usuários com o Firebase Performance para ter uma ideia melhor do desempenho do seu modelo.

Para medir o tempo necessário para executar a inferência, primeiro importe o Firebase em DigitClassifier.swift:

import FirebasePerformance

Em seguida, inicie um rastreamento de desempenho no método de classificação e interrompa o rastreamento quando a inferência for concluída. Certifique-se de adicionar as seguintes linhas de código dentro do encerramento DispatchQueue.global.async e não diretamente abaixo da declaração do método.

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

Se estiver curioso, você pode ativar o log de depuração por meio das instruções aqui para confirmar se seus rastreamentos de desempenho estão sendo registrados. Depois de um tempo, os rastreamentos de desempenho também ficarão visíveis no Firebase Console.

8. Implante um segundo modelo no Firebase ML

Ao criar uma nova versão do seu modelo, como uma com uma arquitetura de modelo melhor ou treinada em um conjunto de dados maior ou atualizado, podemos nos sentir tentados a substituir nosso modelo atual pela nova versão. No entanto, um modelo com bom desempenho em testes não necessariamente tem um desempenho igualmente bom em produção. Portanto, vamos fazer testes A/B em produção para comparar nosso modelo original e o novo.

Ativar API de gerenciamento de modelos do Firebase

Nesta etapa, habilitaremos a API Firebase Model Management para implantar uma nova versão de nosso modelo TensorFlow Lite usando código Python.

Crie um bucket para armazenar seus modelos de ML

No Console do Firebase, acesse Armazenamento e clique em Primeiros passos. fbbea78f0eb3dc9f.png

Siga o diálogo para configurar seu balde.

19517c0d6d2aa14d.png

Ativar API Firebase ML

Acesse a página da API Firebase ML no Console do Google Cloud e clique em Ativar.

2414fd5cced6c984.png Selecione o aplicativo Digit Classifier quando solicitado.

Agora treinaremos uma nova versão do modelo usando um conjunto de dados maior e, em seguida, implantaremos programaticamente diretamente do notebook de treinamento usando o SDK Admin do Firebase.

Baixe a chave privada da conta de serviço

Antes de podermos usar o SDK Admin do Firebase, precisaremos criar uma conta de serviço. Abra o painel Contas de serviço do console do Firebase clicando neste link e clique no botão para criar uma nova conta de serviço para o SDK Admin do Firebase. Quando solicitado, clique no botão Gerar nova chave privada. Usaremos a chave da conta de serviço para autenticar nossas solicitações do notebook Colab.

c3b95de1e5508516.png

Agora podemos treinar e implantar o novo modelo.

  1. Abra este bloco de notas colab e faça uma cópia dele em seu próprio Drive.
  2. Execute a primeira célula "Treinar um modelo aprimorado do TensorFlow Lite" clicando no botão play à esquerda dela. Isso treinará um novo modelo e pode levar algum tempo.
  3. A execução da segunda célula criará um prompt de upload de arquivo. Faça upload do arquivo JSON que você baixou do Firebase Console ao criar sua conta de serviço.

71e847c6a85423b3.png

  1. Execute as duas últimas células.

Depois de executar o notebook colab, você deverá ver um segundo modelo no console do Firebase. Certifique-se de que o segundo modelo seja denominado mnist_v2 .

c316683bb4d75d57.png

9. Selecione um modelo via Configuração Remota

Agora que temos dois modelos separados, adicionaremos um parâmetro para selecionar qual modelo baixar em tempo de execução. O valor do parâmetro que o cliente recebe determinará qual modelo o cliente fará download. Primeiro, abra o console do Firebase e clique no botão Configuração remota no menu de navegação esquerdo. Em seguida, clique no botão “Adicionar Parâmetro”.

Nomeie o novo parâmetro model_name e atribua a ele um valor padrão de mnist_v1 . Clique em Publicar alterações para aplicar as atualizações. Ao colocar o nome do modelo no parâmetro de configuração remota, podemos testar vários modelos sem adicionar um novo parâmetro para cada modelo que queremos testar.

Depois de adicionar o parâmetro, você deverá vê-lo no Console:

699b3fd32acce887.png

Em nosso código, precisaremos adicionar uma verificação ao carregar o modelo remoto. Ao recebermos o parâmetro do Remote Config, buscaremos o modelo remoto com o nome correspondente; caso contrário, tentaremos carregar mnist_v1 . Antes de podermos usar o Configuração remota, precisamos adicioná-lo ao nosso projeto especificando-o como uma dependência no Podfile:

pod 'FirebaseRemoteConfig'

Execute pod install e reabra o projeto Xcode. Em ModelLoader.swift , implemente o 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, em ViewController.swift , substitua a chamada downloadModel pelo novo 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."
    }
  }
}

Execute novamente o aplicativo e certifique-se de que ele ainda carregue o modelo corretamente.

10. Teste A/B dos dois modelos

Por fim, podemos usar o comportamento de teste A/B integrado do Firebase para ver qual dos nossos dois modelos tem melhor desempenho. Vá para Analytics -> Eventos no console do Firebase. Se o evento correct_inference estiver aparecendo, marque-o como um "Evento de conversão", caso contrário, você pode ir em Analytics -> Eventos de conversão e clicar em "Criar um novo evento de conversão" e colocar correct_inference.

Agora vá para "Configuração remota no console do Firebase, selecione o botão "Teste A/B" no menu de mais opções no parâmetro "model_name" que acabamos de adicionar.

fad5ea36969d2aeb.png

No menu a seguir, aceite o nome padrão.

d7c006669ace6e40.png

Selecione seu aplicativo no menu suspenso e altere os critérios de segmentação para 50% de usuários ativos.

6246dd7c660b53fb.png

Se você conseguiu definir o evento correct_inference como uma conversão anteriormente, use esse evento como a métrica principal a ser rastreada. Caso contrário, se não quiser esperar o evento aparecer no Analytics, você pode adicionar correct_inference manualmente.

1ac9c94fb3159271.png

Por fim, na tela Variantes, defina sua variante de grupo de controle para usar mnist_v1 e seu grupo Variante A para usar mnist_v2 .

e4510434f8da31b6.png

Clique no botão Revisar no canto inferior direito.

Parabéns, você criou com sucesso um teste A/B para seus dois modelos separados! O teste A/B está atualmente em estado de rascunho e pode ser iniciado a qualquer momento clicando no botão "Iniciar experimento".

Para uma análise mais detalhada dos testes A/B, verifique a documentação de testes A/B .

11. Conclusão

Neste codelab, você aprendeu a substituir um recurso tflite empacotado estaticamente no seu app por um modelo TFLite carregado dinamicamente do Firebase. Para saber mais sobre o TFLite e o Firebase, dê uma olhada em outros exemplos do TFLite e nos guias de primeiros passos do Firebase.

Ter uma questão?

Relatar problemas