1。概要
目標
Firebase ML を使用すると、モデルを無線でデプロイできます。これにより、アプリのサイズを小さく保ち、必要な場合にのみ ML モデルをダウンロードしたり、複数のモデルを試したり、アプリ全体を再公開することなく ML モデルを更新したりすることができます。
このコードラボでは、静的な TFLite モデルを使用する iOS アプリを、Firebase から動的に提供されるモデルを使用するアプリに変換します。次の方法を学習します:
- TFLite モデルを Firebase ML にデプロイし、アプリからアクセスする
- Analytics を使用してモデル関連のメトリクスをログに記録する
- Remote Config を通じてロードされるモデルを選択します
- さまざまなモデルの A/B テスト
前提条件
このコードラボを開始する前に、以下がインストールされていることを確認してください。
- Xcode 11 (またはそれ以降)
- CocoaPods 1.9.1 (またはそれ以降)
2. Firebaseコンソールプロジェクトを作成する
Firebaseをプロジェクトに追加する
- Firebase コンソールに移動します。
- [新しいプロジェクトの作成]を選択し、プロジェクトに「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 プロジェクトのルートにドラッグします。
Firebase を Podfile に追加し、pod install を実行します。
pod 'FirebaseMLModelDownloader', '9.3.0-beta'
AppDelegate
のdidFinishLaunchingWithOptions
メソッドで、ファイルの先頭に Firebase をインポートします。
import FirebaseCore
そして、Firebase を設定するための呼び出しを追加します。
FirebaseApp.configure()
プロジェクトを再度実行して、アプリが正しく構成されており、起動時にクラッシュしないことを確認します。
4. モデルを Firebase ML にデプロイする
モデルを Firebase ML にデプロイすると、主に次の 2 つの理由で役立ちます。
- アプリのインストール サイズを小さく保ち、必要な場合にのみモデルをダウンロードできます。
- モデルは定期的に更新でき、アプリ全体とは異なるリリース サイクルで更新できます。
アプリ内の静的モデルを Firebase から動的にダウンロードしたモデルに置き換える前に、それを Firebase ML にデプロイする必要があります。モデルは、コンソール経由で、または Firebase Admin SDK を使用してプログラムでデプロイできます。このステップでは、コンソール経由でデプロイします。
物事を簡単にするために、アプリにすでに含まれている TensorFlow Lite モデルを使用します。まず、Firebase を開き、左側のナビゲーション パネルで [Machine Learning] をクリックします。次に、「カスタム」に移動し、「モデルの追加」ボタンをクリックします。
プロンプトが表示されたら、モデルにmnist_v1
のようなわかりやすい名前を付け、コードラボ プロジェクト ディレクトリからファイルをアップロードします。
5. Firebase ML からモデルをダウンロードする
TFLite モデルは比較的大きくなる可能性があるため、Firebase からアプリにリモート モデルをいつダウンロードするかを選択するのは難しい場合があります。理想的には、アプリの起動時にすぐにモデルをロードすることは避けたいと考えています。モデルが 1 つの機能のみに使用され、ユーザーがその機能をまったく使用しない場合、理由もなく大量のデータがダウンロードされることになるからです。 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 イベントをログに記録して、モデルの精度を追跡できます。まず、プロジェクトで使用する前に、Analytics を Podfile に追加する必要があります。
pod 'FirebaseAnalytics'
次にViewController.swift
で、ファイルの先頭に Firebase をインポートします
import FirebaseAnalytics
そして、 correctButtonPressed
メソッドに次のコード行を追加します。
Analytics.logEvent("correct_inference", parameters: nil)
アプリを再度実行し、数字を描画します。 「はい」ボタンを数回押して、推論が正確であるというフィードバックを送信します。
デバッグ分析
通常、アプリによって記録されたイベントは、約 1 時間にわたってまとめられ、一緒にアップロードされます。このアプローチにより、エンド ユーザーのデバイスのバッテリーが節約され、ネットワーク データの使用量が削減されます。ただし、分析の実装を検証する目的 (および DebugView レポートで分析を表示するため) を目的として、開発デバイスでデバッグ モードを有効にして、最小限の遅延でイベントをアップロードできます。
開発デバイスで Analytics デバッグ モードを有効にするには、Xcode で次のコマンド ライン引数を指定します。
-FIRDebugEnabled
アプリを再度実行し、数字を描画します。 「はい」ボタンを数回押して、推論が正確であるというフィードバックを送信します。 Firebase コンソールのデバッグ ビューを介して、ほぼリアルタイムでログ イベントを表示できるようになりました。左側のナビゲーション バーから [Analytics] > [DebugView] をクリックします。
7. Firebase Performance で推論時間を追跡する
モデルをテストする場合、ユーザーがどのハードウェアでアプリを実行するかを知るのは難しいため、開発デバイスで作成されたパフォーマンス メトリックだけでは、モデルがユーザーの手に渡ってどのように動作するかを把握するのに十分ではありません。幸いなことに、Firebase Performance を使用してユーザーのデバイスでモデルのパフォーマンスを測定し、モデルのパフォーマンスをより正確に把握できます。
推論の実行にかかる時間を測定するには、まず DigitClassifier.swift に Firebase をインポートします。
import FirebasePerformance
次に、classify メソッドでパフォーマンス トレースを開始し、推論が完了したらトレースを停止します。次のコード行を、メソッド宣言の直下ではなく、DispatchQueue.global.async クロージャー内に追加してください。
let inferenceTrace = Performance.startTrace(name: "tflite inference") defer { inferenceTrace?.stop() }
興味がある場合は、ここの手順に従ってデバッグ ログを有効にして、パフォーマンス トレースがログに記録されていることを確認できます。しばらくすると、パフォーマンス トレースが Firebase コンソールにも表示されるようになります。
8. 2 番目のモデルを Firebase ML にデプロイする
より優れたモデル アーキテクチャを備えたモデルや、より大規模なデータセットまたは更新されたデータセットでトレーニングされたモデルなど、モデルの新しいバージョンを思いついたとき、現在のモデルを新しいバージョンに置き換えたくなるかもしれません。ただし、テストで良好なパフォーマンスを発揮したモデルが、本番環境でも同様に良好なパフォーマンスを発揮するとは限りません。したがって、本番環境で A/B テストを実行して、元のモデルと新しいモデルを比較してみましょう。
Firebase モデル管理 API を有効にする
このステップでは、Firebase Model Management API を有効にして、Python コードを使用して TensorFlow Lite モデルの新しいバージョンをデプロイします。
ML モデルを保存するバケットを作成する
Firebase コンソールで、[ストレージ] に移動し、[開始する] をクリックします。
ダイアログに従ってバケットを設定します。
Firebase ML API を有効にする
Google Cloud Console のFirebase ML API ページに移動し、[有効にする] をクリックします。
尋ねられたら、Digit Classifier アプリを選択します。
次に、より大きなデータセットを使用して新しいバージョンのモデルをトレーニングし、Firebase Admin SDK を使用してトレーニング ノートブックからプログラムで直接デプロイします。
サービスアカウントの秘密キーをダウンロードする
Firebase Admin SDK を使用する前に、サービス アカウントを作成する必要があります。このリンクをクリックして Firebase コンソールの [サービス アカウント] パネルを開き、ボタンをクリックして Firebase Admin SDK の新しいサービス アカウントを作成します。プロンプトが表示されたら、「新しい秘密キーを生成」ボタンをクリックします。 colab ノートブックからのリクエストを認証するためにサービス アカウント キーを使用します。
これで、新しいモデルをトレーニングしてデプロイできるようになりました。
- このcolab ノートブックを開いて、自分のドライブにコピーを作成します。
- 最初のセル「改良された TensorFlow Lite モデルのトレーニング」の左側にある再生ボタンをクリックして実行します。これにより新しいモデルがトレーニングされるため、時間がかかる場合があります。
- 2 番目のセルを実行すると、ファイルのアップロード プロンプトが作成されます。サービス アカウントの作成時に Firebase コンソールからダウンロードした json ファイルをアップロードします。
- 最後の 2 つのセルを実行します。
colab ノートブックを実行すると、Firebase コンソールに 2 番目のモデルが表示されるはずです。 2 番目のモデルの名前がmnist_v2
であることを確認します。
9. Remote Config でモデルを選択します
2 つの別々のモデルができたので、実行時にどちらのモデルをダウンロードするかを選択するためのパラメーターを追加します。クライアントが受け取るパラメータの値によって、クライアントがダウンロードするモデルが決まります。まず、Firebase コンソールを開き、左側のナビゲーション メニューにある [Remote Config] ボタンをクリックします。次に、「パラメータの追加」ボタンをクリックします。
新しいパラメーターにmodel_name
という名前を付け、デフォルト値のmnist_v1
を指定します。 「変更の公開」をクリックして更新を適用します。モデルの名前をリモート構成パラメーターに入れることで、テストしたいモデルごとに新しいパラメーターを追加することなく、複数のモデルをテストできます。
パラメータを追加すると、コンソールにパラメータが表示されます。
私たちのコードでは、リモート モデルをロードするときにチェックを追加する必要があります。 Remote Config からパラメータを受け取ると、対応する名前のリモート モデルを取得します。それ以外の場合は、 mnist_v1
をロードしようとします。 Remote Config を使用する前に、Podfile で依存関係として指定してプロジェクトに追加する必要があります。
pod 'FirebaseRemoteConfig'
pod install を実行し、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. 2 つのモデルの A/B テスト
最後に、Firebase の組み込み A/B テスト動作を使用して、2 つのモデルのどちらのパフォーマンスが優れているかを確認できます。 Firebase コンソールで [分析] -> [イベント] に移動します。 correct_inference
イベントが表示されている場合は、「コンバージョン イベント」としてマークします。表示されていない場合は、「分析」→「コンバージョン イベント」に移動し、「新しいコンバージョン イベントの作成」をクリックして、 correct_inference.
次に、Firebase コンソールの「Remote Config」に移動し、先ほど追加した「model_name」パラメータのその他のオプション メニューから「A/B テスト」ボタンを選択します。
続くメニューでは、デフォルトの名前を受け入れます。
ドロップダウンでアプリを選択し、ターゲティング基準をアクティブ ユーザーの 50% に変更します。
以前にcorrect_inference
イベントをコンバージョンとして設定できた場合は、このイベントを追跡する主要な指標として使用します。それ以外の場合、Analytics にイベントが表示されるまで待ちたくない場合は、 correct_inference
手動で追加できます。
最後に、[バリアント]画面で、コントロール グループのバリアントがmnist_v1
を使用するように設定し、バリアント A グループがmnist_v2
を使用するように設定します。
右下隅にある「レビュー」ボタンをクリックします。
おめでとうございます。2 つの異なるモデルの A/B テストが正常に作成されました。 A/B テストは現在ドラフト状態にあり、[実験を開始] ボタンをクリックすることでいつでも開始できます。
A/B テストの詳細については、 A/B テストのドキュメントを参照してください。
11. 結論
このコードラボでは、アプリ内の静的にバンドルされた tflite アセットを、Firebase から動的にロードされた TFLite モデルに置き換える方法を学習しました。 TFLite と Firebase について詳しくは、他の TFLite サンプルと Firebase スタート ガイドをご覧ください。