Добавьте Firebase в свое iOS-приложение на базе TFLite

1. Обзор

Цели

Firebase ML позволяет вам развертывать вашу модель по беспроводной сети. Это позволяет вам сохранять размер приложения небольшим и загружать модель машинного обучения только при необходимости, экспериментировать с несколькими моделями или обновлять модель машинного обучения без необходимости повторной публикации всего приложения.

В этой лаборатории кода вы преобразуете приложение iOS, использующее статическую модель TFLite, в приложение, использующее модель, динамически обслуживаемую из Firebase. Вы узнаете, как:

  1. Разверните модели TFLite в Firebase ML и получите к ним доступ из своего приложения.
  2. Регистрируйте метрики, связанные с моделью, с помощью Analytics
  3. Выберите, какая модель загружается через Remote Config.
  4. A/B-тестирование разных моделей

Предварительные условия

Перед запуском этой лаборатории убедитесь, что у вас установлены:

  • Xcode 11 (или выше)
  • CocoaPods 1.9.1 (или выше)

2. Создайте консольный проект Firebase.

Добавьте Firebase в проект

  1. Перейдите в консоль Firebase .
  2. Выберите «Создать новый проект» и назовите свой проект «Firebase ML iOS Codelab».

3. Получите образец проекта

Загрузите код

Начните с клонирования примера проекта и запуска pod update в каталоге проекта:

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

Если у вас не установлен git, вы также можете скачать пример проекта со страницы GitHub или нажав на эту ссылку . Загрузив проект, запустите его в Xcode и поиграйтесь с классификатором цифр, чтобы понять, как он работает.

Настройте Firebase

Следуйте документации , чтобы создать новый проект Firebase. Получив проект, загрузите файл GoogleService-Info.plist вашего проекта из консоли Firebase и перетащите его в корень проекта Xcode.

f06cb08d48de7e10.png

Добавьте Firebase в свой подфайл и запустите установку модуля.

pod 'FirebaseMLModelDownloader', '9.3.0-beta'

В методе didFinishLaunchingWithOptions вашего AppDelegate импортируйте Firebase в верхней части файла.

import FirebaseCore

И добавьте вызов для настройки Firebase.

FirebaseApp.configure()

Запустите проект еще раз, чтобы убедиться, что приложение настроено правильно и не происходит сбой при запуске.

4. Разверните модель в Firebase ML.

Развертывание модели в Firebase ML полезно по двум основным причинам:

  1. Мы можем сохранить размер установки приложения небольшим и загружать модель только при необходимости.
  2. Модель может обновляться регулярно и с другим циклом выпуска, чем все приложение.

Прежде чем мы сможем заменить статическую модель в нашем приложении динамически загруженной моделью из Firebase, нам необходимо развернуть ее в Firebase ML. Модель можно развернуть либо через консоль, либо программно с помощью Firebase Admin SDK. На этом этапе мы выполним развертывание через консоль.

Для простоты мы будем использовать модель TensorFlow Lite, которая уже есть в нашем приложении. Сначала откройте Firebase и нажмите «Машинное обучение» на левой навигационной панели. Затем перейдите к «Пользовательский» и нажмите кнопку «Добавить модель».

При появлении запроса дайте модели описательное имя, например mnist_v1 , и загрузите файл из каталога проекта codelab.

3c3c50e6ef12b3b.png

5. Загрузите модель из Firebase ML.

Выбор времени загрузки удаленной модели из Firebase в ваше приложение может оказаться непростым делом, поскольку модели TFLite могут вырасти относительно большими. В идеале мы хотим избежать загрузки модели сразу при запуске приложения, поскольку, если наша модель используется только для одной функции, а пользователь никогда не использует эту функцию, мы без причины загрузим значительный объем данных. Мы также можем установить параметры загрузки, например, загрузку моделей только при подключении к Wi-Fi. Если вы хотите быть уверенным, что модель доступна даже без подключения к сети, вам также следует включить ее в состав приложения в качестве резервной копии.

Для простоты мы удалим связанную модель по умолчанию и всегда будем загружать модель из Firebase при запуске приложения. Таким образом, при запуске распознавания цифр вы можете быть уверены, что вывод выполняется с использованием модели, предоставленной Firebase.

В верхней части ModelLoader.swift импортируйте модуль Firebase.

import FirebaseCore
import FirebaseMLModelDownloader

Затем реализуйте следующий метод.

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

В ViewController.swift viewDidLoad замените вызов инициализации DigitClassifier нашим новым методом загрузки модели.

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

Перезапустите приложение. Через несколько секунд вы должны увидеть журнал в Xcode, указывающий, что удаленная модель успешно загружена. Попробуйте нарисовать цифру и убедитесь, что поведение приложения не изменилось.

6. Отслеживайте отзывы пользователей и конверсии, чтобы измерить точность модели.

Мы будем измерять точность модели, отслеживая отзывы пользователей о прогнозах модели. Если пользователь нажмет «да», это будет означать, что прогноз оказался точным.

Мы можем зарегистрировать событие Analytics, чтобы отслеживать точность нашей модели. Во-первых, мы должны добавить аналитику в подфайл, прежде чем его можно будет использовать в проекте:

pod 'FirebaseAnalytics'

Затем в ViewController.swift импортируйте Firebase в верхней части файла.

import FirebaseAnalytics

И добавьте следующую строку кода в метод correctButtonPressed .

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

Запустите приложение еще раз и нарисуйте цифру. Нажмите кнопку «Да» несколько раз, чтобы сообщить, что вывод верен.

Отладочная аналитика

Обычно события, регистрируемые вашим приложением, группируются в течение примерно одного часа и загружаются вместе. Такой подход экономит заряд батареи на устройствах конечных пользователей и снижает использование сетевых данных. Однако в целях проверки реализации аналитики (и для просмотра аналитики в отчете DebugView) вы можете включить режим отладки на своем устройстве разработки, чтобы загружать события с минимальной задержкой.

Чтобы включить режим отладки Analytics на вашем устройстве разработки, укажите следующий аргумент командной строки в Xcode:

-FIRDebugEnabled

Запустите приложение еще раз и нарисуйте цифру. Нажмите кнопку «Да» несколько раз, чтобы сообщить, что вывод верен. Теперь вы можете просматривать события журнала практически в реальном времени через представление отладки в консоли Firebase. Нажмите Аналитика > DebugView на левой панели навигации.

5276199a086721fd.png

7. Отслеживайте время вывода с помощью Firebase Performance.

При тестировании вашей модели показателей производительности, полученных на устройствах разработки, недостаточно, чтобы понять, как модель будет работать в руках ваших пользователей, поскольку трудно сказать, на каком оборудовании пользователи будут запускать ваше приложение. К счастью, вы можете измерить производительность вашей модели на устройствах пользователей с помощью Firebase Performance, чтобы получить более полное представление о производительности вашей модели.

Чтобы измерить время, необходимое для выполнения вывода, сначала импортируйте Firebase в DigitClassifier.swift:

import FirebasePerformance

Затем запустите трассировку производительности в методе classify и остановите трассировку после завершения вывода. Обязательно добавьте следующие строки кода внутри закрытия DispatchQueue.global.async, а не непосредственно под объявлением метода.

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

Если вам интересно, вы можете включить ведение журнала отладки, следуя инструкциям здесь , чтобы убедиться, что ваши трассировки производительности записываются. Через некоторое время трассировка производительности также будет видна в консоли Firebase.

8. Разверните вторую модель в Firebase ML.

При разработке новой версии вашей модели, например, с лучшей архитектурой модели или версии, обученной на более крупном или обновленном наборе данных, у нас может возникнуть соблазн заменить текущую модель новой версией. Однако модель, хорошо зарекомендовавшая себя в тестировании, не обязательно будет так же хорошо работать в производстве. Поэтому давайте проведем A/B-тестирование в производстве, чтобы сравнить нашу исходную модель и новую.

Включить API управления моделями Firebase

На этом этапе мы включим API управления моделями Firebase для развертывания новой версии нашей модели TensorFlow Lite с использованием кода Python.

Создайте корзину для хранения моделей машинного обучения.

В консоли Firebase перейдите в раздел «Хранилище» и нажмите «Начать». fbbea78f0eb3dc9f.png

Следуйте диалогу, чтобы настроить ведро.

19517c0d6d2aa14d.png

Включить API Firebase ML

Перейдите на страницу Firebase ML API в Google Cloud Console и нажмите «Включить».

2414fd5cced6c984.png Когда вас спросят, выберите приложение «Классификатор цифр».

Теперь мы обучим новую версию модели, используя больший набор данных, а затем развернем ее программно прямо из учебного блокнота с помощью Firebase Admin SDK.

Скачать закрытый ключ для сервисного аккаунта

Прежде чем мы сможем использовать Firebase Admin SDK, нам необходимо создать сервисную учетную запись. Откройте панель «Учетные записи служб» консоли Firebase, щелкнув эту ссылку , и нажмите кнопку, чтобы создать новую учетную запись службы для Firebase Admin SDK. При появлении запроса нажмите кнопку «Создать новый закрытый ключ». Мы будем использовать ключ служебной учетной записи для аутентификации наших запросов из блокнота Colab.

c3b95de1e5508516.png

Теперь мы можем обучить и развернуть новую модель.

  1. Откройте этот блокнот Colab и скопируйте его на свой Диск.
  2. Запустите первую ячейку «Обучение улучшенной модели TensorFlow Lite», нажав кнопку воспроизведения слева от нее. Это обучит новую модель и может занять некоторое время.
  3. Запуск второй ячейки создаст запрос на загрузку файла. Загрузите файл JSON, который вы скачали из консоли Firebase при создании учетной записи службы.

71e847c6a85423b3.png

  1. Запустите последние две ячейки.

После запуска блокнота Colab вы должны увидеть вторую модель в консоли Firebase. Убедитесь, что вторая модель называется mnist_v2 .

c316683bb4d75d57.png

9. Выберите модель через Remote Config.

Теперь, когда у нас есть две отдельные модели, мы добавим параметр для выбора модели для загрузки во время выполнения. Значение параметра, который получает клиент, будет определять, какую модель он загрузит. Сначала откройте консоль Firebase и нажмите кнопку Remote Config в левом навигационном меню. Затем нажмите кнопку «Добавить параметр».

Назовите новый параметр model_name и присвойте ему значение по умолчанию mnist_v1 . Нажмите «Опубликовать изменения» , чтобы применить обновления. Указав имя модели в параметре удаленной конфигурации, мы можем протестировать несколько моделей, не добавляя новый параметр для каждой модели, которую мы хотим протестировать.

После добавления параметра вы должны увидеть его в консоли:

699b3fd32acce887.png

В нашем коде нам нужно будет добавить проверку при загрузке удаленной модели. Когда мы получим параметр от Remote Config, мы получим удаленную модель с соответствующим именем; в противном случае мы попытаемся загрузить mnist_v1 . Прежде чем мы сможем использовать Remote Config, нам нужно добавить его в наш проект, указав его как зависимость в подфайле:

pod 'FirebaseRemoteConfig'

Запустите установку модуля и повторно откройте проект Xcode. В ModelLoader.swift реализуйте метод 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)
    }
  }
}

Наконец, в ViewController.swift замените вызов downloadModel новым методом, который мы только что реализовали.

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

Перезапустите приложение и убедитесь, что оно по-прежнему правильно загружает модель.

10. A/B-тестирование двух моделей

Наконец, мы можем использовать встроенное в Firebase поведение A/B-тестирования, чтобы увидеть, какая из двух наших моделей работает лучше. Перейдите в Аналитика -> События в консоли Firebase. Если отображается событие correct_inference , отметьте его как «Событие-конверсия», если нет, вы можете перейти в «Аналитика» -> «События-конверсии», нажать «Создать новое событие-конверсию» и проставить correct_inference.

Теперь перейдите в «Удаленная настройка» в консоли Firebase, выберите кнопку «A/B-тест» в меню дополнительных параметров для только что добавленного параметра «имя_модели».

fad5ea36969d2aeb.png

В следующем меню примите имя по умолчанию.

d7c006669ace6e40.png

Выберите свое приложение в раскрывающемся списке и измените критерии таргетинга на 50 % активных пользователей.

6246dd7c660b53fb.png

Если ранее вам удалось установить событие correct_inference в качестве конверсии, используйте это событие в качестве основного показателя для отслеживания. В противном случае, если вы не хотите ждать, пока событие отобразится в Analytics, вы можете добавить correct_inference вручную.

1ac9c94fb3159271.png

Наконец, на экране «Варианты» установите для варианта контрольной группы использование mnist_v1 , а для группы варианта A — использование mnist_v2 .

e4510434f8da31b6.png

Нажмите кнопку «Просмотреть» в правом нижнем углу.

Поздравляем, вы успешно создали A/B-тест для двух отдельных моделей! A/B-тест в настоящее время находится в состоянии черновика, и его можно запустить в любой момент, нажав кнопку «Начать эксперимент».

Более подробную информацию об A/B-тестировании можно найти в документации по A/B-тестированию .

11. Заключение

В этой лабораторной работе вы узнали, как заменить статически связанный ресурс tflite в вашем приложении динамически загружаемой моделью TFLite из Firebase. Чтобы узнать больше о TFLite и Firebase, ознакомьтесь с другими примерами TFLite и руководствами по началу работы с Firebase.

Есть вопрос?

Сообщить о проблемах